import { pgTable, text, serial, boolean, timestamp, integer, varchar, unique, customType, jsonb } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";

const bytea = customType<{ data: Buffer }>({
  dataType() { return 'bytea'; },
});

export interface WebAuthnCredential {
  credentialID: string;
  credentialPublicKey: string;
  counter: number;
  transports?: string[];
  registeredAt: string;
}

export const users = pgTable("users", {
  id: serial("id").primaryKey(),
  name: varchar("name", { length: 100 }).notNull(),
  phoneNumber: varchar("phone_number", { length: 20 }).notNull(),
  accessCode: varchar("access_code", { length: 8 }).notNull().unique(),
  messageQuota: integer("message_quota").default(0).notNull(),
  messagesSent: integer("messages_sent").default(0).notNull(),
  isAdmin: boolean("is_admin").default(false).notNull(),
  isCoAdmin: boolean("is_co_admin").default(false).notNull(),
  role: varchar("role", { length: 20 }).default("user").notNull(),
  parentHallId: integer("parent_hall_id"),
  isSuspended: boolean("is_suspended").default(false).notNull(),
  subscriptionExpiresAt: timestamp("subscription_expires_at"),
  subscriptionStartedAt: timestamp("subscription_started_at"),
  paymentWarningAt: timestamp("payment_warning_at"),
  hallNotifiedAt: timestamp("hall_notified_at"),
  hallPassword: varchar("hall_password", { length: 100 }),
  phoneVerified: boolean("phone_verified").default(false).notNull(),
  billingStatus: varchar("billing_status", { length: 20 }),
  nextBillingAt: timestamp("next_billing_at"),
  myfatoorahToken: varchar("myfatoorah_token", { length: 255 }),
  subscriptionType: varchar("subscription_type", { length: 10 }).default("monthly"),
  balanceResetAt: timestamp("balance_reset_at"),
  primaryUserId: integer("primary_user_id"),
  adminWarning7DaysAt: timestamp("admin_warning_7days_at"),
  adminWarningDayZeroAt: timestamp("admin_warning_day_zero_at"),
  adminWarning1DayAt: timestamp("admin_warning_1day_at"),
  adminWarning3DaysAfterAt: timestamp("admin_warning_3days_after_at"),
  passwordHash: varchar("password_hash", { length: 255 }),
  webauthnCredentials: jsonb("webauthn_credentials").$type<WebAuthnCredential[]>(),
  createdAt: timestamp("created_at").defaultNow(),
  isArchived: boolean("is_archived").default(false).notNull(),
  archivedAt: timestamp("archived_at"),
  currentMonthQuota: integer("current_month_quota").default(0).notNull(),
  suspendedByHall: boolean("suspended_by_hall").default(false).notNull(),
  hasBranches: boolean("has_branches").default(false).notNull(),
  googleMapsUrl: text("google_maps_url"),
});

export const guests = pgTable("guests", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").notNull(),
  name: varchar("name", { length: 100 }).notNull(),
  phoneNumber: varchar("phone_number", { length: 20 }).notNull(),
  status: varchar("status", { length: 10, enum: ["pending", "confirmed", "declined"] }).default("pending").notNull(),
  qrToken: varchar("qr_token", { length: 64 }).unique(),
  inviteSlug: varchar("invite_slug", { length: 100 }).unique(),
  checkedIn: boolean("checked_in").default(false).notNull(),
  checkedInAt: timestamp("checked_in_at"),
  sentAt: timestamp("sent_at"),
  guestCount: integer("guest_count").default(1).notNull(),
  additionalNames: text("additional_names"),
  createdAt: timestamp("created_at").defaultNow(),
});

export const settings = pgTable("settings", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").notNull(),
  key: varchar("key", { length: 50 }).notNull(),
  value: text("value"),
}, (t) => [unique("settings_user_key_unique").on(t.userId, t.key)]);

export const whatsappAccounts = pgTable("whatsapp_accounts", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").notNull(),
  name: varchar("name", { length: 50 }).notNull(),
  createdAt: timestamp("created_at").defaultNow(),
});

export const whatsappAuthData = pgTable("whatsapp_auth_data", {
  id: serial("id").primaryKey(),
  accountId: integer("account_id").notNull(),
  dataKey: varchar("data_key", { length: 255 }).notNull(),
  dataValue: text("data_value"),
});

export const mediaFiles = pgTable("media_files", {
  userId: integer("user_id").primaryKey(),
  data: bytea("data").notNull(),
  mimeType: varchar("mime_type", { length: 100 }).notNull(),
  fileType: varchar("file_type", { length: 10 }).notNull(),
  size: integer("size"),
  uploadedAt: timestamp("uploaded_at").defaultNow(),
});

export const sendQueue = pgTable("send_queue", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").notNull(),
  guestId: integer("guest_id").notNull(),
  scheduledAt: timestamp("scheduled_at").notNull(),
  status: varchar("status", { length: 12 }).default("pending").notNull(),
  templateId: varchar("template_id", { length: 50 }).default("formal").notNull(),
  accountId: integer("account_id"),
  useSystem: boolean("use_system").default(false).notNull(),
  warmupActive: boolean("warmup_active").default(false).notNull(),
  attempts: integer("attempts").default(0).notNull(),
  lastError: text("last_error"),
  baseUrl: varchar("base_url", { length: 255 }).notNull(),
  intervalMs: integer("interval_ms").default(60000).notNull(),
  settingsUserId: integer("settings_user_id"),
  createdAt: timestamp("created_at").defaultNow(),
});

export type SendQueueEntry = typeof sendQueue.$inferSelect;
export type InsertSendQueueEntry = typeof sendQueue.$inferInsert;

export const ipBans = pgTable("ip_bans", {
  ip: varchar("ip", { length: 64 }).primaryKey(),
  bannedAt: timestamp("banned_at").defaultNow().notNull(),
  reason: varchar("reason", { length: 255 }),
  manual: boolean("manual").default(false).notNull(),
});

export const auditLogs = pgTable("audit_logs", {
  id: serial("id").primaryKey(),
  actorId: integer("actor_id"),
  action: varchar("action", { length: 80 }).notNull(),
  details: text("details"),
  ip: varchar("ip", { length: 64 }),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

export const hallBranches = pgTable("hall_branches", {
  id: serial("id").primaryKey(),
  hallId: integer("hall_id").notNull(),
  name: varchar("name", { length: 200 }).notNull(),
  googleMapsUrl: text("google_maps_url"),
  createdAt: timestamp("created_at").defaultNow(),
});

export type IpBan = typeof ipBans.$inferSelect;
export type AuditLog = typeof auditLogs.$inferSelect;
export type HallBranch = typeof hallBranches.$inferSelect;
export type InsertHallBranch = typeof hallBranches.$inferInsert;

export const insertUserSchema = createInsertSchema(users).omit({ id: true, createdAt: true });
export const insertGuestSchema = createInsertSchema(guests).omit({ id: true, createdAt: true });
export const insertSettingsSchema = createInsertSchema(settings).omit({ id: true });
export const insertWhatsappAccountSchema = createInsertSchema(whatsappAccounts).omit({ id: true, createdAt: true });

export type User = typeof users.$inferSelect;
export type InsertUser = z.infer<typeof insertUserSchema>;
export type Guest = typeof guests.$inferSelect;
export type InsertGuest = z.infer<typeof insertGuestSchema>;
export type Setting = typeof settings.$inferSelect;
export type WhatsappAccount = typeof whatsappAccounts.$inferSelect;
export type InsertWhatsappAccount = z.infer<typeof insertWhatsappAccountSchema>;

export type CreateGuestRequest = Omit<InsertGuest, 'userId'>;
export type UpdateGuestRequest = Partial<CreateGuestRequest>;
export type UpdateStatusRequest = { status: "pending" | "confirmed" | "declined" };

export type GuestResponse = Guest;
export type GuestsListResponse = Guest[];

export interface FileUploadResponse {
  url: string;
  type: 'image' | 'video';
}

export interface WhatsappAccountStatus {
  id: number;
  name: string;
  status: 'disconnected' | 'connecting' | 'connected' | 'qr_ready';
  qr?: string;
  phoneNumber?: string;
  createdAt?: string | null;
}

export interface UserProfile {
  id: number;
  name: string;
  phoneNumber: string;
  accessCode: string;
  messageQuota: number;
  messagesSent: number;
  messagesRemaining: number;
  isAdmin: boolean;
  isCoAdmin?: boolean;
  role: string;
  parentHallId?: number | null;
  isSuspended?: boolean;
  subscriptionExpiresAt?: string | null;
  subscriptionStartedAt?: string | null;
  paymentWarningAt?: string | null;
  hallNotifiedAt?: string | null;
  hallPassword?: string | null;
  billingStatus?: string | null;
  nextBillingAt?: string | null;
  myfatoorahToken?: string | null;
  subscriptionType?: string | null;
  balanceResetAt?: string | null;
  primaryUserId?: number | null;
}

export interface EventDetails {
  event_date?: string;
  event_time?: string;
  venue_name?: string;
  venue_address?: string;
  delivery_method?: string;
}

export interface InviteData {
  guest: Guest;
  event: EventDetails;
  expired: boolean;
  expiryDate: string | null;
}
