import { apiClient } from "../api/client";
import { axiosSuccessStatusOnly } from "../lib/applicationReviewApi";
import { parseContributionSubmissionDateInput } from "../lib/vnDateFormat";

export type ApplicantDraftTab = "report" | "application" | "contribution";

export interface ApplicantDraftBundle {
  caseId: string;
  updatedAt: string;
  tabs: {
    report?: Record<string, unknown>;
    application?: Record<string, unknown>;
    contribution?: Record<string, unknown>;
  };
}

/** Normalize values for JSON (Dates → ISO, File → stub). Use for exports & display. */
export function serializeDraftDataForExport(input: unknown): unknown {
  if (input instanceof Date) return input.toISOString();
  if (typeof File !== "undefined" && input instanceof File) {
    return input ? { name: input.name, size: input.size, type: input.type } : null;
  }
  if (Array.isArray(input)) return input.map(serializeDraftDataForExport);
  if (input && typeof input === "object") {
    return Object.fromEntries(
      Object.entries(input as Record<string, unknown>).map(([key, value]) => [
        key,
        serializeDraftDataForExport(value),
      ]),
    );
  }
  return input;
}

function normalizeTabData(tab: ApplicantDraftTab, data: Record<string, unknown>) {
  const safe = serializeDraftDataForExport(data) as Record<string, unknown>;
  if (tab === "application") {
    return {
      ...safe,
      textbookEvidenceFile: null,
      researchEvidenceFile: null,
      technicalEvidenceFile: null,
    };
  }
  if (tab === "contribution") {
    return {
      ...safe,
      submissionDate: typeof safe.submissionDate === "string" ? safe.submissionDate : null,
    };
  }
  return safe;
}

export async function saveApplicantDraftTab(
  tab: ApplicantDraftTab,
  data: Record<string, unknown>,
  caseId?: string,
): Promise<ApplicantDraftBundle> {
  return apiClient.post<ApplicantDraftBundle>("/api/v1/application-drafts", {
    caseId: caseId || undefined,
    tab,
    data: normalizeTabData(tab, data),
  });
}

function unwrapResponsePayload<T>(raw: unknown): T {
  if (raw && typeof raw === "object" && "data" in raw && (raw as { data: unknown }).data !== undefined) {
    return (raw as { data: T }).data;
  }
  return raw as T;
}

function isRecord(x: unknown): x is Record<string, unknown> {
  return x !== null && typeof x === "object" && !Array.isArray(x);
}

/**
 * Load persisted report / application / contribution tab JSON for a dashboard `caseId`
 * (Initiative.case_code, not the submission `sub-…` id).
 */
export async function loadApplicantDraftBundle(caseId: string): Promise<ApplicantDraftBundle> {
  const safe = encodeURIComponent(caseId.trim() || caseId);
  const raw = await apiClient.get<unknown>(`/api/v1/application-drafts/${safe}`, axiosSuccessStatusOnly);
  const body = unwrapResponsePayload<Record<string, unknown>>(raw);
  const tabsRaw = body?.tabs;
  const tabs = isRecord(tabsRaw) ? tabsRaw : {};
  return {
    caseId: String(body?.caseId ?? caseId),
    updatedAt: String(body?.updatedAt ?? new Date().toISOString()),
    tabs: {
      report: isRecord(tabs.report) ? (tabs.report as Record<string, unknown>) : undefined,
      application: isRecord(tabs.application) ? (tabs.application as Record<string, unknown>) : undefined,
      contribution: isRecord(tabs.contribution) ? (tabs.contribution as Record<string, unknown>) : undefined,
    },
  };
}

export function reviveContributionDraft(data?: Record<string, unknown>) {
  if (!data) return undefined;
  return {
    ...data,
    submissionDate: (() => {
      const d = parseContributionSubmissionDateInput(data.submissionDate);
      return d ?? new Date();
    })(),
  };
}
