export interface MergeField {
  token: string;
  label: string;
  required: boolean;
}

export type MergeFieldCatalog = Record<string, MergeField[]>;

export const MERGE_FIELDS: MergeFieldCatalog = {
  client: [
    { token: '{{client.fullName}}', label: 'Client Full Name', required: true },
    { token: '{{client.email}}', label: 'Primary Email', required: false },
    { token: '{{client.phone}}', label: 'Primary Phone', required: false },
    { token: '{{client.nationality}}', label: 'Nationality', required: false },
    { token: '{{client.source}}', label: 'Lead Source', required: false },
  ],
  yacht: [
    { token: '{{yacht.name}}', label: 'Yacht Name', required: false },
    { token: '{{yacht.hullNumber}}', label: 'Hull Number', required: false },
    { token: '{{yacht.registration}}', label: 'Registration', required: false },
    { token: '{{yacht.flag}}', label: 'Flag', required: false },
    { token: '{{yacht.yearBuilt}}', label: 'Year Built', required: false },
    { token: '{{yacht.lengthFt}}', label: 'Yacht Length (ft)', required: false },
    { token: '{{yacht.widthFt}}', label: 'Yacht Beam (ft)', required: false },
    { token: '{{yacht.draftFt}}', label: 'Yacht Draft (ft)', required: false },
    { token: '{{yacht.lengthM}}', label: 'Yacht Length (m)', required: false },
    { token: '{{yacht.widthM}}', label: 'Yacht Beam (m)', required: false },
    { token: '{{yacht.draftM}}', label: 'Yacht Draft (m)', required: false },
  ],
  company: [
    { token: '{{company.name}}', label: 'Company Name', required: false },
    { token: '{{company.legalName}}', label: 'Company Legal Name', required: false },
    { token: '{{company.taxId}}', label: 'Company Tax ID', required: false },
    { token: '{{company.billingAddress}}', label: 'Company Billing Address', required: false },
  ],
  owner: [
    { token: '{{owner.type}}', label: 'Yacht Owner Type', required: false },
    { token: '{{owner.name}}', label: 'Yacht Owner Name', required: false },
    { token: '{{owner.legalName}}', label: 'Yacht Owner Legal Name', required: false },
  ],
  interest: [
    { token: '{{interest.stage}}', label: 'Pipeline Stage', required: false },
    { token: '{{interest.leadCategory}}', label: 'Lead Category', required: false },
    { token: '{{interest.berthNumber}}', label: 'Berth Number', required: false },
    { token: '{{interest.eoiStatus}}', label: 'EOI Status', required: false },
    { token: '{{interest.dateFirstContact}}', label: 'Date First Contact', required: false },
    { token: '{{interest.dateEoiSigned}}', label: 'Date EOI Signed', required: false },
    { token: '{{interest.dateContractSigned}}', label: 'Date Contract Signed', required: false },
    { token: '{{interest.notes}}', label: 'Interest Notes', required: false },
  ],
  berth: [
    // Non-required so non-EOI templates (welcome letters etc.) don't fail.
    // EOI-specific required-field enforcement lives in STANDARD_EOI_MERGE_FIELDS.
    { token: '{{berth.mooringNumber}}', label: 'Mooring Number', required: false },
    { token: '{{berth.area}}', label: 'Area', required: false },
    { token: '{{berth.status}}', label: 'Berth Status', required: false },
    { token: '{{berth.price}}', label: 'Price', required: false },
    { token: '{{berth.priceCurrency}}', label: 'Price Currency', required: false },
    { token: '{{berth.lengthFt}}', label: 'Length (ft)', required: false },
    { token: '{{berth.widthFt}}', label: 'Beam (ft)', required: false },
    { token: '{{berth.tenureType}}', label: 'Tenure Type', required: false },
    { token: '{{berth.tenureYears}}', label: 'Tenure Years', required: false },
  ],
  eoi: [
    // Compact range string of every berth in the EOI bundle - used inside
    // the Documenso PDF where space is constrained. CRM UI always renders
    // the bundle as individual berth chips. See `formatBerthRange`.
    { token: '{{eoi.berthRange}}', label: 'EOI Berth Range', required: false },
  ],
  reservation: [
    { token: '{{reservation.startDate}}', label: 'Reservation Start Date', required: false },
    { token: '{{reservation.endDate}}', label: 'Reservation End Date', required: false },
    { token: '{{reservation.tenureType}}', label: 'Reservation Tenure Type', required: false },
    { token: '{{reservation.termSummary}}', label: 'Reservation Term Summary', required: false },
    { token: '{{reservation.signedDate}}', label: 'Reservation Signed Date', required: false },
  ],
  port: [
    { token: '{{port.name}}', label: 'Port Name', required: false },
    { token: '{{port.defaultCurrency}}', label: 'Default Currency', required: false },
  ],
  date: [
    { token: '{{date.today}}', label: "Today's Date", required: false },
    { token: '{{date.year}}', label: 'Current Year', required: false },
  ],
};

/**
 * Flat set of every valid token from the catalog. Used as the validator
 * allow-list so unknown tokens are rejected at template creation time.
 */
export const VALID_MERGE_TOKENS: ReadonlySet<string> = new Set(
  Object.values(MERGE_FIELDS).flatMap((scope) => scope.map((field) => field.token)),
);

/**
 * Custom-field merge tokens follow the pattern `{{custom.<fieldName>}}`
 * where fieldName matches the per-port custom field's `fieldName` (the
 * machine identifier, not the display label). Field names are validated
 * at definition time as `[a-z][a-z0-9_]*` so this regex is the matching
 * recogniser. Tokens that match this shape bypass the static
 * `VALID_MERGE_TOKENS` check - the resolver fetches the actual
 * definitions per port at expand time.
 */
export const CUSTOM_MERGE_TOKEN_RE = /^\{\{custom\.[a-z][a-z0-9_]*\}\}$/;

/** True when the token is a `{{custom.<fieldName>}}` shape. */
export function isCustomMergeToken(token: string): boolean {
  return CUSTOM_MERGE_TOKEN_RE.test(token);
}

/** Extract the fieldName from a `{{custom.<fieldName>}}` token. */
export function extractCustomFieldName(token: string): string | null {
  const match = token.match(/^\{\{custom\.([a-z][a-z0-9_]*)\}\}$/);
  return match?.[1] ?? null;
}
