import { sqliteTable, text, integer, customType as sqliteCustomType } from 'drizzle-orm/sqlite-core';
import {
  pgTable,
  uuid,
  varchar,
  text as pgText,
  timestamp,
  boolean as pgBoolean,
  bigint,
  customType as pgCustomType,
} from 'drizzle-orm/pg-core';

// Better Auth table definitions for both dialects.
//
// The `user` model maps onto the EXISTING `users` table so user IDs (and every
// foreign key that references them) survive the auth migration untouched. Only
// the columns Better Auth reads/writes are declared here; legacy columns
// (password, google_id, token_version) stay physically present but invisible
// to Better Auth. The full application-facing definition lives in schema.ts —
// two Drizzle table objects can safely describe the same SQL table.
const dbType = process.env.DB_TYPE || 'sqlite';

// Better Auth hands the adapter JS Date objects, but the legacy sqlite `users`
// timestamps are ISO-8601 TEXT columns. Bridge the two representations.
const isoText = sqliteCustomType<{ data: Date; driverData: string }>({
  dataType() {
    return 'text';
  },
  toDriver(value: Date): string {
    return (value instanceof Date ? value : new Date(value)).toISOString();
  },
  fromDriver(value: string): Date {
    return new Date(value);
  },
});

// Legacy pg `users.is_claimed` is an INTEGER 0/1 column; expose it as boolean.
const pgIntBool = pgCustomType<{ data: boolean; driverData: number }>({
  dataType() {
    return 'integer';
  },
  toDriver(value: boolean): number {
    return value ? 1 : 0;
  },
  fromDriver(value: number | boolean): boolean {
    return Boolean(value);
  },
});

// ==================== SQLite ====================

export const sqliteAuthUsers = sqliteTable('users', {
  id: text('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  emailVerified: integer('email_verified', { mode: 'boolean' }).notNull().default(false),
  image: text('image'),
  createdAt: isoText('created_at').notNull(),
  updatedAt: isoText('updated_at').notNull(),
  // admin plugin fields
  role: text('role').notNull().default('user'),
  banned: integer('banned', { mode: 'boolean' }).notNull().default(false),
  banReason: text('ban_reason'),
  banExpires: integer('ban_expires', { mode: 'timestamp_ms' }),
  // application additionalFields
  phone: text('phone'),
  languagePreference: text('language_preference'),
  rucNumber: text('ruc_number'),
  isClaimed: integer('is_claimed', { mode: 'boolean' }).notNull().default(true),
  accountStatus: text('account_status').notNull().default('active'),
});

export const sqliteAuthSessions = sqliteTable('auth_sessions', {
  id: text('id').primaryKey(),
  userId: text('user_id')
    .notNull()
    .references(() => sqliteAuthUsers.id, { onDelete: 'cascade' }),
  token: text('token').notNull().unique(),
  expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(),
  ipAddress: text('ip_address'),
  userAgent: text('user_agent'),
  // admin plugin (impersonation)
  impersonatedBy: text('impersonated_by'),
  createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
  updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),
});

export const sqliteAuthAccounts = sqliteTable('auth_accounts', {
  id: text('id').primaryKey(),
  userId: text('user_id')
    .notNull()
    .references(() => sqliteAuthUsers.id, { onDelete: 'cascade' }),
  accountId: text('account_id').notNull(),
  providerId: text('provider_id').notNull(),
  accessToken: text('access_token'),
  refreshToken: text('refresh_token'),
  idToken: text('id_token'),
  accessTokenExpiresAt: integer('access_token_expires_at', { mode: 'timestamp_ms' }),
  refreshTokenExpiresAt: integer('refresh_token_expires_at', { mode: 'timestamp_ms' }),
  scope: text('scope'),
  password: text('password'),
  createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
  updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),
});

export const sqliteAuthVerifications = sqliteTable('auth_verifications', {
  id: text('id').primaryKey(),
  identifier: text('identifier').notNull(),
  value: text('value').notNull(),
  expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(),
  createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
  updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),
});

export const sqliteAuthRateLimits = sqliteTable('auth_rate_limits', {
  id: text('id').primaryKey(),
  key: text('key'),
  count: integer('count'),
  lastRequest: integer('last_request'),
});

// ==================== PostgreSQL ====================

export const pgAuthUsers = pgTable('users', {
  id: uuid('id').primaryKey(),
  name: varchar('name', { length: 255 }).notNull(),
  email: varchar('email', { length: 255 }).notNull().unique(),
  emailVerified: pgBoolean('email_verified').notNull().default(false),
  image: pgText('image'),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
  // admin plugin fields
  role: varchar('role', { length: 20 }).notNull().default('user'),
  banned: pgBoolean('banned').notNull().default(false),
  banReason: pgText('ban_reason'),
  banExpires: timestamp('ban_expires'),
  // application additionalFields
  phone: varchar('phone', { length: 50 }),
  languagePreference: varchar('language_preference', { length: 10 }),
  rucNumber: varchar('ruc_number', { length: 15 }),
  isClaimed: pgIntBool('is_claimed').notNull(),
  accountStatus: varchar('account_status', { length: 20 }).notNull().default('active'),
});

export const pgAuthSessions = pgTable('auth_sessions', {
  id: uuid('id').primaryKey(),
  userId: uuid('user_id')
    .notNull()
    .references(() => pgAuthUsers.id, { onDelete: 'cascade' }),
  token: varchar('token', { length: 255 }).notNull().unique(),
  expiresAt: timestamp('expires_at').notNull(),
  ipAddress: varchar('ip_address', { length: 45 }),
  userAgent: pgText('user_agent'),
  // admin plugin (impersonation)
  impersonatedBy: uuid('impersonated_by'),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const pgAuthAccounts = pgTable('auth_accounts', {
  id: uuid('id').primaryKey(),
  userId: uuid('user_id')
    .notNull()
    .references(() => pgAuthUsers.id, { onDelete: 'cascade' }),
  accountId: varchar('account_id', { length: 255 }).notNull(),
  providerId: varchar('provider_id', { length: 100 }).notNull(),
  accessToken: pgText('access_token'),
  refreshToken: pgText('refresh_token'),
  idToken: pgText('id_token'),
  accessTokenExpiresAt: timestamp('access_token_expires_at'),
  refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
  scope: pgText('scope'),
  password: pgText('password'),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const pgAuthVerifications = pgTable('auth_verifications', {
  id: uuid('id').primaryKey(),
  identifier: varchar('identifier', { length: 255 }).notNull(),
  value: pgText('value').notNull(),
  expiresAt: timestamp('expires_at').notNull(),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const pgAuthRateLimits = pgTable('auth_rate_limits', {
  id: varchar('id', { length: 64 }).primaryKey(),
  key: varchar('key', { length: 255 }),
  count: bigint('count', { mode: 'number' }),
  lastRequest: bigint('last_request', { mode: 'number' }),
});

// ==================== Runtime-switched exports ====================

export const authUsers = dbType === 'postgres' ? pgAuthUsers : sqliteAuthUsers;
export const authSessions = dbType === 'postgres' ? pgAuthSessions : sqliteAuthSessions;
export const authAccounts = dbType === 'postgres' ? pgAuthAccounts : sqliteAuthAccounts;
export const authVerifications = dbType === 'postgres' ? pgAuthVerifications : sqliteAuthVerifications;
export const authRateLimits = dbType === 'postgres' ? pgAuthRateLimits : sqliteAuthRateLimits;
