import {
  sqliteTable,
  text,
  integer,
  real,
  index,
  unique,
} from "drizzle-orm/sqlite-core";

export const users = sqliteTable(
  "users",
  {
    id: text("id").primaryKey(),
    email: text("email").notNull().unique(),
    firstName: text("first_name").notNull(),
    lastName: text("last_name").notNull(),
    password: text("password"), // Optional - Clerk handles authentication
    role: text("role", {
      enum: ["superAdmin", "admin", "trainer", "client"],
    })
      .notNull()
      .default("client"),
    phone: text("phone"),
    gymId: text("gym_id"), // FK reference added after gyms table
    expoPushToken: text("expo_push_token"), // For push notifications
    deviceType: text("device_type", { enum: ["ios", "android"] }), // Device platform
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    updatedAt: integer("updated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    emailIdx: index("users_email_idx").on(table.email),
    gymIdIdx: index("users_gym_id_idx").on(table.gymId),
    roleIdx: index("users_role_idx").on(table.role),
    expoPushTokenIdx: index("users_expo_push_token_idx").on(
      table.expoPushToken,
    ),
  }),
);

export const gyms = sqliteTable(
  "gyms",
  {
    id: text("id").primaryKey(),
    name: text("name").notNull(),
    location: text("location"),
    status: text("status", { enum: ["active", "inactive"] })
      .notNull()
      .default("active"),
    adminUserId: text("admin_user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    updatedAt: integer("updated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    adminUserIdIdx: index("gyms_admin_user_id_idx").on(table.adminUserId),
    statusIdx: index("gyms_status_idx").on(table.status),
  }),
);

export const clients = sqliteTable(
  "clients",
  {
    id: text("id").primaryKey(),
    userId: text("user_id")
      .notNull()
      .unique()
      .references(() => users.id, { onDelete: "cascade" }),
    membershipType: text("membership_type", {
      enum: ["basic", "premium", "vip"],
    })
      .notNull()
      .default("basic"),
    membershipStatus: text("membership_status", {
      enum: ["active", "inactive", "suspended"],
    })
      .notNull()
      .default("active"),
    joinDate: integer("join_date", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    lastVisit: integer("last_visit", { mode: "timestamp" }),
    emergencyContactName: text("emergency_contact_name"),
    emergencyContactPhone: text("emergency_contact_phone"),
    emergencyContactRelationship: text("emergency_contact_relationship"),
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    updatedAt: integer("updated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    userIdIdx: index("clients_user_id_idx").on(table.userId),
    membershipStatusIdx: index("clients_membership_status_idx").on(
      table.membershipStatus,
    ),
  }),
);

export const payments = sqliteTable(
  "payments",
  {
    id: text("id").primaryKey(),
    clientId: text("client_id")
      .notNull()
      .references(() => clients.id, { onDelete: "cascade" }),
    amount: real("amount").notNull(),
    currency: text("currency").notNull().default("USD"),
    status: text("status", {
      enum: ["pending", "completed", "failed", "refunded"],
    })
      .notNull()
      .default("pending"),
    paymentMethod: text("payment_method", {
      enum: ["cash", "card", "bank_transfer"],
    }).notNull(),
    dueDate: integer("due_date", { mode: "timestamp" }).notNull(),
    paidAt: integer("paid_at", { mode: "timestamp" }),
    description: text("description").notNull(),
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    updatedAt: integer("updated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    clientIdIdx: index("payments_client_id_idx").on(table.clientId),
    statusIdx: index("payments_status_idx").on(table.status),
    dueDateIdx: index("payments_due_date_idx").on(table.dueDate),
  }),
);

export const attendance = sqliteTable(
  "attendance",
  {
    id: text("id").primaryKey(),
    userId: text("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    checkInTime: integer("check_in_time", { mode: "timestamp" }).notNull(),
    checkOutTime: integer("check_out_time", { mode: "timestamp" }),
    type: text("type", { enum: ["gym", "class", "personal_training"] })
      .notNull()
      .default("gym"),
    notes: text("notes"),
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    userIdIdx: index("attendance_user_id_idx").on(table.userId),
    checkInTimeIdx: index("attendance_check_in_time_idx").on(table.checkInTime),
    // Composite index for common query: get user's attendance history
    userCheckInIdx: index("attendance_user_check_in_idx").on(
      table.userId,
      table.checkInTime,
    ),
  }),
);

export const notifications = sqliteTable(
  "notifications",
  {
    id: text("id").primaryKey(),
    userId: text("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    title: text("title").notNull(),
    message: text("message").notNull(),
    type: text("type", {
      enum: ["payment_reminder", "attendance", "promotion", "system"],
    }).notNull(),
    read: integer("read", { mode: "boolean" }).notNull().default(false),
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    userIdIdx: index("notifications_user_id_idx").on(table.userId),
    readIdx: index("notifications_read_idx").on(table.read),
    // Composite index for common query: get user's unread notifications
    userReadIdx: index("notifications_user_read_idx").on(
      table.userId,
      table.read,
    ),
  }),
);

export const fitnessProfiles = sqliteTable(
  "fitness_profiles",
  {
    id: text("id").primaryKey(),
    userId: text("user_id")
      .notNull()
      .unique()
      .references(() => users.id, { onDelete: "cascade" }),
    height: real("height"), // in cm
    weight: real("weight"), // in kg
    age: integer("age"),
    gender: text("gender", {
      enum: ["male", "female", "other", "prefer_not_to_say"],
    }),
    fitnessGoals: text("fitness_goals", { mode: "json" }).$type<string[]>(),
    activityLevel: text("activity_level", {
      enum: [
        "sedentary",
        "lightly_active",
        "moderately_active",
        "very_active",
        "extremely_active",
      ],
    }),
    medicalConditions: text("medical_conditions"),
    allergies: text("allergies"),
    injuries: text("injuries"),
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    updatedAt: integer("updated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    userIdIdx: index("fitness_profiles_user_id_idx").on(table.userId),
  }),
);

export const fitnessGoals = sqliteTable(
  "fitness_goals",
  {
    id: text("id").primaryKey(),
    userId: text("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    fitnessProfileId: text("fitness_profile_id").references(
      () => fitnessProfiles.id,
      { onDelete: "cascade" },
    ),

    // Goal details
    goalType: text("goal_type", {
      enum: [
        "weight_target",
        "strength_milestone",
        "endurance_target",
        "flexibility_goal",
        "habit_building",
        "custom",
      ],
    }).notNull(),

    title: text("title").notNull(),
    description: text("description"),

    // Measurable targets
    targetValue: real("target_value"), // e.g., 70 (kg), 100 (kg bench press)
    currentValue: real("current_value"), // Current progress
    unit: text("unit"), // kg, km, reps, etc.

    // Timeline
    startDate: integer("start_date", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    targetDate: integer("target_date", { mode: "timestamp" }),
    completedDate: integer("completed_date", { mode: "timestamp" }),

    // Status tracking
    status: text("status", {
      enum: ["active", "completed", "abandoned", "paused"],
    })
      .notNull()
      .default("active"),

    progress: real("progress").default(0), // 0-100 percentage

    // Metadata
    priority: text("priority", {
      enum: ["low", "medium", "high"],
    }).default("medium"),

    notes: text("notes"),

    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    updatedAt: integer("updated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    userIdIdx: index("fitness_goals_user_id_idx").on(table.userId),
    statusIdx: index("fitness_goals_status_idx").on(table.status),
    // Composite index for common query: get user's active goals
    userStatusIdx: index("fitness_goals_user_status_idx").on(
      table.userId,
      table.status,
    ),
  }),
);

// Removed local invitations table; Clerk invitations are the source of truth

export const trainerClients = sqliteTable(
  "trainer_clients",
  {
    id: text("id").primaryKey(),
    trainerUserId: text("trainer_user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    clientUserId: text("client_user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    gymId: text("gym_id")
      .notNull()
      .references(() => gyms.id, { onDelete: "cascade" }),
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    trainerIdIdx: index("trainer_clients_trainer_id_idx").on(
      table.trainerUserId,
    ),
    clientIdIdx: index("trainer_clients_client_id_idx").on(table.clientUserId),
    gymIdIdx: index("trainer_clients_gym_id_idx").on(table.gymId),
    // Composite unique constraint: prevent duplicate trainer-client assignments
    trainerClientUnique: unique("trainer_client_unique").on(
      table.trainerUserId,
      table.clientUserId,
    ),
  }),
);

export const recommendations = sqliteTable(
  "recommendations",
  {
    id: text("id").primaryKey(),
    userId: text("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    fitnessProfileId: text("fitness_profile_id")
      .notNull()
      .references(() => fitnessProfiles.id, { onDelete: "cascade" }),
    recommendationText: text("recommendation_text").notNull(),
    activityPlan: text("activity_plan").notNull(),
    dietPlan: text("diet_plan").notNull(),
    status: text("status", {
      enum: ["pending", "approved", "rejected"],
    })
      .notNull()
      .default("pending"),
    generatedAt: integer("generated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    approvedAt: integer("approved_at", { mode: "timestamp" }),
    approvedBy: text("approved_by"), // User ID of admin/trainer
    createdAt: integer("created_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
    updatedAt: integer("updated_at", { mode: "timestamp" })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    userIdIdx: index("recommendations_user_id_idx").on(table.userId),
    statusIdx: index("recommendations_status_idx").on(table.status),
    fitnessProfileIdIdx: index("recommendations_fitness_profile_id_idx").on(
      table.fitnessProfileId,
    ),
  }),
);

export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
export type Client = typeof clients.$inferSelect;
export type NewClient = typeof clients.$inferInsert;
export type Payment = typeof payments.$inferSelect;
export type NewPayment = typeof payments.$inferInsert;
export type Attendance = typeof attendance.$inferSelect;
export type NewAttendance = typeof attendance.$inferInsert;
export type Notification = typeof notifications.$inferSelect;
export type NewNotification = typeof notifications.$inferInsert;
export type FitnessProfile = typeof fitnessProfiles.$inferSelect;
export type NewFitnessProfile = typeof fitnessProfiles.$inferInsert;
export type FitnessGoal = typeof fitnessGoals.$inferSelect;
export type NewFitnessGoal = typeof fitnessGoals.$inferInsert;
export type Recommendation = typeof recommendations.$inferSelect;
export type NewRecommendation = typeof recommendations.$inferInsert;
