"use client";

import React, {
  FC,
  Dispatch,
  SetStateAction,
  useState,
  useEffect,
  useRef,
} from "react";
import { WebViewerInstance, Core } from "@pdftron/webviewer";
import { useToast } from "@/hooks/use-toast";
import prettyBytes from "pretty-bytes";
import { X, Loader2 } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import { getReportTempList } from "@/lib/forms/services";
import { DataTableColumnJSON } from "./form-data-table-columns";

type ReportData = {
  [key: string]: any;
};

interface tempFile {
  fileName: string;
  filePath: string;
}

interface FormDataReportDialogProps {
  columnsJSON: DataTableColumnJSON[];
  reportData: ReportData[];
  setReportData: Dispatch<SetStateAction<ReportData[]>>;
  packageId: number;
  formId: number;
  formCode: string;
}

export const FormDataReportDialog: FC<FormDataReportDialogProps> = ({
  columnsJSON,
  reportData,
  setReportData,
  packageId,
  formId,
}) => {
  const [tempList, setTempList] = useState<tempFile[]>([]);
  const [selectTemp, setSelectTemp] = useState<string>("");
  const [instance, setInstance] = useState<null | WebViewerInstance>(null);
  const [fileLoading, setFileLoading] = useState<boolean>(true);

  useEffect(() => {
    updateReportTempList(packageId, formId, setTempList);
  }, [packageId, formId]);

  const onClose = async (value: boolean) => {
    if (fileLoading) {
      return;
    }
    if (!value) {
      setTimeout(() => cleanupHtmlStyle(), 1000);
      setReportData([]);
    }
  };

  const downloadFileData = async () => {
    if (instance) {
      const { UI, Core } = instance;
      const { documentViewer } = Core;

      const doc = documentViewer.getDocument();
      const fileName = doc.getFilename();
      const fileData = await doc.getFileData({
        includeAnnotations: true, // 사용자가 추가한 폼 필드 및 입력 포함
        // officeOptions: {
        //   outputFormat: "docx",
        // },
      });

      const blob = new Blob([fileData], {
        type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      });

      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);

      // const allTabs = UI.TabManager.getAllTabs() as {
      //   id: number;
      //   src: Core.Document;
      // }[];

      // for (const tab of allTabs) {
      //   // await UI.TabManager.setActiveTab(tab.id);
      //   await activateTabAndWaitForLoad(instance, tab.id);
      //   const tabDoc = tab.src;
      //   const fileName = tabDoc.getFilename();

      //   const fileData = await tabDoc.getFileData({
      //     includeAnnotations: true,
      //   });

      //   console.log({ fileData });

      //   const blob = new Blob([fileData], {
      //     type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      //   });

      //   // 다운로드
      //   // const link = document.createElement("a");
      //   // link.href = URL.createObjectURL(blob);
      //   // link.download = fileName;
      //   // document.body.appendChild(link);
      //   // link.click();
      //   // document.body.removeChild(link);
      // }
    }
  };

  return (
    <Dialog open={reportData.length > 0} onOpenChange={onClose}>
      <DialogContent className="w-[70vw]" style={{ maxWidth: "none" }}>
        <DialogHeader>
          <DialogTitle>Report</DialogTitle>
          <DialogDescription>
            사용하시고자 하는 Report Template를 선택하여 주시기 바랍니다.
          </DialogDescription>
        </DialogHeader>
        <div className="h-[60px]">
          <Label>Report Template Select</Label>
          <Select
            value={selectTemp}
            onValueChange={setSelectTemp}
            disabled={instance === null}
          >
            <SelectTrigger className="w-[100%]">
              <SelectValue placeholder="사용하시고자하는 Report Template를 선택하여 주시기 바랍니다." />
            </SelectTrigger>
            <SelectContent>
              {tempList.map((c) => {
                const { fileName, filePath } = c;

                return (
                  <SelectItem key={filePath} value={filePath}>
                    {fileName}
                  </SelectItem>
                );
              })}
            </SelectContent>
          </Select>
        </div>
        <div className="h-[calc(70vh-60px)]">
          <ReportWebViewer
            columnsJSON={columnsJSON}
            reportTempPath={selectTemp}
            reportDatas={reportData}
            instance={instance}
            setInstance={setInstance}
            setFileLoading={setFileLoading}
          />
        </div>

        <DialogFooter>
          <Button onClick={downloadFileData} disabled={selectTemp.length === 0}>
            다운로드
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};

interface ReportWebViewerProps {
  columnsJSON: DataTableColumnJSON[];
  reportTempPath: string;
  reportDatas: ReportData[];
  instance: null | WebViewerInstance;
  setInstance: Dispatch<SetStateAction<WebViewerInstance | null>>;
  setFileLoading: Dispatch<SetStateAction<boolean>>;
}

const ReportWebViewer: FC<ReportWebViewerProps> = ({
  columnsJSON,
  reportTempPath,
  reportDatas,
  instance,
  setInstance,
  setFileLoading,
}) => {
  const [viwerLoading, setViewerLoading] = useState<boolean>(true);
  const viewer = useRef<HTMLDivElement>(null);
  const initialized = React.useRef(false);
  const isCancelled = React.useRef(false); // 초기화 중단용 flag

  useEffect(() => {
    if (!initialized.current) {
      initialized.current = true;
      isCancelled.current = false; // 다시 열릴 때는 false로 리셋

      requestAnimationFrame(() => {
        if (viewer.current) {
          import("@pdftron/webviewer").then(({ default: WebViewer }) => {
            console.log(isCancelled.current);
            if (isCancelled.current) {
              console.log("📛 WebViewer 초기화 취소됨 (Dialog 닫힘)");

              return;
            }

            WebViewer(
              {
                path: "/pdftronWeb",
                licenseKey: process.env.NEXT_PUBLIC_PDFTRON_WEBVIEW_KEY,
                fullAPI: true,
              },
              viewer.current as HTMLDivElement
            ).then(async (instance: WebViewerInstance) => {
              setInstance(instance);
              // //Tab 메뉴 사용 필요시 활성화
              // instance.UI.enableFeatures([instance.UI.Feature.MultiTab]);
              // instance.UI.disableElements([
              //   "addTabButton",
              //   "multiTabsEmptyPage",
              // ]);
              setViewerLoading(false);
            });
          });
        }
      });
    }

    return () => {
      // cleanup 시에는 중단 flag 세움
      if (instance) {
        instance.UI.dispose();
      }
      setTimeout(() => cleanupHtmlStyle(), 500);
    };
  }, []);

  useEffect(() => {
    importReportData(
      columnsJSON,
      instance,
      reportDatas,
      reportTempPath,
      setFileLoading
    );
  }, [reportTempPath, reportDatas, instance, columnsJSON]);

  return (
    <div ref={viewer} className="h-[100%]">
      {viwerLoading && (
        <div className="flex flex-col items-center justify-center py-12">
          <Loader2 className="h-8 w-8 text-blue-500 animate-spin mb-4" />
          <p className="text-sm text-muted-foreground">문서 뷰어 로딩 중...</p>
        </div>
      )}
    </div>
  );
};

const cleanupHtmlStyle = () => {
  const htmlElement = document.documentElement;

  // 기존 style 속성 가져오기
  const originalStyle = htmlElement.getAttribute("style") || "";

  // "color-scheme: light" 또는 "color-scheme: dark" 찾기
  const colorSchemeStyle = originalStyle
    .split(";")
    .map((s) => s.trim())
    .find((s) => s.startsWith("color-scheme:"));

  // 새로운 스타일 적용 (color-scheme만 유지)
  if (colorSchemeStyle) {
    htmlElement.setAttribute("style", colorSchemeStyle + ";");
  } else {
    htmlElement.removeAttribute("style"); // color-scheme도 없으면 style 속성 자체 삭제
  }

  console.log("html style 삭제");
};

const stringifyAllValues = (obj: any): any => {
  if (Array.isArray(obj)) {
    return obj.map((item) => stringifyAllValues(item));
  } else if (typeof obj === "object" && obj !== null) {
    const result: any = {};
    for (const key in obj) {
      result[key] = stringifyAllValues(obj[key]);
    }
    return result;
  } else {
    return obj !== null && obj !== undefined ? String(obj) : "";
  }
};

type ImportReportData = (
  columnsJSON: DataTableColumnJSON[],
  instance: null | WebViewerInstance,
  reportDatas: ReportData[],
  reportTempPath: string,
  setFileLoading: Dispatch<SetStateAction<boolean>>
) => void;

const importReportData: ImportReportData = async (
  columnsJSON,
  instance,
  reportDatas,
  reportTempPath,
  setFileLoading
) => {
  setFileLoading(true);
  try {
    if (instance && reportDatas.length > 0 && reportTempPath.length > 0) {
      const { UI, Core } = instance;
      const { documentViewer, createDocument } = Core;

      const getFileData = await fetch(reportTempPath);
      const reportFileBlob = await getFileData.blob();

      const reportData = reportDatas[0];
      const reportValue = stringifyAllValues(reportData);

      const reportValueMapping: { [key: string]: any } = {};

      columnsJSON.forEach((c) => {
        const { key, label } = c;

        const objKey = label.split(" ").join("_");

        reportValueMapping[objKey] = reportValue?.[key] ?? "";
      });

      const doc = await createDocument(reportFileBlob, {
        extension: "docx",
      });

      await doc.applyTemplateValues(reportValueMapping);

      documentViewer.loadDocument(doc, {
        extension: "docx",
        enableOfficeEditing: true,
        officeOptions: {
          formatOptions: {
            applyPageBreaksToSheet: true,
          },
        },
      });
    }
  } catch (err) {
  } finally {
    setFileLoading(false);
  }
};

const importReportDataTab: ImportReportData = async (
  columnJSON,
  instance,
  reportDatas,
  reportTempPath,
  setFileLoading
) => {
  setFileLoading(true);
  try {
    if (instance && reportDatas.length > 0 && reportTempPath.length > 0) {
      const { UI, Core } = instance;
      const { createDocument } = Core;

      const getFileData = await fetch(reportTempPath);
      const reportFileBlob = await getFileData.blob();

      const prevTab = UI.TabManager.getAllTabs();

      (prevTab as object[] as { id: number }[]).forEach((c) => {
        const { id } = c;
        UI.TabManager.deleteTab(id);
      });

      const fileOptions = reportDatas.map((c) => {
        const { tagNumber } = c;

        const options = {
          filename: `${tagNumber}_report.docx`,
        };

        return { options, reportData: c };
      });

      const tabIds = [];

      for (const fileOption of fileOptions) {
        let doc = await createDocument(reportFileBlob, {
          ...fileOption.options,
          extension: "docx",
        });

        await doc.applyTemplateValues(
          stringifyAllValues(fileOption.reportData)
        );

        const tab = await UI.TabManager.addTab(doc, {
          ...fileOption.options,
        });

        tabIds.push(tab); // 탭 ID 저장
      }

      if (tabIds.length > 0) {
        await UI.TabManager.setActiveTab(tabIds[0]);
      }
    }
  } catch (err) {
  } finally {
    setFileLoading(false);
  }
};

type UpdateReportTempList = (
  packageId: number,
  formId: number,
  setPrevReportTemp: Dispatch<SetStateAction<tempFile[]>>
) => void;

const updateReportTempList: UpdateReportTempList = async (
  packageId,
  formId,
  setTempList
) => {
  const tempList = await getReportTempList(packageId, formId);

  setTempList(
    tempList.map((c) => {
      const { fileName, filePath } = c;
      return { fileName, filePath };
    })
  );
};
