import {
  boolean,
  integer,
  pgEnum,
  pgTable,
  primaryKey,
  text,
  timestamp,
  uniqueIndex,
  uuid,
} from "drizzle-orm/pg-core";

export const accountStatusEnum = pgEnum("account_status", ["active", "disabled", "pending"]);
export const organizationStatusEnum = pgEnum("organization_status", ["active", "disabled"]);
export const roleScopeEnum = pgEnum("role_scope", ["platform", "organization"]);
export const membershipStatusEnum = pgEnum("membership_status", ["active", "disabled", "pending"]);
export const bedStatusEnum = pgEnum("bed_status", ["available", "occupied", "maintenance", "disabled"]);
export const elderStatusEnum = pgEnum("elder_status", ["active", "pending", "discharged"]);
export const careLevelEnum = pgEnum("care_level", ["self-care", "semi-assisted", "assisted", "intensive"]);
export const genderEnum = pgEnum("gender", ["male", "female", "other"]);
export const admissionStatusEnum = pgEnum("admission_status", ["active", "transferred", "discharged"]);
export const auditResultEnum = pgEnum("audit_result", ["success", "denied", "failure"]);
export const incidentStatusEnum = pgEnum("incident_status", ["open", "acknowledged", "resolved", "closed"]);
export const incidentSeverityEnum = pgEnum("incident_severity", ["info", "warning", "critical"]);
export const joinRequestStatusEnum = pgEnum("join_request_status", ["pending", "approved", "rejected"]);

export const systemSettings = pgTable("system_settings", {
  id: text("id").primaryKey().default("global"),
  registrationEnabled: boolean("registration_enabled").notNull().default(true),
  oidcEnabled: boolean("oidc_enabled").notNull().default(false),
  oidcIssuerUrl: text("oidc_issuer_url").notNull().default(""),
  oidcClientId: text("oidc_client_id").notNull().default(""),
  oidcClientSecret: text("oidc_client_secret").notNull().default(""),
  oidcScopes: text("oidc_scopes").notNull().default("openid profile email"),
  oidcRedirectUri: text("oidc_redirect_uri").notNull().default(""),
  oidcAvatarClaim: text("oidc_avatar_claim").notNull().default("picture"),
  oidcAutoProvision: boolean("oidc_auto_provision").notNull().default(false),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
});

export const organizations = pgTable("organizations", {
  id: uuid("id").primaryKey().defaultRandom(),
  name: text("name").notNull(),
  slug: text("slug").notNull(),
  status: organizationStatusEnum("status").notNull().default("active"),
  registrationEnabled: boolean("registration_enabled").notNull().default(true),
  oidcEnabled: boolean("oidc_enabled").notNull().default(false),
  oidcIssuerUrl: text("oidc_issuer_url").notNull().default(""),
  oidcClientId: text("oidc_client_id").notNull().default(""),
  oidcClientSecret: text("oidc_client_secret").notNull().default(""),
  oidcScopes: text("oidc_scopes").notNull().default("openid profile email"),
  oidcRedirectUri: text("oidc_redirect_uri").notNull().default(""),
  oidcAvatarClaim: text("oidc_avatar_claim").notNull().default("picture"),
  oidcAutoProvision: boolean("oidc_auto_provision").notNull().default(false),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
  slugUnique: uniqueIndex("organizations_slug_unique").on(table.slug),
}));

export const permissions = pgTable("permissions", {
  id: text("id").primaryKey(),
  label: text("label").notNull(),
  category: text("category").notNull(),
  description: text("description").notNull(),
  isEnabled: boolean("is_enabled").notNull().default(true),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});

export const roles = pgTable("roles", {
  id: uuid("id").primaryKey().defaultRandom(),
  key: text("key").notNull(),
  organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }),
  scope: roleScopeEnum("scope").notNull(),
  label: text("label").notNull(),
  description: text("description").notNull(),
  isSystem: boolean("is_system").notNull().default(false),
  isEnabled: boolean("is_enabled").notNull().default(true),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
  roleKeyUnique: uniqueIndex("roles_key_organization_unique").on(table.key, table.organizationId),
}));

export const rolePermissions = pgTable("role_permissions", {
  roleId: uuid("role_id").notNull().references(() => roles.id, { onDelete: "cascade" }),
  permissionId: text("permission_id").notNull().references(() => permissions.id, { onDelete: "cascade" }),
}, (table) => ({
  pk: primaryKey({ columns: [table.roleId, table.permissionId] }),
}));

export const accounts = pgTable("accounts", {
  id: uuid("id").primaryKey().defaultRandom(),
  platformRoleId: uuid("platform_role_id").references(() => roles.id),
  name: text("name").notNull(),
  email: text("email").notNull(),
  avatarUrl: text("avatar_url").notNull().default(""),
  passwordHash: text("password_hash").notNull(),
  passwordSalt: text("password_salt").notNull(),
  status: accountStatusEnum("status").notNull().default("active"),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
  emailUnique: uniqueIndex("accounts_email_unique").on(table.email),
}));

export const memberships = pgTable("memberships", {
  id: uuid("id").primaryKey().defaultRandom(),
  accountId: uuid("account_id").notNull().references(() => accounts.id, { onDelete: "cascade" }),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  roleId: uuid("role_id").notNull().references(() => roles.id),
  status: membershipStatusEnum("status").notNull().default("active"),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
  accountOrganizationUnique: uniqueIndex("memberships_account_organization_unique").on(
    table.accountId,
    table.organizationId,
  ),
}));

export const sessions = pgTable("sessions", {
  id: uuid("id").primaryKey().defaultRandom(),
  accountId: uuid("account_id").notNull().references(() => accounts.id, { onDelete: "cascade" }),
  activeOrganizationId: uuid("active_organization_id").references(() => organizations.id),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
});

export const joinRequests = pgTable("join_requests", {
  id: uuid("id").primaryKey().defaultRandom(),
  accountId: uuid("account_id").notNull().references(() => accounts.id, { onDelete: "cascade" }),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  status: joinRequestStatusEnum("status").notNull().default("pending"),
  reason: text("reason").notNull().default(""),
  reviewedByAccountId: uuid("reviewed_by_account_id").references(() => accounts.id),
  reviewedAt: timestamp("reviewed_at", { withTimezone: true }),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});

export const organizationInvitations = pgTable("organization_invitations", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  roleId: uuid("role_id").notNull().references(() => roles.id),
  email: text("email").notNull().default(""),
  token: text("token").notNull(),
  status: text("status").notNull().default("active"),
  createdByAccountId: uuid("created_by_account_id").references(() => accounts.id),
  acceptedByAccountId: uuid("accepted_by_account_id").references(() => accounts.id),
  acceptedAt: timestamp("accepted_at", { withTimezone: true }),
  expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
  tokenUnique: uniqueIndex("organization_invitations_token_unique").on(table.token),
}));

export const campuses = pgTable("campuses", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  address: text("address").notNull().default(""),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
});

export const buildings = pgTable("buildings", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  campusId: uuid("campus_id").notNull().references(() => campuses.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
});

export const floors = pgTable("floors", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  buildingId: uuid("building_id").notNull().references(() => buildings.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  level: integer("level").notNull(),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
});

export const rooms = pgTable("rooms", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  floorId: uuid("floor_id").notNull().references(() => floors.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  code: text("code").notNull(),
  capacity: integer("capacity").notNull().default(1),
  status: organizationStatusEnum("status").notNull().default("active"),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
  roomCodeUnique: uniqueIndex("rooms_code_organization_unique").on(table.organizationId, table.code),
}));

export const beds = pgTable("beds", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  roomId: uuid("room_id").notNull().references(() => rooms.id, { onDelete: "cascade" }),
  code: text("code").notNull(),
  status: bedStatusEnum("status").notNull().default("available"),
  notes: text("notes").notNull().default(""),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
  bedCodeUnique: uniqueIndex("beds_code_room_unique").on(table.roomId, table.code),
}));

export const elders = pgTable("elders", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  gender: genderEnum("gender").notNull(),
  age: integer("age").notNull(),
  careLevel: careLevelEnum("care_level").notNull(),
  status: elderStatusEnum("status").notNull().default("pending"),
  primaryContact: text("primary_contact").notNull(),
  phone: text("phone").notNull(),
  medicalNotes: text("medical_notes").notNull().default(""),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
});

export const admissions = pgTable("admissions", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
  elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }),
  bedId: uuid("bed_id").notNull().references(() => beds.id),
  status: admissionStatusEnum("status").notNull().default("active"),
  admittedAt: timestamp("admitted_at", { withTimezone: true }).notNull().defaultNow(),
  dischargedAt: timestamp("discharged_at", { withTimezone: true }),
  notes: text("notes").notNull().default(""),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
});

export const auditLogs = pgTable("audit_logs", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }),
  timestamp: timestamp("timestamp", { withTimezone: true }).notNull().defaultNow(),
  actorAccountId: uuid("actor_account_id").references(() => accounts.id),
  actorEmail: text("actor_email"),
  action: text("action").notNull(),
  targetType: text("target_type").notNull(),
  targetId: text("target_id"),
  result: auditResultEnum("result").notNull(),
  reason: text("reason").notNull(),
});

export const systemIncidents = pgTable("system_incidents", {
  id: uuid("id").primaryKey().defaultRandom(),
  organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }),
  severity: incidentSeverityEnum("severity").notNull(),
  status: incidentStatusEnum("status").notNull().default("open"),
  title: text("title").notNull(),
  description: text("description").notNull(),
  source: text("source").notNull(),
  acknowledgedByAccountId: uuid("acknowledged_by_account_id").references(() => accounts.id),
  acknowledgedAt: timestamp("acknowledged_at", { withTimezone: true }),
  resolvedByAccountId: uuid("resolved_by_account_id").references(() => accounts.id),
  resolvedAt: timestamp("resolved_at", { withTimezone: true }),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
});
