import {
  useCallback,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import { useQueryClient } from '@tanstack/react-query';
import { Loader2 } from 'lucide-react';
import { toast } from 'sonner';
import {
  Button,
  Checkbox,
  type InitiativeDraft,
  buildOfficialBieuMauFromDraft,
  type ContributionDraftShape,
  fetchApplicationFormDocxPreview,
  fetchApplicationFormOfficialPdf,
  persistReviewDocumentBundle,
  useAuth,
  ApplicationFormOfficialPdfActions,
  useOptionalDraft,
  collectApplicantSubmitToAdminPrerequisiteGaps,
  formatApplicantPrerequisiteToastDescription,
  DocxToPdfViewer,
} from '@ump/shared';
import { runInitiativeSubmitWorkflow } from '@/lib/initiativeSubmitWorkflow';
import { saveApplicantSubmissionRecord } from '@/lib/applicantSubmissionRecord';


const STAFF_PREVIEW_EXPLANATION = (
  <>
    PDF mẫu từ máy chủ (LibreOffice) đồng bộ với tệp lưu ở MinIO khi ứng viên nộp; có thể dự phòng cục bộ trong trình duyệt.
    Nguồn JSON: Đơn / Báo cáo / Xác nhận đóng góp. Dùng{' '}
    <span className="font-medium not-italic text-foreground">Tải DOCX</span> khi cần đối chiếu ngoại tuyến. Cuối khối:{' '}
    <span className="font-medium not-italic text-foreground">Từ chối</span>,{' '}
    <span className="font-medium not-italic text-foreground">Kho minh chứng</span>,{' '}
    <span className="font-medium not-italic text-foreground">Duyệt</span>.
  </>
);

/** Ban quản trị (chỉ xem): không có nút tải DOCX/PDF. */
const ADMIN_READONLY_PREVIEW_EXPLANATION = (
  <>
    Dữ liệu Đơn / Báo cáo / Xác nhận đóng góp; PDF chính thức trên máy chủ khớp MinIO sau khi nộp.
    Cuối khối:{' '}
    <span className="font-medium not-italic text-foreground">Từ chối</span>, mở{' '}
    <span className="font-medium not-italic text-foreground">Kho minh chứng</span>, hoặc{' '}
    <span className="font-medium not-italic text-foreground">Duyệt</span>.
  </>
);

function safeFileBaseName(initiativeName: string, fallbackId: string): string {
  const raw = initiativeName.trim() || fallbackId;
  const cleaned = raw.replace(/[^a-zA-Z0-9_\-\u00C0-\u024F\s]+/g, '-').trim();
  return cleaned || 'ho-so-sang-kien';
}

function triggerDownload(blob: Blob, fileName: string) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = fileName;
  a.click();
  URL.revokeObjectURL(url);
}

type SaveAllDraftsPayload = {
  report: Record<string, unknown>;
  application: Record<string, unknown>;
  contribution: Record<string, unknown>;
};

export type ApplicationFormDocxPreviewProps = {
  draft: InitiativeDraft;
  contribution: ContributionDraftShape;
  className?: string;
  /** Backend case id (review JSON, PDF minh chứng từ MinIO). */
  caseId?: string;
  onSaveAllDrafts?: (payload: SaveAllDraftsPayload) => Promise<void>;
  /** Hội đồng / quản trị: thay nút Lưu / Gửi và cam kết ứng viên. */
  docxStaffFooter?: ReactNode;
  /**
   * Ban quản trị chỉ xem: ẩn « Tải DOCX » / « Tải PDF » (Hội đồng vẫn dùng hai nút này).
   * @default false
   */
  hideDocxPdfExportButtons?: boolean;
};

/**
 * Mẫu hồ sơ `template_application_form.docx` — nguồn dữ liệu: ba form Đơn / Báo cáo / Xác nhận đóng góp
 * (cùng state với `ReviewSnapshotSections`).
 */
export function ApplicationFormDocxPreview({
  draft,
  contribution,
  className,
  caseId,
  onSaveAllDrafts,
  docxStaffFooter,
  hideDocxPdfExportButtons = false,
}: ApplicationFormDocxPreviewProps) {
  const queryClient = useQueryClient();
  const { user } = useAuth();
  const draftContext = useOptionalDraft();
  /** Must match Postgres `Initiative.case_code` so review JSON + submit target the same row. */
  const resolvedServerCaseId =
    (caseId?.trim() || draftContext?.caseId?.trim() || '').trim() || undefined;
  const [formDocxLoading, setFormDocxLoading] = useState(false);
  const [formPdfPreviewUrl, setFormPdfPreviewUrl] = useState<string | null>(null);

  const officialBieuMau = useMemo(
    () =>
      buildOfficialBieuMauFromDraft(
        draft,
        contribution as unknown as Record<string, unknown> | null,
      ) as unknown as Record<string, unknown>,
    [draft, contribution],
  );

  const [isSavingDrafts, setIsSavingDrafts] = useState(false);
  const [isExportingDocx, setIsExportingDocx] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [isHonestyConfirmed, setIsHonestyConfirmed] = useState(false);
  const [browserPdfToolOpen, setBrowserPdfToolOpen] = useState(false);
  const [browserPdfToolFile, setBrowserPdfToolFile] = useState<File | null>(null);
  const [browserPdfToolLoading, setBrowserPdfToolLoading] = useState(false);

  useEffect(() => {
    const both =
      Boolean(draft.application.honestyConfirmed) && Boolean(draft.report.honestyConfirmed);
    setIsHonestyConfirmed(both);
  }, [draft.draftId, draft.application.honestyConfirmed, draft.report.honestyConfirmed]);

  useEffect(() => {
    if (!browserPdfToolOpen) return;
    let cancelled = false;
    setBrowserPdfToolLoading(true);
    setBrowserPdfToolFile(null);
    void (async () => {
      try {
        const buf = await fetchApplicationFormDocxPreview(officialBieuMau);
        if (cancelled) return;
        setBrowserPdfToolFile(
          new File([buf], 'mau-ho-so-xem-truoc.docx', {
            type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
          }),
        );
      } catch (e) {
        if (!cancelled) {
          const msg = e instanceof Error ? e.message : 'Không tải được DOCX cho công cụ cục bộ.';
          toast.error(msg);
        }
      } finally {
        if (!cancelled) setBrowserPdfToolLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [browserPdfToolOpen, officialBieuMau]);

  const a = draft.application;
  const r = draft.report;
  const contributionRecord = contribution as unknown as Record<string, unknown>;
  const contributionDigitalSigned = Boolean(contributionRecord.digitalSignatureConfirmed);

  const submitPrerequisiteGaps = useMemo(
    () =>
      collectApplicantSubmitToAdminPrerequisiteGaps(
        draft.report,
        draft.application,
        contributionDigitalSigned,
      ),
    [draft.report, draft.application, contributionDigitalSigned],
  );

  const persistAllDraftsAndReviewBundle = async () => {
    if (!onSaveAllDrafts) {
      throw new Error('Thiếu tác vụ lưu bản nháp. Vui lòng tải lại trang hoặc thử sau.');
    }
    await onSaveAllDrafts({
      report: r as unknown as Record<string, unknown>,
      application: a as unknown as Record<string, unknown>,
      contribution: contributionRecord,
    });
    await persistReviewDocumentBundle(draft, contributionRecord, resolvedServerCaseId);
  };

  const handleSaveDrafts = async () => {
    if (isSavingDrafts) return;
    try {
      setIsSavingDrafts(true);
      await persistAllDraftsAndReviewBundle();
      toast.success('Đã lưu toàn bộ bản nháp (3 tab) và dữ liệu xem lại lên máy chủ.');
    } catch (e) {
      const msg = e instanceof Error ? e.message : 'Không thể lưu bản nháp. Vui lòng thử lại.';
      toast.error(msg);
    } finally {
      setIsSavingDrafts(false);
    }
  };

  const handleExportDocx = async () => {
    if (isExportingDocx) return;
    setIsExportingDocx(true);
    try {
      const buf = await fetchApplicationFormDocxPreview(officialBieuMau);
      const blob = new Blob([buf], {
        type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      });
      const initiativeName =
        draft.application.initiativeName?.trim() || draft.report.initiativeName?.trim() || '';
      const base = safeFileBaseName(initiativeName, draft.draftId);
      triggerDownload(blob, `${base}-mau-ho-so.docx`);
      toast.success('Đã tải file Word mẫu hồ sơ.');
    } catch (e) {
      const msg = e instanceof Error ? e.message : 'Không tải được DOCX.';
      toast.error(msg);
    } finally {
      setIsExportingDocx(false);
    }
  };

  const handleSubmitToAdmin = async () => {
    if (!isHonestyConfirmed || isSubmitting) return;
    if (submitPrerequisiteGaps.length > 0) {
      toast.error('Chưa đủ điều kiện gửi hồ sơ', {
        description: formatApplicantPrerequisiteToastDescription(submitPrerequisiteGaps),
      });
      return;
    }
    const initiativeName =
      draft.application.initiativeName?.trim() || draft.report.initiativeName?.trim() || '';
    if (!initiativeName) {
      toast.error('Vui lòng điền tên sáng kiến ở Đơn hoặc Báo cáo trước khi nộp.');
      return;
    }
    const loadingToastId = toast.loading(
      'Đang lưu bản nháp, tạo PDF và gửi… (quá trình có thể mất vài phút; vui lòng không đóng trang)',
    );
    setIsSubmitting(true);
    try {
      await persistAllDraftsAndReviewBundle();
      const primaryAuthor = draft.application.authors[0];
      const response = await runInitiativeSubmitWorkflow({
        draft,
        initiativeCaseId: resolvedServerCaseId,
        contributionDraft: contributionRecord,
        onSaveAllDrafts: undefined,
        metadata: {
          initiativeName,
          authorName:
            draft.report.representativeAuthor?.trim() ||
            primaryAuthor?.name?.trim() ||
            user?.name ||
            '—',
          authorEmail: draft.report.representativeEmail?.trim() || user?.email || undefined,
          authorPhone: draft.report.representativePhone?.trim() || undefined,
          initiativeCaseId: resolvedServerCaseId,
          caseId: resolvedServerCaseId ?? draft.draftId,
          topicType: draft.application.applicationField?.trim() || undefined,
        },
      });
      saveApplicantSubmissionRecord(response, {
        caseId: resolvedServerCaseId ?? draft.draftId,
        initiativeName: response.name ?? initiativeName,
      });
      await queryClient.invalidateQueries({ queryKey: ['applications'] });
      await queryClient.invalidateQueries({ queryKey: ['applications-mine'] });
      await queryClient.invalidateQueries({ queryKey: ['application-detail', response.id] });
      toast.success(
        'Đã gửi hồ sơ PDF. Ban quản trị xem tại mục Danh Sách Sáng kiến trên bảng điều khiển.',
        { id: loadingToastId },
      );
    } catch (e) {
      const msg = e instanceof Error ? e.message : 'Không thể gửi hồ sơ.';
      toast.error(msg, { id: loadingToastId });
    } finally {
      setIsSubmitting(false);
    }
  };

  const runFormDocxPreview = useCallback(async () => {
    setFormDocxLoading(true);
    try {
      const buf = await fetchApplicationFormOfficialPdf(officialBieuMau);
      const blob = new Blob([buf], {
        type: 'application/pdf',
      });
      const nextUrl = URL.createObjectURL(blob);
      setFormPdfPreviewUrl((previous) => {
        if (previous) URL.revokeObjectURL(previous);
        return nextUrl;
      });
    } catch (e) {
      const msg = e instanceof Error ? e.message : 'Không xem trước được mẫu PDF.';
      toast.error(msg);
    } finally {
      setFormDocxLoading(false);
    }
  }, [officialBieuMau]);

  useEffect(() => {
    void runFormDocxPreview();
  }, [runFormDocxPreview]);

  useEffect(() => {
    return () => {
      if (formPdfPreviewUrl) URL.revokeObjectURL(formPdfPreviewUrl);
    };
  }, [formPdfPreviewUrl]);

  return (
    <div
      className={
        'rounded-lg border border-border/60 bg-muted/15 p-3 sm:p-4 ' + (className ?? '')
      }
    >
      <section aria-labelledby="form-docx-preview-heading" className="flex flex-col h-full space-y-2">
        <h3 id="form-docx-preview-heading" className="text-sm font-semibold text-foreground">
          Xem trước mẫu hồ sơ (PDF)
        </h3>
        <p className="text-sm text-muted-foreground leading-relaxed">
          {docxStaffFooter
            ? hideDocxPdfExportButtons
              ? ADMIN_READONLY_PREVIEW_EXPLANATION
              : STAFF_PREVIEW_EXPLANATION
            : null}
        </p>
        {formDocxLoading && (
          <p className="text-sm text-muted-foreground flex items-center gap-2 py-1">
            <Loader2 className="h-4 w-4 shrink-0 animate-spin" aria-hidden />
            Đang tạo bản xem trước…
          </p>
        )}
        <div className="h-[792pt] max-h-[90vh] overflow-hidden rounded border border-border/60 bg-muted/20">
          {formPdfPreviewUrl ? (
            <iframe
              src={formPdfPreviewUrl}
              title="Xem trước mẫu hồ sơ PDF"
              className="h-full w-full"
            />
          ) : (
            <div className="flex h-full items-center justify-center text-sm text-muted-foreground">
              Chưa có dữ liệu xem trước PDF.
            </div>
          )}
        </div>
      </section>

      {!docxStaffFooter || !hideDocxPdfExportButtons ? (
        <div className="mt-4 flex flex-col h-full hidden-overflow gap-2 sm:flex-row sm:flex-wrap">
          {!hideDocxPdfExportButtons ? (
            <ApplicationFormOfficialPdfActions
              draft={draft}
              contribution={contribution}
              caseId={resolvedServerCaseId}
              disabled={isSubmitting}
              className="flex w-full flex-col gap-2 sm:flex-row sm:w-auto sm:flex-wrap"
            />
          ) : null}
          {!docxStaffFooter ? (
            <Button
              type="button"
              variant="outline"
              size="sm"
              className="w-full sm:w-auto"
              onClick={() => void handleSaveDrafts()}
              disabled={!onSaveAllDrafts || isSavingDrafts || isSubmitting}
            >
              {isSavingDrafts ? (
                <>
                  <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin inline" aria-hidden />
                  Đang lưu…
                </>
              ) : (
                "Lưu bản nháp"
              )}
            </Button>
          ) : null}
          {!hideDocxPdfExportButtons ? (
            <Button
              type="button"
              variant="outline"
              size="sm"
              className="w-full sm:w-auto"
              onClick={() => void handleExportDocx()}
              disabled={isExportingDocx || isSubmitting}
            >
              {isExportingDocx ? (
                <>
                  <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin inline" aria-hidden />
                  Đang tải DOCX…
                </>
              ) : (
                "Tải DOCX"
              )}
            </Button>
          ) : null}
        </div>
      ) : null}

      {!hideDocxPdfExportButtons ? (
            <details
              className="mt-4 rounded-md border border-border/60 bg-muted/10 text-sm"
              open={browserPdfToolOpen}
              onToggle={(e) => {
                const el = e.currentTarget;
                setBrowserPdfToolOpen(el.open);
                if (!el.open) setBrowserPdfToolFile(null);
              }}
            >
              <summary className="cursor-pointer select-none px-3 py-2 font-medium text-foreground">
                Công cụ xuất PDF cục bộ (docx-to-pdf-demo · docx-preview + html2canvas)
              </summary>
              <div className="space-y-3 border-t border-border/60 px-3 py-3">
                <p className="text-xs text-muted-foreground leading-relaxed">
                  Dùng khi cần xem từng trang raster trong trình duyệt hoặc khi API LibreOffice chưa sẵn sàng. Nút « Xem trước
                  PDF » / « Xuất PDF » phía trên ưu tiên bản máy chủ (đồng bộ MinIO sau khi nộp).
                </p>
                {browserPdfToolLoading ? (
                  <p className="flex items-center gap-2 text-xs text-muted-foreground">
                    <Loader2 className="h-3.5 w-3.5 shrink-0 animate-spin" aria-hidden />
                    Đang lấy DOCX từ API…
                  </p>
                ) : null}
                {browserPdfToolFile ? (
                  <DocxToPdfViewer file={browserPdfToolFile} hideFilePicker className="space-y-2" />
                ) : null}
              </div>
            </details>
          ) : null}

      {docxStaffFooter ? (
        <div className="mt-4 space-y-3 border-t border-border/60 pt-4">{docxStaffFooter}</div>
      ) : (
        <div className="mt-4 space-y-3 border-t border-border/60 pt-4">
          <div className="flex items-start gap-3">
            <Checkbox
              id="docx-preview-honesty-confirm"
              checked={isHonestyConfirmed}
              onCheckedChange={(checked) => {
                const v = checked === true;
                if (v && submitPrerequisiteGaps.length > 0) {
                  toast.error('Chưa đủ điều kiện xác nhận', {
                    description: formatApplicantPrerequisiteToastDescription(submitPrerequisiteGaps),
                  });
                  return;
                }
                setIsHonestyConfirmed(v);
              }}
              className="mt-0.5"
            />
            <label
              htmlFor="docx-preview-honesty-confirm"
              className="italic text-sm cursor-pointer leading-snug text-muted-foreground"
            >
              Tôi xin cam đoan mọi thông tin nêu trong đơn là trung thực, đúng sự thật và hoàn toàn chịu trách nhiệm
              trước pháp luật.
            </label>
          </div>
          <div className="flex flex-wrap justify-end gap-2">
            <Button
              type="button"
              onClick={() => void handleSubmitToAdmin()}
              disabled={
                !isHonestyConfirmed ||
                isSubmitting ||
                isSavingDrafts ||
                !onSaveAllDrafts ||
                submitPrerequisiteGaps.length > 0
              }
              className="shadow-lg"
            >
              {isSubmitting ? (
                <>
                  <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin inline" aria-hidden />
                  Đang gửi…
                </>
              ) : (
                "Gửi tới Ban quản trị"
              )}
            </Button>
          </div>
        </div>
      )}
    </div>
  );
}
