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

export const companies = pgTable(
  'companies',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    portId: text('port_id')
      .notNull()
      .references(() => ports.id),
    name: text('name').notNull(),
    legalName: text('legal_name'),
    taxId: text('tax_id'),
    registrationNumber: text('registration_number'),
    /** ISO-3166-1 alpha-2 country of incorporation. */
    incorporationCountryIso: text('incorporation_country_iso'),
    /** ISO 3166-2 subdivision (state/province) of incorporation. Optional. */
    incorporationSubdivisionIso: text('incorporation_subdivision_iso'),
    incorporationDate: timestamp('incorporation_date', { withTimezone: true, mode: 'date' }),
    status: text('status').notNull().default('active'), // 'active' | 'dissolved'
    billingEmail: text('billing_email'),
    notes: text('notes'),
    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_companies_port').on(table.portId),
    uniqueIndex('idx_companies_name_unique').on(table.portId, sql`lower(${table.name})`),
    index('idx_companies_taxid')
      .on(table.portId, table.taxId)
      .where(sql`${table.taxId} IS NOT NULL`),
    // M-SC02: partial index covering the hot "non-archived companies"
    // path. Matches the pattern already used on clients/yachts/interests.
    index('idx_companies_archived')
      .on(table.portId)
      .where(sql`${table.archivedAt} IS NULL`),
  ],
);

export const companyMemberships = pgTable(
  'company_memberships',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    companyId: text('company_id')
      .notNull()
      .references(() => companies.id, { onDelete: 'cascade' }),
    clientId: text('client_id')
      .notNull()
      .references(() => clients.id, { onDelete: 'cascade' }),
    role: text('role').notNull(), // director | officer | broker | representative | legal_counsel | employee | shareholder | other
    roleDetail: text('role_detail'),
    startDate: timestamp('start_date', { withTimezone: true, mode: 'date' }).notNull(),
    endDate: timestamp('end_date', { withTimezone: true, mode: 'date' }),
    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_cm_company').on(table.companyId),
    index('idx_cm_client').on(table.clientId),
    index('idx_cm_active')
      .on(table.companyId, table.clientId)
      .where(sql`${table.endDate} IS NULL`),
    uniqueIndex('unique_cm_exact').on(table.companyId, table.clientId, table.role, table.startDate),
  ],
);

export const companyAddresses = pgTable(
  'company_addresses',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    companyId: text('company_id')
      .notNull()
      .references(() => companies.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. 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_compa_company').on(table.companyId),
    index('idx_compa_port').on(table.portId),
    uniqueIndex('idx_compa_primary')
      .on(table.companyId)
      .where(sql`${table.isPrimary} = true`),
  ],
);

export const companyNotes = pgTable(
  'company_notes',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    companyId: text('company_id')
      .notNull()
      .references(() => companies.id, { onDelete: 'cascade' }),
    authorId: text('author_id').notNull(),
    content: text('content').notNull(),
    mentions: text('mentions').array(),
    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_compn_company').on(table.companyId)],
);

export const companyTags = pgTable(
  'company_tags',
  {
    companyId: text('company_id')
      .notNull()
      .references(() => companies.id, { onDelete: 'cascade' }),
    tagId: text('tag_id').notNull(),
  },
  (table) => [primaryKey({ columns: [table.companyId, table.tagId] })],
);

export type Company = typeof companies.$inferSelect;
export type NewCompany = typeof companies.$inferInsert;
export type CompanyMembership = typeof companyMemberships.$inferSelect;
export type NewCompanyMembership = typeof companyMemberships.$inferInsert;
export type CompanyAddress = typeof companyAddresses.$inferSelect;
export type NewCompanyAddress = typeof companyAddresses.$inferInsert;
export type CompanyNote = typeof companyNotes.$inferSelect;
export type NewCompanyNote = typeof companyNotes.$inferInsert;
