import { Session } from "better-auth";
import * as v from "valibot";

export type { Session } from "better-auth";

export type ModifiedSession = Session & { isCurrent?: boolean };

// User role enum
export enum UserRoleMap {
    user = "user",
    admin = "admin",
}

// User role schema
export const userRoleSchema = v.picklist(["user", "admin"]);
export type UserRole = v.InferOutput<typeof userRoleSchema>;

// User schema
export const userSchema = v.object({
    id: v.string(),
    name: v.string(),
    email: v.string(),
    emailVerified: v.boolean(),
    image: v.optional(v.string()),
    createdAt: v.date(),
    updatedAt: v.date(),
    username: v.optional(v.string()),
    displayUsername: v.optional(v.string()),
    role: v.optional(v.string()),
    banned: v.optional(v.boolean()),
    banReason: v.optional(v.string()),
    banExpires: v.optional(v.date()),
    onboardingDone: v.optional(v.boolean()),
    last2FAVerifiedAt: v.optional(v.date()),
    parentId: v.optional(v.string()),
});
export type User = v.InferOutput<typeof userSchema>;

// Account schema
export const accountSchema = v.object({
    id: v.string(),
    accountId: v.string(),
    providerId: v.string(),
    userId: v.string(),
    accessToken: v.string(),
    refreshToken: v.string(),
    idToken: v.string(),
    accessTokenExpiresAt: v.date(),
    refreshTokenExpiresAt: v.date(),
    scope: v.string(),
    password: v.string(),
    createdAt: v.date(),
    updatedAt: v.date(),
});
export type Account = v.InferOutput<typeof accountSchema>;

// Ensure account exists schema
export const ensureAccountExistsSchema = v.object({
    userId: v.string(),
});
export type EnsureAccountExists = v.InferOutput<
    typeof ensureAccountExistsSchema
>;

// Ban info schema
export const banInfoSchema = v.object({
    banned: v.boolean(),
    reason: v.optional(v.string()),
    expires: v.optional(v.date()),
});
export type BanInfo = v.InferOutput<typeof banInfoSchema>;

// Ban user schema
export const banUserSchema = v.object({
    userId: v.string(),
    reason: v.string(),
    banExpiresAt: v.date(),
});
export type BanUser = v.InferOutput<typeof banUserSchema>;

// Check username availability schema
export const checkUsernameSchema = v.object({
    username: v.string(),
});
export type CheckUsername = v.InferOutput<typeof checkUsernameSchema>;

// Rotate password schema
export const rotatePasswordSchema = v.object({
    userId: v.string(),
    password: v.string(),
});
export type RotatePassword = v.InferOutput<typeof rotatePasswordSchema>;

// View Model specific types

// Search and filter types
export const searchFieldSchema = v.picklist(["email", "name", "username"]);
export type SearchField = v.InferOutput<typeof searchFieldSchema>;

export const searchOperatorSchema = v.picklist([
    "contains",
    "starts_with",
    "ends_with",
]);
export type SearchOperator = v.InferOutput<typeof searchOperatorSchema>;

export const filterOperatorSchema = v.picklist([
    "eq",
    "ne",
    "lt",
    "lte",
    "gt",
    "gte",
]);
export type FilterOperator = v.InferOutput<typeof filterOperatorSchema>;

export const sortDirectionSchema = v.picklist(["asc", "desc"]);
export type SortDirection = v.InferOutput<typeof sortDirectionSchema>;

// Users query state
export const usersQueryStateSchema = v.object({
    // searching
    searchValue: v.optional(v.string()),
    searchField: v.optional(searchFieldSchema),
    searchOperator: v.optional(searchOperatorSchema),

    // pagination
    limit: v.pipe(v.number(), v.integer()),
    offset: v.pipe(v.number(), v.integer()),

    // sorting
    sortBy: v.optional(v.string()),
    sortDirection: v.optional(sortDirectionSchema),

    // filtering
    filterField: v.optional(v.string()),
    filterValue: v.optional(v.union([v.string(), v.number(), v.boolean()])),
    filterOperator: v.optional(filterOperatorSchema),
});
export type UsersQueryState = v.InferOutput<typeof usersQueryStateSchema>;

// UI View Model types

export const banExpiryModeSchema = v.picklist([
    "never",
    "1d",
    "7d",
    "30d",
    "custom",
]);
export type BanExpiryMode = v.InferOutput<typeof banExpiryModeSchema>;

export const createUserFormSchema = v.object({
    email: v.string(),
    password: v.string(),
    name: v.string(),
    role: v.union([userRoleSchema, v.array(userRoleSchema)]),
});
export type CreateUserForm = v.InferOutput<typeof createUserFormSchema>;
