import { sql } from "drizzle-orm";
import { pgTable, text, varchar, timestamp, integer, boolean, json } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";

export const users = pgTable("users", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  username: text("username").notNull().unique(),
  email: text("email").notNull().unique(), // Added email
  password: text("password").notNull(),
  role: text("role").notNull().default("user"), // 'admin' | 'user'
  isActive: boolean("is_active").notNull().default(true),
  xp: integer("xp").notNull().default(0),
  level: integer("level").notNull().default(1),
  currentStreak: integer("current_streak").notNull().default(0),
  lastTaskDate: timestamp("last_task_date"),
  showOnLeaderboard: boolean("show_on_leaderboard").notNull().default(false), // Privacy setting
  isSearchable: boolean("is_searchable").notNull().default(false), // Privacy setting
  apiKey: text("api_key"), // For MCP Server access
  aiEnabled: boolean("ai_enabled").notNull().default(true), // Feature flag per user
});

export const systemSettings = pgTable("system_settings", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  key: text("key").notNull().unique(), // e.g., 'registration_enabled'
  value: text("value").notNull(),      // e.g., 'true'
  updatedAt: timestamp("updated_at").defaultNow(),
});

export const labels = pgTable("labels", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: text("name").notNull(),
  color: text("color").notNull(),
  creatorId: varchar("creator_id").references(() => users.id), // Added creator ownership
});

export const sharedLabels = pgTable("shared_labels", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  labelId: varchar("label_id").references(() => labels.id).notNull(),
  sharedByUserId: varchar("shared_by_user_id").references(() => users.id).notNull(),
  sharedWithUserId: varchar("shared_with_user_id").references(() => users.id).notNull(),
  permission: text("permission").notNull().default("read"), // 'read' | 'write'
  createdAt: timestamp("created_at").defaultNow(),
});

export const tasks = pgTable("tasks", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  title: text("title").notNull(),
  description: text("description"),
  status: text("status").notNull().default("todo"), // 'todo' | 'inProgress' | 'done'
  priority: text("priority").notNull().default("medium"), // 'low' | 'medium' | 'high'
  dueDate: timestamp("due_date"),
  timeTracked: integer("time_tracked").notNull().default(0), // in minutes
  isTracking: boolean("is_tracking").notNull().default(false),
  projectId: text("project_id"),
  notes: text("notes"),
  labelId: varchar("label_id").references(() => labels.id),
  energyLevel: text("energy_level").default("medium"), // 'low' | 'medium' | 'high'
  estimatedDuration: integer("estimated_duration"), // in minutes
  parentTaskId: varchar("parent_task_id").references((): any => tasks.id), // Self-reference for subtasks
  startDate: timestamp("start_date"), // For multi-day tasks
  dependencies: text("dependencies").array(), // Array of task IDs
  userId: varchar("user_id").references(() => users.id), // Added for ownership
});

// Single Task Sharing
export const sharedTasks = pgTable("shared_tasks", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  taskId: varchar("task_id").references(() => tasks.id).notNull(),
  sharedByUserId: varchar("shared_by_user_id").references(() => users.id).notNull(),
  sharedWithUserId: varchar("shared_with_user_id").references(() => users.id).notNull(),
  createdAt: timestamp("created_at").defaultNow(),
});

// Global "Share All" Access
export const userTaskAccess = pgTable("user_task_access", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  ownerId: varchar("owner_id").references(() => users.id).notNull(),
  viewerId: varchar("viewer_id").references(() => users.id).notNull(),
  createdAt: timestamp("created_at").defaultNow(),
});

export const insertUserSchema = createInsertSchema(users).pick({
  username: true,
  password: true,
  email: true,
  showOnLeaderboard: true,
  isSearchable: true,
  aiEnabled: true,
});

export const registerSchema = insertUserSchema;

export const loginSchema = z.object({
  username: z.string().min(1, "Username is required"),
  password: z.string().min(1, "Password is required"),
  rememberMe: z.boolean().optional(),
});

export type LoginUser = z.infer<typeof loginSchema>;

export const insertSystemSettingsSchema = createInsertSchema(systemSettings).omit({
  id: true,
  updatedAt: true,
});

export const insertLabelSchema = createInsertSchema(labels).omit({
  id: true,
});

export const insertTaskSchema = createInsertSchema(tasks, {
  dueDate: z.coerce.date().nullable(),
  startDate: z.coerce.date().nullable(),
}).omit({
  id: true,
  userId: true, // We will set this server-side
});


// Schema exports for sharing
export const insertSharedTaskSchema = createInsertSchema(sharedTasks).omit({
  id: true,
  createdAt: true,
});

export const insertUserTaskAccessSchema = createInsertSchema(userTaskAccess).omit({
  id: true,
  createdAt: true,
});

export type InsertUser = z.infer<typeof insertUserSchema>;
export type User = typeof users.$inferSelect;
export type InsertSystemSettings = z.infer<typeof insertSystemSettingsSchema>;
export type SystemSettings = typeof systemSettings.$inferSelect;
export type InsertLabel = z.infer<typeof insertLabelSchema>;
export type Label = typeof labels.$inferSelect;
export type SharedLabel = typeof sharedLabels.$inferSelect;
export type InsertTask = z.infer<typeof insertTaskSchema>;
export type Task = typeof tasks.$inferSelect;
export type InsertSharedTask = z.infer<typeof insertSharedTaskSchema>;
export type SharedTask = typeof sharedTasks.$inferSelect;
export type InsertUserTaskAccess = z.infer<typeof insertUserTaskAccessSchema>;
export type UserTaskAccess = typeof userTaskAccess.$inferSelect;


export const notes = pgTable("notes", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  title: text("title"),
  content: text("content"),
  taskId: varchar("task_id").references(() => tasks.id),
  userId: varchar("user_id").references(() => users.id),
  createdAt: timestamp("created_at").defaultNow(),
});

export const insertNoteSchema = createInsertSchema(notes).omit({
  id: true,
  createdAt: true,
});

export type InsertNote = z.infer<typeof insertNoteSchema>;
export const xpEvents = pgTable("xp_events", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").references(() => users.id),
  amount: integer("amount").notNull(),
  source: text("source").notNull(), // 'task_completion', 'daily_streak', 'bonus'
  taskId: varchar("task_id"),
  createdAt: timestamp("created_at").defaultNow(),
});

export const goals = pgTable("goals", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").references(() => users.id),
  title: text("title").notNull(),
  target: integer("target").notNull(),
  current: integer("current").notNull().default(0),
  type: text("type").notNull(), // 'weekly_tasks', 'total_xp', 'streak'
  deadline: timestamp("deadline"),
  completed: boolean("completed").default(false),
  createdAt: timestamp("created_at").defaultNow(),
});

export const insertXpEventSchema = createInsertSchema(xpEvents).omit({
  id: true,
  createdAt: true,
});

export const insertGoalSchema = createInsertSchema(goals).omit({
  id: true,
  current: true,
  completed: true,
  createdAt: true,
});

export type InsertXpEvent = z.infer<typeof insertXpEventSchema>;
export type XpEvent = typeof xpEvents.$inferSelect;
export type InsertGoal = z.infer<typeof insertGoalSchema>;
export type Goal = typeof goals.$inferSelect;
export type Note = typeof notes.$inferSelect;

export const rewards = pgTable("rewards", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  title: text("title").notNull(),
  description: text("description"),
  cost: integer("cost").notNull(),
  icon: text("icon").notNull(),
  type: text("type").notNull().default("virtual"), // 'virtual', 'real_world', 'feature_unlock'
  isSystem: boolean("is_system").default(true),
  userId: varchar("user_id").references(() => users.id), // Nullable for system rewards
});

export const userRewards = pgTable("user_rewards", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").references(() => users.id),
  rewardId: varchar("reward_id").references(() => rewards.id),
  purchasedAt: timestamp("purchased_at").defaultNow(),
});

export const insertRewardSchema = createInsertSchema(rewards).omit({
  id: true,
});

export type InsertReward = z.infer<typeof insertRewardSchema>;
export type Reward = typeof rewards.$inferSelect;
export type UserReward = typeof userRewards.$inferSelect;

export const insertUserRewardSchema = createInsertSchema(userRewards).omit({
  id: true,
  purchasedAt: true,
});

// Session table (managed by connect-pg-simple but defined here to avoid drizzle-kit deletion)
export const session = pgTable("session", {
  sid: varchar("sid").primaryKey(),
  sess: json("sess").notNull(),
  expire: timestamp("expire", { precision: 6 }).notNull(),
});

export const passwordResetTokens = pgTable("password_reset_tokens", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").references(() => users.id).notNull(),
  token: text("token").notNull().unique(),
  expiresAt: timestamp("expires_at").notNull(),
  isUsed: boolean("is_used").default(false),
  createdAt: timestamp("created_at").defaultNow(),
});

export const insertPasswordResetTokenSchema = createInsertSchema(passwordResetTokens).omit({
  id: true,
  createdAt: true,
});

export type InsertPasswordResetToken = z.infer<typeof insertPasswordResetTokenSchema>;
export type PasswordResetToken = typeof passwordResetTokens.$inferSelect;

export type InsertUserReward = z.infer<typeof insertUserRewardSchema>;

// AI Chat Tables
export const conversations = pgTable("conversations", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").references(() => users.id).notNull(),
  title: text("title").notNull(),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

export const messages = pgTable("messages", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  conversationId: varchar("conversation_id").references(() => conversations.id).notNull(),
  role: text("role").notNull(), // 'user' | 'assistant' | 'system'
  content: text("content").notNull(),
  createdAt: timestamp("created_at").defaultNow(),
});

export const insertConversationSchema = createInsertSchema(conversations).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export const insertMessageSchema = createInsertSchema(messages).omit({
  id: true,
  createdAt: true,
});

export type InsertConversation = z.infer<typeof insertConversationSchema>;
export type Conversation = typeof conversations.$inferSelect;
export type InsertMessage = z.infer<typeof insertMessageSchema>;
export type Message = typeof messages.$inferSelect;

// Audit Logging
export const auditLogs = pgTable("audit_logs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").references(() => users.id), // Nullable if system action (though usually we track actor)
  action: text("action").notNull(), // 'CREATE', 'UPDATE', 'DELETE', 'LOGIN', etc.
  entityType: text("entity_type").notNull(), // 'TASK', 'GOAL', 'USER', 'SYSTEM'
  entityId: text("entity_id"), // ID of the modified entity
  details: json("details"), // JSON object with changed fields
  source: text("source").notNull().default("USER"), // 'USER' | 'AI' | 'SYSTEM'
  createdAt: timestamp("created_at").defaultNow(),
});

export const insertAuditLogSchema = createInsertSchema(auditLogs).omit({
  id: true,
  createdAt: true,
});

export type InsertAuditLog = z.infer<typeof insertAuditLogSchema>;
export type AuditLog = typeof auditLogs.$inferSelect;
