"use client";

import React, {
  FC,
  Dispatch,
  SetStateAction,
  useState,
  useEffect,
} from "react";
import { useToast } from "@/hooks/use-toast";
import { toast as toastMessage } from "sonner";
import prettyBytes from "pretty-bytes";
import { X, Loader2 } from "lucide-react";
import { saveAs } from "file-saver";
import { Badge } from "@/components/ui/badge";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Dropzone,
  DropzoneDescription,
  DropzoneInput,
  DropzoneTitle,
  DropzoneUploadIcon,
  DropzoneZone,
} from "@/components/ui/dropzone";
import {
  FileList,
  FileListAction,
  FileListDescription,
  FileListHeader,
  FileListIcon,
  FileListInfo,
  FileListItem,
  FileListName,
} from "@/components/ui/file-list";
import { Button } from "@/components/ui/button";
import { getReportTempList, getOrigin } from "@/lib/forms/services";
import { DataTableColumnJSON } from "./form-data-table-columns";

const MAX_FILE_SIZE = 3000000;

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

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

interface FormDataReportBatchDialogProps {
  open: boolean;
  setOpen: Dispatch<SetStateAction<boolean>>;
  columnsJSON: DataTableColumnJSON[];
  reportData: ReportData[];
  packageId: number;
  formId: number;
  formCode: string;
}

export const FormDataReportBatchDialog: FC<FormDataReportBatchDialogProps> = ({
  open,
  setOpen,
  columnsJSON,
  reportData,
  packageId,
  formId,
  formCode,
}) => {
  const { toast } = useToast();
  const [tempList, setTempList] = useState<tempFile[]>([]);
  const [selectTemp, setSelectTemp] = useState<string>("");
  const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
  const [isUploading, setIsUploading] = useState(false);

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

  const onClose = () => {
    if (isUploading) {
      return;
    }
    setOpen(false);
  };

  // 드롭존 - 파일 드랍 처리
  const handleDropAccepted = (acceptedFiles: File[]) => {
    const newFiles = [...acceptedFiles];
    setSelectedFiles(newFiles);
  };

  // 드롭존 - 파일 거부(에러) 처리
  const handleDropRejected = (fileRejections: any[]) => {
    fileRejections.forEach((rejection) => {
      toast({
        variant: "destructive",
        title: "File Error",
        description: `${rejection.file.name}: ${
          rejection.errors[0]?.message || "Upload failed"
        }`,
      });
    });
  };

  // 파일 제거 핸들러
  const removeFile = (index: number) => {
    const updatedFiles = [...selectedFiles];
    updatedFiles.splice(index, 1);
    setSelectedFiles(updatedFiles);
  };

  const submitData = async () => {
    setIsUploading(true);

    try {
      const origin = await getOrigin();

      const targetFiles = selectedFiles[0];

      const reportDatas = reportData.map((c) => {
        const reportValue = stringifyAllValues(c);

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

        columnsJSON.forEach((c2) => {
          const { key } = c2;

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

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

        return reportValueMapping;
      });
      const formData = new FormData();
      formData.append("file", targetFiles);
      formData.append("customFileName", `${formCode}.pdf`);
      formData.append("reportDatas", JSON.stringify(reportDatas));
      formData.append("reportTempPath", selectTemp);

      const reqeustCreateReport = await fetch(
        `${origin}/api/pdftron/createVendorDataReports`,
        { method: "POST", body: formData }
      );

      if (reqeustCreateReport.ok) {
        const blob = await reqeustCreateReport.blob();

        saveAs(blob, `${formCode}.pdf`);

        toastMessage.success("Report 다운로드 완료!");
      } else {
        const err = await reqeustCreateReport.json();
        console.error("에러:", err);
        throw new Error(err.message);
      }
    } catch (err) {
      console.error(err);
      toast({
        title: "Error",
        description: "Report 생성 중 오류가 발생했습니다.",
        variant: "destructive",
      });
    } finally {
      setIsUploading(false);
      setSelectedFiles([]);
      setOpen(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onClose}>
      <DialogContent className="w-[600px]" style={{ maxWidth: "none" }}>
        <DialogHeader>
          <DialogTitle>Vendor Document Create</DialogTitle>
          <DialogDescription>
            Vendor Document Template을 선택하신 후 갑지를 업로드하여 주시기
            바랍니다.
          </DialogDescription>
        </DialogHeader>
        <div className="h-[60px]">
          <Label>Vendor Document Template Select</Label>
          <Select value={selectTemp} onValueChange={setSelectTemp}>
            <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>
          <Label>Vendor Document Cover Page Upload(.docx)</Label>
          <Dropzone
            maxSize={MAX_FILE_SIZE}
            multiple={false}
            accept={{ accept: [".docx"] }}
            onDropAccepted={handleDropAccepted}
            onDropRejected={handleDropRejected}
            disabled={isUploading}
          >
            {({ maxSize }) => (
              <>
                <DropzoneZone className="flex justify-center">
                  <DropzoneInput />
                  <div className="flex items-center gap-6">
                    <DropzoneUploadIcon />
                    <div className="grid gap-0.5">
                      <DropzoneTitle>파일을 여기에 드롭하세요</DropzoneTitle>
                      <DropzoneDescription>
                        또는 클릭하여 파일을 선택하세요. 최대 크기:{" "}
                        {maxSize ? prettyBytes(maxSize) : "무제한"}
                      </DropzoneDescription>
                    </div>
                  </div>
                </DropzoneZone>
                <Label className="text-xs text-muted-foreground">
                  여러 파일을 선택할 수 있습니다.
                </Label>
              </>
            )}
          </Dropzone>
        </div>

        {selectedFiles.length > 0 && (
          <div className="grid gap-2">
            <div className="flex items-center justify-between">
              <h6 className="text-sm font-semibold">
                선택된 파일 ({selectedFiles.length})
              </h6>
              <Badge variant="secondary">{selectedFiles.length}개 파일</Badge>
            </div>
            <ScrollArea>
              <UploadFileItem
                selectedFiles={selectedFiles}
                removeFile={removeFile}
                isUploading={isUploading}
              />
            </ScrollArea>
          </div>
        )}

        <DialogFooter>
          <Button
            disabled={
              selectedFiles.length === 0 ||
              selectTemp.length === 0 ||
              isUploading
            }
            onClick={submitData}
          >
            {isUploading && <Loader2 />}Vendor Document Create
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};

interface UploadFileItemProps {
  selectedFiles: File[];
  removeFile: (index: number) => void;
  isUploading: boolean;
}

const UploadFileItem: FC<UploadFileItemProps> = ({
  selectedFiles,
  removeFile,
  isUploading,
}) => {
  return (
    <FileList className="max-h-[200px] gap-3">
      {selectedFiles.map((file, index) => (
        <FileListItem key={index} className="p-3">
          <FileListHeader>
            <FileListIcon />
            <FileListInfo>
              <FileListName>{file.name}</FileListName>
              <FileListDescription>
                {prettyBytes(file.size)}
              </FileListDescription>
            </FileListInfo>
            <FileListAction
              onClick={() => removeFile(index)}
              disabled={isUploading}
            >
              <X className="h-4 w-4" />
              <span className="sr-only">Remove</span>
            </FileListAction>
          </FileListHeader>
        </FileListItem>
      ))}
    </FileList>
  );
};

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 };
    })
  );
};

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) : "";
  }
};