import {
  pgTable,
  text,
  boolean,
  timestamp,
  jsonb,
  index,
  uniqueIndex,
  primaryKey,
} from 'drizzle-orm/pg-core';
import { sql } from 'drizzle-orm';
import { ports } from './ports';

export const clients = pgTable(
  'clients',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    portId: text('port_id')
      .notNull()
      .references(() => ports.id),
    fullName: text('full_name').notNull(),
    /** ISO-3166-1 alpha-2 nationality code. */
    nationalityIso: text('nationality_iso'),
    preferredContactMethod: text('preferred_contact_method'), // email, phone, whatsapp
    preferredLanguage: text('preferred_language'),
    /** IANA timezone, e.g. 'Europe/Warsaw'. Validated client + server. */
    timezone: text('timezone'),
    source: text('source'), // website, manual, referral, broker
    sourceDetails: text('source_details'),
    archivedAt: timestamp('archived_at', { withTimezone: true }),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [
    index('idx_clients_port').on(table.portId),
    index('idx_clients_name').on(table.portId, table.fullName),
    index('idx_clients_archived').on(table.portId, table.archivedAt),
    index('idx_clients_nationality_iso').on(table.nationalityIso),
  ],
);

export const clientContacts = pgTable(
  'client_contacts',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    clientId: text('client_id')
      .notNull()
      .references(() => clients.id, { onDelete: 'cascade' }),
    channel: text('channel').notNull(), // email, phone, whatsapp, other
    value: text('value').notNull(),
    /** E.164-normalized phone number (only set when channel='phone'/'whatsapp'). */
    valueE164: text('value_e164'),
    /** ISO-3166-1 alpha-2 of the country this number was parsed against. */
    valueCountry: text('value_country'),
    label: text('label'), // primary, secondary, work, personal, broker, assistant
    isPrimary: boolean('is_primary').notNull().default(false),
    notes: text('notes'),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [
    index('idx_cc_client').on(table.clientId),
    index('idx_cc_email')
      .on(table.channel, table.value)
      .where(sql`${table.channel} = 'email'`),
    index('idx_cc_phone')
      .on(table.channel, table.value)
      .where(sql`${table.channel} = 'phone'`),
  ],
);

export const clientRelationships = pgTable(
  'client_relationships',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    portId: text('port_id')
      .notNull()
      .references(() => ports.id),
    clientAId: text('client_a_id')
      .notNull()
      .references(() => clients.id, { onDelete: 'cascade' }),
    clientBId: text('client_b_id')
      .notNull()
      .references(() => clients.id, { onDelete: 'cascade' }),
    relationshipType: text('relationship_type').notNull(), // referred_by, broker_for, family_member, same_vessel, custom
    description: text('description'),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [index('idx_cr_port').on(table.portId)],
);

export const clientNotes = pgTable(
  'client_notes',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    clientId: text('client_id')
      .notNull()
      .references(() => clients.id, { onDelete: 'cascade' }),
    authorId: text('author_id').notNull(), // user ID
    content: text('content').notNull(),
    mentions: text('mentions').array(), // array of mentioned user IDs
    isLocked: boolean('is_locked').notNull().default(false),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [index('idx_cn_client').on(table.clientId)],
);

export const clientTags = pgTable(
  'client_tags',
  {
    clientId: text('client_id')
      .notNull()
      .references(() => clients.id, { onDelete: 'cascade' }),
    tagId: text('tag_id').notNull(), // references tags.id — defined later in system.ts
  },
  (table) => [primaryKey({ columns: [table.clientId, table.tagId] })],
);

export const clientMergeLog = pgTable(
  'client_merge_log',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    portId: text('port_id')
      .notNull()
      .references(() => ports.id),
    survivingClientId: text('surviving_client_id')
      .notNull()
      .references(() => clients.id),
    mergedClientId: text('merged_client_id').notNull(), // the client that was merged away (may no longer exist)
    mergedBy: text('merged_by').notNull(), // user ID
    mergeDetails: jsonb('merge_details').notNull(), // which fields were kept from which record
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [index('idx_cml_port').on(table.portId)],
);

export const clientAddresses = pgTable(
  'client_addresses',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    clientId: text('client_id')
      .notNull()
      .references(() => clients.id, { onDelete: 'cascade' }),
    portId: text('port_id')
      .notNull()
      .references(() => ports.id, { onDelete: 'cascade' }),
    label: text('label').notNull().default('Primary'),
    streetAddress: text('street_address'),
    city: text('city'),
    /** ISO 3166-2 subdivision code (e.g. 'PL-MZ', 'US-CA'). Optional. */
    subdivisionIso: text('subdivision_iso'),
    postalCode: text('postal_code'),
    /** ISO-3166-1 alpha-2 country code. */
    countryIso: text('country_iso'),
    isPrimary: boolean('is_primary').notNull().default(true),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [
    index('idx_ca_client').on(table.clientId),
    index('idx_ca_port').on(table.portId),
    uniqueIndex('idx_ca_primary')
      .on(table.clientId)
      .where(sql`${table.isPrimary} = true`),
  ],
);

export type Client = typeof clients.$inferSelect;
export type NewClient = typeof clients.$inferInsert;
export type ClientContact = typeof clientContacts.$inferSelect;
export type NewClientContact = typeof clientContacts.$inferInsert;
export type ClientRelationship = typeof clientRelationships.$inferSelect;
export type NewClientRelationship = typeof clientRelationships.$inferInsert;
export type ClientNote = typeof clientNotes.$inferSelect;
export type NewClientNote = typeof clientNotes.$inferInsert;
export type ClientMergeLog = typeof clientMergeLog.$inferSelect;
export type NewClientMergeLog = typeof clientMergeLog.$inferInsert;
export type ClientAddress = typeof clientAddresses.$inferSelect;
export type NewClientAddress = typeof clientAddresses.$inferInsert;
