/**
 * Catalog of fields a form-template can bind to on Interest / Client / Yacht.
 *
 * Each entry maps a dot-path token (e.g. `client.email`) to:
 *   - the entity table whose row should be read/written
 *   - the column on that table
 *   - the form input type that best matches the column
 *   - a human label shown in the admin "Bind to" picker
 *
 * The form-template editor uses this as an allow-list (a field whose
 * `bindTo` isn't in the catalog is rejected by the validator). The
 * supplemental-form runtime uses it twice: at load time to prefill the
 * public form with the entity's current value, and at submission time to
 * route each posted answer back to the correct table+column with an
 * `interest_field_history` row capturing the override.
 *
 * Entity scoping rules:
 *   - `interest.*`   → write to `interests` row resolved from the token
 *   - `client.*`     → write to `clients` row resolved from interest.clientId
 *   - `client_address.*` → write to first `client_addresses` row (or insert)
 *   - `yacht.*`      → write to the interest's linked yacht (if present)
 *
 * Not in the catalog (intentional):
 *   - Polymorphic ownership columns (yacht.current_owner_*) - needs
 *     ownership-flow service, not a flat write.
 *   - Anything on companies (M43 first pass scopes to client+yacht).
 */

export type BindableType = 'text' | 'textarea' | 'email' | 'phone' | 'number';

export interface BindableField {
  /** Stable dot-path. The form template stores this verbatim in `field.bindTo`. */
  path: string;
  /** Human label shown in the admin picker + the field-history popover. */
  label: string;
  /** Entity bucket - drives the picker grouping + write routing. */
  entity: 'interest' | 'client' | 'client_address' | 'yacht';
  /** Column on the entity's row. */
  column: string;
  /** Default form-input type when the binding is set (the editor still lets the admin override). */
  inputType: BindableType;
}

/**
 * Path naming convention:
 *   - `client.<column>`              - top-level clients row
 *   - `client.primaryEmail|primaryPhone` - synthesised over client_contacts
 *   - `client.address.<column>`      - the primary client_addresses row
 *   - `yacht.<column>`               - interest's linked yachts row
 *   - `interest.<column>`            - interests row resolved from the token
 *
 * `interest_field_history.field_path` stores these strings verbatim, so the
 * detail-page history popover can `WHERE field_path = ?` to surface the
 * inline clock icon for the matching InlineEditableField.
 */
export const BINDABLE_FIELDS: readonly BindableField[] = [
  // ─── Client (top-level identity) ─────────────────────────────────
  {
    path: 'client.fullName',
    label: 'Full name',
    entity: 'client',
    column: 'fullName',
    inputType: 'text',
  },
  {
    path: 'client.primaryEmail',
    label: 'Primary email',
    entity: 'client',
    column: 'primaryEmail',
    inputType: 'email',
  },
  {
    path: 'client.primaryPhone',
    label: 'Primary phone',
    entity: 'client',
    column: 'primaryPhone',
    inputType: 'phone',
  },
  {
    path: 'client.nationality',
    label: 'Nationality',
    entity: 'client',
    column: 'nationality',
    inputType: 'text',
  },

  // ─── Client address (single canonical row) ───────────────────────
  {
    path: 'client.address.streetAddress',
    label: 'Street address',
    entity: 'client_address',
    column: 'streetAddress',
    inputType: 'text',
  },
  {
    path: 'client.address.city',
    label: 'City',
    entity: 'client_address',
    column: 'city',
    inputType: 'text',
  },
  {
    path: 'client.address.postalCode',
    label: 'Postal code',
    entity: 'client_address',
    column: 'postalCode',
    inputType: 'text',
  },
  {
    path: 'client.address.countryIso',
    label: 'Country',
    entity: 'client_address',
    column: 'countryIso',
    inputType: 'text',
  },

  // ─── Yacht ───────────────────────────────────────────────────────
  { path: 'yacht.name', label: 'Yacht name', entity: 'yacht', column: 'name', inputType: 'text' },
  {
    path: 'yacht.hullNumber',
    label: 'Hull number',
    entity: 'yacht',
    column: 'hullNumber',
    inputType: 'text',
  },
  {
    path: 'yacht.registration',
    label: 'Registration',
    entity: 'yacht',
    column: 'registration',
    inputType: 'text',
  },
  { path: 'yacht.flag', label: 'Flag', entity: 'yacht', column: 'flag', inputType: 'text' },
  {
    path: 'yacht.yearBuilt',
    label: 'Year built',
    entity: 'yacht',
    column: 'yearBuilt',
    inputType: 'number',
  },
  {
    path: 'yacht.lengthFt',
    label: 'Length (ft)',
    entity: 'yacht',
    column: 'lengthFt',
    inputType: 'number',
  },
  {
    path: 'yacht.widthFt',
    label: 'Beam (ft)',
    entity: 'yacht',
    column: 'widthFt',
    inputType: 'number',
  },
  {
    path: 'yacht.draftFt',
    label: 'Draft (ft)',
    entity: 'yacht',
    column: 'draftFt',
    inputType: 'number',
  },

  // ─── Interest (deal-level free-form) ─────────────────────────────
  {
    path: 'interest.notes',
    label: 'Additional notes',
    entity: 'interest',
    column: 'notes',
    inputType: 'textarea',
  },
] as const;

const BINDABLE_BY_PATH = new Map(BINDABLE_FIELDS.map((f) => [f.path, f]));

export function getBindableField(path: string | null | undefined): BindableField | null {
  if (!path) return null;
  return BINDABLE_BY_PATH.get(path) ?? null;
}

export function isBindablePath(path: string): boolean {
  return BINDABLE_BY_PATH.has(path);
}

export const BINDABLE_PATHS: readonly string[] = BINDABLE_FIELDS.map((f) => f.path);

/**
 * Grouped form for the admin picker. Returns entries in the order entities
 * should appear in the dropdown (Client, then Yacht, then Interest, then
 * address - most-frequent first).
 */
export function bindableFieldsByEntity(): Array<{
  entity: BindableField['entity'];
  label: string;
  fields: readonly BindableField[];
}> {
  const buckets: Array<{ entity: BindableField['entity']; label: string }> = [
    { entity: 'client', label: 'Client' },
    { entity: 'client_address', label: 'Client address' },
    { entity: 'yacht', label: 'Yacht' },
    { entity: 'interest', label: 'Interest' },
  ];
  return buckets.map((b) => ({
    ...b,
    fields: BINDABLE_FIELDS.filter((f) => f.entity === b.entity),
  }));
}
