import { pgTable, text, integer, bigint, boolean, unique, index, primaryKey, AnyPgColumn } from 'drizzle-orm/pg-core';
import { sql } from 'drizzle-orm';

export const ENTITIES = ['categories', 'tasks', 'subtasks', 'repeatProfiles', 'friendships'] as const;
export type EntityName = (typeof ENTITIES)[number];

export const users = pgTable('users', {
  id: text('id').primaryKey(),
  username: text('username').notNull().unique(),
  passwordHash: text('password_hash').notNull(),
  resetToken: text('reset_token'),
  resetTokenExpiry: bigint('reset_token_expiry', { mode: 'number' }),
  createdAt: bigint('created_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
});

export const friendships = pgTable(
  'friendships',
  {
    id: text('id').primaryKey(),
    userId: text('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
    friendId: text('friend_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
    status: text('status', { enum: ['pending', 'accepted'] }).notNull().default('pending'),
    createdAt: bigint('created_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
    updatedAt: bigint('updated_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
  },
  (t) => ({
    pairUnique: unique('friendships_pair').on(t.userId, t.friendId),
    userIdx: index('friendships_user_idx').on(t.userId),
    friendIdx: index('friendships_friend_idx').on(t.friendId),
  })
);

export const categories = pgTable('categories', {
  id: text('id').primaryKey(),
  userId: text('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
  name: text('name').notNull(),
  color: text('color').notNull(),
  order: integer('order').notNull().default(0),
  createdAt: bigint('created_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
  updatedAt: bigint('updated_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
});

export const tasks = pgTable('tasks', {
  id: text('id').primaryKey(),
  userId: text('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
  categoryId: text('category_id').references(() => categories.id, { onDelete: 'cascade' }),
  tags: text('tags').notNull().default(''),
  title: text('title').notNull(),
  description: text('description').notNull().default(''),
  priority: text('priority', { enum: ['none', 'low', 'medium', 'high', 'critical'] }).notNull().default('none'),
  completed: boolean('completed').notNull().default(false),
  dueDate: bigint('due_date', { mode: 'number' }).notNull().default(0),
  dueTime: text('due_time').notNull().default(''),
  endTime: text('end_time').notNull().default(''),
  allDay: boolean('all_day').notNull().default(false),
  repeat: text('repeat', { enum: ['none', 'daily', 'weekly', 'monthly', 'custom'] }).notNull().default('none'),
  repeatInterval: integer('repeat_interval').notNull().default(1),
  repeatDays: text('repeat_days').notNull().default(''),
  seriesId: text('series_id').notNull().default(''),
  assigneeId: text('assignee_id').references(() => users.id, { onDelete: 'set null' }),
  reminder: text('reminder', { enum: ['none', 'at_time', '15', '30', '60', '120', '1440'] }).notNull().default('none'),
  reminders: text('reminders').notNull().default(''),
  completedAt: bigint('completed_at', { mode: 'number' }),
  createdAt: bigint('created_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
  updatedAt: bigint('updated_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
});

export const tombstones = pgTable(
  'tombstones',
  {
    entity: text('entity', { enum: ENTITIES }).notNull(),
    entityId: text('entity_id').notNull(),
    userId: text('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
    updatedAt: bigint('updated_at', { mode: 'number' }).notNull(),
  },
  (t) => ({
    pk: primaryKey({ columns: [t.entity, t.entityId] }),
    userIdx: index('tombstones_user_updated_idx').on(t.userId, t.updatedAt),
  })
);

// Define subtasks with explicit type to avoid circular reference
export const subtasks = pgTable('subtasks', {
  id: text('id').primaryKey(),
  userId: text('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
  taskId: text('task_id').notNull().references(() => tasks.id, { onDelete: 'cascade' }),
  parentSubtaskId: text('parent_subtask_id').references((): AnyPgColumn => subtasks.id, { onDelete: 'cascade' }),
  categoryId: text('category_id').references(() => categories.id, { onDelete: 'set null' }),
  title: text('title').notNull(),
  description: text('description').notNull().default(''),
  priority: text('priority', { enum: ['none', 'low', 'medium', 'high', 'critical'] }).notNull().default('none'),
  completed: boolean('completed').notNull().default(false),
  dueDate: bigint('due_date', { mode: 'number' }).notNull().default(0),
  dueTime: text('due_time').notNull().default(''),
  endTime: text('end_time').notNull().default(''),
  allDay: boolean('all_day').notNull().default(false),
  repeat: text('repeat', { enum: ['none', 'daily', 'weekly', 'monthly', 'custom'] }).notNull().default('none'),
  repeatInterval: integer('repeat_interval').notNull().default(1),
  repeatDays: text('repeat_days').notNull().default(''),
  seriesId: text('series_id').notNull().default(''),
  reminder: text('reminder', { enum: ['none', 'at_time', '15', '30', '60', '120', '1440'] }).notNull().default('none'),
  reminders: text('reminders').notNull().default(''),
  assigneeId: text('assignee_id').references(() => users.id, { onDelete: 'set null' }),
  order: integer('order').notNull().default(0),
  createdAt: bigint('created_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
  updatedAt: bigint('updated_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
}, (t) => ({
  parentIdx: index('subtasks_parent_idx').on(t.parentSubtaskId),
  taskIdx: index('subtasks_task_idx').on(t.taskId),
  userIdx: index('subtasks_user_idx').on(t.userId),
}));

export const repeatProfiles = pgTable('repeat_profiles', {
  id: text('id').primaryKey(),
  userId: text('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
  name: text('name').notNull(),
  repeat: text('repeat', { enum: ['none', 'daily', 'weekly', 'monthly', 'custom'] }).notNull().default('none'),
  repeatInterval: integer('repeat_interval').notNull().default(1),
  repeatDays: text('repeat_days').notNull().default(''),
  createdAt: bigint('created_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
  updatedAt: bigint('updated_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
});

export const userSettings = pgTable('user_settings', {
  userId: text('user_id').primaryKey().references(() => users.id, { onDelete: 'cascade' }),
  darkMode: boolean('dark_mode').notNull().default(false),
  notifications: boolean('notifications').notNull().default(true),
  reminderTime: text('reminder_time').notNull().default('09:00'),
  defaultCategory: text('default_category'),
  sortBy: text('sort_by', { enum: ['dueDate', 'priority', 'title', 'createdAt'] }).notNull().default('dueDate'),
  sortOrder: text('sort_order', { enum: ['asc', 'desc'] }).notNull().default('asc'),
  updatedAt: bigint('updated_at', { mode: 'number' }).notNull().default(sql`EXTRACT(EPOCH FROM NOW()) * 1000`),
});
