// 2026-11-11 — Auditee details for Create Job.
//
// Why: many companies carry placeholder contact data ("Unknown", "N/A", "0000000000",
// "unknown@example.com", scope "Unknown") — often because the real details were saved on a DUPLICATE
// company or only on the Audit Request (auditee_name / auditee_contact / auditee_email / auditees / scope).
// The documents printed those placeholders.
//
// Now the Create Job form shows the auditee details (name, designation, mobile, telephone, email, address,
// scope of work) pre-filled from the best source, editable, with buttons to copy from the other sources.
// The edited values are stored on each job (jobs.companySnapshot, auditeeEdited = true) and printed on its
// documents; optionally they are also written back to the company record (logged in company_change_log).

export const AUDITEE_FIELDS = ['contact_person', 'designation', 'mobile', 'telephone', 'email', 'address', 'scope_of_work'] as const;
export type AuditeeField = (typeof AUDITEE_FIELDS)[number];
export type Auditee = Partial<Record<AuditeeField, string>>;

/** placeholder values that mean "not known" */
export function isPlaceholder(v: any): boolean {
  if (v === null || v === undefined) return true;
  const s = String(v).trim().toLowerCase();
  if (!s) return true;
  if (/^0+$/.test(s.replace(/[\s+()-]/g, ''))) return true; // 0000000000
  if (['unknown', 'n/a', 'na', 'n.a', 'n.a.', '-', '--', 'none', 'null', 'nil', 'test', 'tbd', '.'].includes(s)) return true;
  if (/^unknown@|@example\.com$/.test(s)) return true;
  return false;
}
export const clean = (v: any): string => (isPlaceholder(v) ? '' : String(v).trim());

export function fromCompany(c: any): Auditee {
  if (!c) return {};
  const out: Auditee = {};
  for (const f of AUDITEE_FIELDS) out[f] = clean(c[f]);
  return out;
}

/** audit_requests row → auditee (auditee_name / auditee_contact / auditee_email / auditees[].designation / scope_of_work) */
export function fromAuditRequest(ar: any): Auditee {
  if (!ar) return {};
  let list: any[] = [];
  try {
    list = typeof ar.auditees === 'string' ? JSON.parse(ar.auditees) : Array.isArray(ar.auditees) ? ar.auditees : [];
  } catch {
    list = [];
  }
  const name = clean(ar.auditee_name) || clean(list[0]?.name);
  const match = list.find((x: any) => clean(x?.name).toLowerCase() === name.toLowerCase()) || list[0];
  return {
    contact_person: name,
    designation: clean(match?.designation),
    mobile: clean(ar.auditee_contact),
    telephone: '',
    email: clean(ar.auditee_email),
    address: clean(ar.company_location) || clean(ar.location),
    scope_of_work: clean(ar.scope_of_work),
  };
}

/** first non-empty value per field across the sources (in priority order) */
export function merge(...sources: Auditee[]): Auditee {
  const out: Auditee = {};
  for (const f of AUDITEE_FIELDS) out[f] = sources.map((s) => s?.[f] || '').find((x) => !!x) || '';
  return out;
}

export function hasAny(a: Auditee): boolean {
  return AUDITEE_FIELDS.some((f) => !!a[f]);
}

/** body value → trimmed string (max length) or null */
export function sanitize(a: any): Auditee | null {
  if (!a || typeof a !== 'object') return null;
  const max: Record<AuditeeField, number> = {
    contact_person: 255,
    designation: 255,
    mobile: 100,
    telephone: 100,
    email: 255,
    address: 1000,
    scope_of_work: 10000,
  };
  const out: Auditee = {};
  for (const f of AUDITEE_FIELDS) {
    if (a[f] === undefined || a[f] === null) continue;
    out[f] = String(a[f]).trim().slice(0, max[f]);
  }
  return out;
}
