// Companies → Documents (Job Registrar Stage 1 / Stage 2 packs) — 2026-11-10
import { fetchApi, API_BASE_URL } from "@/lib/api/http";

export type PackStage = "stage1" | "stage2";
export type PackField =
  | "approvedDate"
  | "prepareDate"
  | "docReview"
  | "numEmployees"
  | "naceEacCodes"
  | "md"
  | "mdRisk"
  | "technicalExpert";

export interface PackFormDef {
  key: string;
  stage: PackStage;
  title: string;
  form_no: string | null;
  fields: PackField[];
  variant_for: string | null;
  for_std: string | null;
}

export interface PackFields {
  docReview?: string | null;
  prepareDate?: string | null;
  approvedDate?: string | null;
  numEmployees?: number | string | null;
  naceEacCodes?: string | null;
  md?: string | null;
  mdRisk?: string | null;
  technicalExpert?: string | null;
  date?: string | null;
  scheduleSlot?: string | null;
  leadAuditorId?: number | null;
  standardIds?: number[];
  expectedSurveillanceDate?: string | null;
  expectedIADate?: string | null;
  expectedMRMDate?: string | null;
  expectedInitialInquiryDate?: string | null;
  expectedInitial_Stage1_Date?: string | null;
}

export interface CompanyAuditOption {
  id: number;
  audit_code: string;
  audit_type: string;
  audit_stage: string;
  audit_mode: string | null;
  status: string;
  schedule_date: string | null;
  audit_time: string | null;
  lead_auditor_id: number | null;
  lead_auditor: string | null;
  standards: { id: number; name: string; title: string }[];
  default_stage: PackStage;
  default_forms: Record<PackStage, string[]>;
  prefill: PackFields;
}

export interface PackFormState {
  key: string;
  title: string;
  form_no: string | null;
  status: "pending" | "done" | "failed";
  file: string | null;
  error: string | null;
}

export interface DocumentPack {
  id: number;
  company_id: number;
  audit_schedule_row_id: number;
  stage: PackStage;
  status: "queued" | "generating" | "done" | "partial" | "failed";
  job_id: number | null;
  job_code: string | null;
  forms: PackFormState[];
  fields: PackFields;
  has_zip: boolean;
  error: string | null;
  version: number;
  created_by_name?: string | null;
  audit_code?: string | null;
  audit_stage?: string | null;
  schedule_date?: string | null;
  generated_at: string | null;
  created_at: string;
  updated_at: string;
}

export interface CompanyDocumentsResponse {
  company: { id: number; name: string };
  audits: CompanyAuditOption[];
  catalogue: PackFormDef[];
  packs: DocumentPack[];
  can_generate: boolean;
}

export interface CodebookRow {
  id: number;
  eac_iaf_codes: string | null;
  division: string | null;
  group: string | null;
  class: string | null;
  nace_rev1: string | null;
  nace_rev2_description: string | null;
  risk: string | null;
}

const BASE = `${API_BASE_URL}/company-documents`;

export const getCompanyDocuments = (companyId: number) =>
  fetchApi<CompanyDocumentsResponse>(`${BASE}/${companyId}`);

export const getDocumentPack = (packId: number) => fetchApi<DocumentPack>(`${BASE}/packs/${packId}`);

export const searchCodebook = (q: string) =>
  fetchApi<CodebookRow[]>(`${BASE}/codebook?q=${encodeURIComponent(q)}`);

export const generateDocumentPack = (
  companyId: number,
  body: { audit_schedule_row_id: number; stage: PackStage; forms: string[]; fields: PackFields; pack_id?: number },
) => fetchApi<DocumentPack>(`${BASE}/${companyId}/generate`, { method: "POST", body: JSON.stringify(body) });

/** Opens (PDF) or downloads (ZIP) a generated file with the user's token. */
export async function openPackFile(packId: number, which: string, filename: string, download = false): Promise<void> {
  const t =
    typeof window !== "undefined"
      ? localStorage.getItem("access_token") || sessionStorage.getItem("access_token")
      : null;
  const res = await fetch(`${BASE}/packs/${packId}/file/${encodeURIComponent(which)}${download ? "?download=1" : ""}`, {
    credentials: "include",
    headers: t ? { Authorization: `Bearer ${t}` } : {},
  });
  if (!res.ok) {
    let msg = `Download failed (${res.status})`;
    try {
      const j = await res.json();
      msg = j?.message || msg;
    } catch {
      /* not json */
    }
    throw new Error(msg);
  }
  const blob = await res.blob();
  const url = URL.createObjectURL(blob);
  if (!download && blob.type === "application/pdf") {
    window.open(url, "_blank", "noopener");
  } else {
    const a = document.createElement("a");
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
  }
  setTimeout(() => URL.revokeObjectURL(url), 60_000);
}

// ═══════════ 2026-11-10: scheme-style "Create Job" flow ═══════════
// 2026-11-11 — editable auditee details (printed on the documents)
export type AuditeeField = "contact_person" | "designation" | "mobile" | "telephone" | "email" | "address" | "scope_of_work";
export type Auditee = Partial<Record<AuditeeField, string>>;
export interface AuditeeSource {
  key: string;
  label: string;
  values: Auditee;
}
export interface DuplicateCompany {
  id: number;
  name: string;
  company_code?: string | null;
  contact_person?: string | null;
  mobile?: string | null;
  email?: string | null;
}

export interface JobFormAudit extends CompanyAuditOption {
  stage_label: "Stage 1" | "Stage 2";
  recommended_template_ids: Record<"Stage 1" | "Stage 2", number[]>;
  auditee?: Auditee; // 2026-11-11
  auditee_sources?: AuditeeSource[]; // 2026-11-11
}
export interface JobFormTemplate {
  id: number;
  name: string;
  stage_name: "Stage 1" | "Stage 2";
  prints: string[];
}
export interface JobFormData {
  company: { id: number; name: string };
  audits: JobFormAudit[];
  templates: JobFormTemplate[];
  allowed_stages?: ("Stage 1" | "Stage 2")[]; // 2026-11-10: dynamic Job Documents permission
  users: { id: number; name: string; is_auditor: boolean }[];
  standards: { id: number; name: string; title: string }[];
  initial_only?: boolean;
  duplicates?: DuplicateCompany[]; // 2026-11-11
  can_update_company?: boolean; // 2026-11-11
}
export interface CompanyJob {
  id: number;
  jobCodes: string[];
  stage: string;
  date: string | null;
  template: string;
  standards: string[];
  lead_auditor: string | null;
  audit_schedule_row_id: number | null;
  created_at: string;
  pdf_url: string;
}

export const getJobForm = (companyId: number) => fetchApi<JobFormData>(`${BASE}/${companyId}/job-form`);
export const getCompanyJobs = (companyId: number) => fetchApi<CompanyJob[]>(`${BASE}/${companyId}/jobs`);
export const createCompanyJobs = (companyId: number, body: Record<string, any>) =>
  fetchApi<{ created: number; jobs: { id: number; jobCode: string; template: string; stage: string }[]; company_updated?: string[] }>(`${BASE}/${companyId}/jobs`, {
    method: "POST",
    body: JSON.stringify(body),
  });

/** Fetch any /api/... file with the user's token, then open (PDF) or save it. Works for registrar and CRM jobs. */
export async function openAuthedFile(apiPath: string, filename: string, download = false): Promise<void> {
  const origin = API_BASE_URL.replace(/\/api\/?$/, "");
  const url = /^https?:\/\//.test(apiPath) ? apiPath : `${origin}${apiPath.startsWith("/") ? "" : "/"}${apiPath}`;
  const t = typeof window !== "undefined" ? localStorage.getItem("access_token") || sessionStorage.getItem("access_token") : null;
  const res = await fetch(encodeURI(decodeURI(url)), { credentials: "include", headers: t ? { Authorization: `Bearer ${t}` } : {} });
  if (!res.ok) {
    let msg = `Could not load the file (${res.status})`;
    try {
      const j = await res.json();
      msg = j?.message || msg;
    } catch {
      /* not json */
    }
    throw new Error(msg);
  }
  const blob = await res.blob();
  const obj = URL.createObjectURL(blob);
  if (!download && blob.type === "application/pdf") window.open(obj, "_blank", "noopener");
  else {
    const a = document.createElement("a");
    a.href = obj;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
  }
  setTimeout(() => URL.revokeObjectURL(obj), 60_000);
}

export const downloadStageZip = (companyId: number, stage: string, filename: string, format: "pdf" | "docx" = "pdf") =>
  openAuthedFile(`/api/company-documents/${companyId}/jobs/zip?stage=${encodeURIComponent(stage)}&format=${format}`, filename, true);

/** 2026-11-10: Word copy of one job document */
export const downloadJobDocx = (jobId: number, filename: string) =>
  openAuthedFile(`/api/company-documents/jobs/${jobId}/docx`, filename, true);

// ═══════════ 2026-11-11: Transfer audits to a Job Documents user ═══════════
export interface TransferUser {
  id: number;
  name: string;
  email: string | null;
  job_docs: boolean;
  transferred: number;
}
export interface TransferAudit {
  id: number;
  audit_code: string;
  audit_type: string;
  audit_stage: string;
  status: string;
  company_id: number;
  company_name: string;
  company_code: string | null;
  schedule_date: string | null;
  lead_auditor: string | null;
  standards: string[];
  documents: number;
  assigned_to: number | null;
  assigned_to_name: string | null;
  assigned_at: string | null;
}
export interface TransferGroup {
  user_id: number;
  name: string;
  month: string;
  audits: number;
  companies: number;
  row_ids: number[];
}
export const getTransferUsers = () => fetchApi<TransferUser[]>(`${BASE}/transfer/users`);
export const getTransferPreview = (month: string, type: "INITIAL" | "ALL" = "INITIAL") =>
  fetchApi<{ ready: boolean; month: string; audits: TransferAudit[] }>(`${BASE}/transfer/preview?month=${encodeURIComponent(month)}&type=${type}`);
export const getTransferSummary = () => fetchApi<{ ready: boolean; groups: TransferGroup[] }>(`${BASE}/transfer/summary`);
export const getMyTransfers = () =>
  fetchApi<{ mode: "all" | "initial" | "transferred"; audits: number; months: string[] }>(`${BASE}/transfer/mine`);
export const transferAudits = (toUserId: number, rowIds: number[], note?: string) =>
  fetchApi<{ transferred: number; to: number }>(`${BASE}/transfer`, { method: "POST", body: JSON.stringify({ toUserId, rowIds, note }) });
export const removeTransfers = (rowIds: number[]) =>
  fetchApi<{ removed: number }>(`${BASE}/transfer/remove`, { method: "POST", body: JSON.stringify({ rowIds }) });
