"use client";

/**
 * AttachmentDialog — 공통 첨부파일 모달
 *
 * 어디서나 재사용. attach_file_info(target_objid, doc_type) 기반.
 * - 목록 조회 / 다운로드 / 업로드(다중) / 삭제
 * - readOnly=true 면 조회 전용
 * - onChanged 콜백으로 그리드 카운트 갱신 트리거
 */

import { useCallback, useEffect, useRef, useState } from "react";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Download, Paperclip, Trash2, Upload } from "lucide-react";
import { apiClient } from "@/lib/api/client";
import { toast } from "sonner";

interface AttachmentFile {
  objid: string;
  realFileName: string;
  savedFileName: string;
  fileSize: number;
  fileExt: string;
  filePath: string;
  docType: string;
  docTypeName?: string;
  writer: string;
  regdate: string;
}

export interface AttachmentDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** attach_file_info.target_objid (보통 contract_mgmt.objid 등) */
  targetObjid: string | number | null | undefined;
  /** 조회 시 doc_type 필터. 단일 문자열 또는 배열(예: ["FTC_ORDER","ORDER"]) */
  docType: string | string[];
  /** 새 업로드 시 INSERT할 doc_type. 미지정 시 docType 단일/배열의 첫 값 사용 */
  uploadDocType?: string;
  /** docType_name 컬럼에 저장할 한글 라벨 (선택) */
  uploadDocTypeName?: string;
  title?: string;
  /** 업로드/삭제 버튼 비활성화 (조회 전용) */
  readOnly?: boolean;
  /** 업로드/삭제 후 호출 — 그리드 카운트 갱신용 */
  onChanged?: () => void;
}

export function AttachmentDialog({
  open,
  onOpenChange,
  targetObjid,
  docType,
  uploadDocType,
  uploadDocTypeName,
  title = "첨부파일",
  readOnly = false,
  onChanged,
}: AttachmentDialogProps) {
  const [files, setFiles] = useState<AttachmentFile[]>([]);
  const [loading, setLoading] = useState(false);
  const [uploading, setUploading] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const docTypeQuery = Array.isArray(docType) ? docType.join(",") : docType;
  const docTypeForUpload =
    uploadDocType ?? (Array.isArray(docType) ? docType[0] : docType);

  const loadFiles = useCallback(async () => {
    if (!targetObjid) {
      setFiles([]);
      return;
    }
    setLoading(true);
    try {
      const res = await apiClient.get("/files", {
        params: { targetObjid: String(targetObjid), docType: docTypeQuery },
      });
      if (res.data?.success) {
        setFiles(res.data.files || []);
      } else {
        setFiles([]);
      }
    } catch (e: any) {
      toast.error("파일 목록 조회 실패: " + (e?.message ?? ""));
      setFiles([]);
    } finally {
      setLoading(false);
    }
  }, [targetObjid, docTypeQuery]);

  useEffect(() => {
    if (open) {
      loadFiles();
    }
  }, [open, loadFiles]);

  async function handleUpload(filesToUpload: FileList | null) {
    if (!filesToUpload || filesToUpload.length === 0) return;
    if (!targetObjid) {
      toast.error("대상 ID(targetObjid)가 없습니다.");
      return;
    }
    if (!docTypeForUpload) {
      toast.error("업로드 doc_type을 결정할 수 없습니다.");
      return;
    }

    setUploading(true);
    try {
      const fd = new FormData();
      for (let i = 0; i < filesToUpload.length; i++) {
        fd.append("files", filesToUpload[i]);
      }
      fd.append("targetObjid", String(targetObjid));
      fd.append("docType", docTypeForUpload);
      if (uploadDocTypeName) fd.append("docTypeName", uploadDocTypeName);

      const res = await apiClient.post("/files/upload", fd, {
        headers: { "Content-Type": "multipart/form-data" },
      });
      if (res.data?.success) {
        toast.success(`${filesToUpload.length}건 업로드 완료`);
        await loadFiles();
        onChanged?.();
      } else {
        toast.error(res.data?.message || "업로드 실패");
      }
    } catch (e: any) {
      toast.error("업로드 실패: " + (e?.message ?? ""));
    } finally {
      setUploading(false);
      if (fileInputRef.current) fileInputRef.current.value = "";
    }
  }

  async function handleDelete(objid: string, name: string) {
    if (!window.confirm(`'${name}' 파일을 삭제하시겠습니까?`)) return;
    try {
      await apiClient.delete(`/files/${objid}`);
      toast.success("파일이 삭제되었습니다.");
      await loadFiles();
      onChanged?.();
    } catch (e: any) {
      toast.error("삭제 실패: " + (e?.message ?? ""));
    }
  }

  function handleDownload(objid: string) {
    const baseURL = (apiClient.defaults.baseURL ?? "").replace(/\/$/, "");
    window.open(`${baseURL}/files/download/${objid}`, "_blank");
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-3xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Paperclip className="h-4 w-4" />
            {title}
          </DialogTitle>
        </DialogHeader>

        <div className="border rounded-md max-h-[50vh] overflow-y-auto">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead className="w-[60px] text-center">#</TableHead>
                <TableHead>파일명</TableHead>
                <TableHead className="w-[100px] text-right">크기</TableHead>
                <TableHead className="w-[110px] text-center">등록자</TableHead>
                <TableHead className="w-[150px] text-center">등록일</TableHead>
                <TableHead className="w-[110px] text-center">동작</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {loading && (
                <TableRow>
                  <TableCell colSpan={6} className="text-center text-muted-foreground py-6">
                    로딩 중…
                  </TableCell>
                </TableRow>
              )}
              {!loading && files.length === 0 && (
                <TableRow>
                  <TableCell colSpan={6} className="text-center text-muted-foreground py-6">
                    첨부파일이 없습니다.
                  </TableCell>
                </TableRow>
              )}
              {!loading &&
                files.map((f, i) => (
                  <TableRow key={f.objid}>
                    <TableCell className="text-center">{i + 1}</TableCell>
                    <TableCell className="truncate max-w-[260px]" title={f.realFileName}>
                      {f.realFileName}
                    </TableCell>
                    <TableCell className="text-right">{formatBytes(f.fileSize)}</TableCell>
                    <TableCell className="text-center">{f.writer}</TableCell>
                    <TableCell className="text-center">
                      {f.regdate ? f.regdate.replace("T", " ").slice(0, 16) : ""}
                    </TableCell>
                    <TableCell className="text-center">
                      <Button
                        variant="ghost"
                        size="sm"
                        onClick={() => handleDownload(f.objid)}
                        title="다운로드"
                      >
                        <Download className="h-4 w-4" />
                      </Button>
                      {!readOnly && (
                        <Button
                          variant="ghost"
                          size="sm"
                          onClick={() => handleDelete(f.objid, f.realFileName)}
                          title="삭제"
                        >
                          <Trash2 className="h-4 w-4 text-destructive" />
                        </Button>
                      )}
                    </TableCell>
                  </TableRow>
                ))}
            </TableBody>
          </Table>
        </div>

        <DialogFooter className="flex sm:justify-between gap-2">
          {!readOnly ? (
            <div className="flex items-center gap-2">
              <input
                ref={fileInputRef}
                type="file"
                multiple
                onChange={(e) => handleUpload(e.target.files)}
                className="hidden"
              />
              <Button
                variant="outline"
                size="sm"
                disabled={uploading || !targetObjid}
                onClick={() => fileInputRef.current?.click()}
              >
                <Upload className="h-4 w-4 mr-1" />
                {uploading ? "업로드 중..." : "파일 추가"}
              </Button>
            </div>
          ) : (
            <span />
          )}
          <Button variant="ghost" onClick={() => onOpenChange(false)}>
            닫기
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function formatBytes(n: number) {
  if (!n) return "0 B";
  const u = ["B", "KB", "MB", "GB"];
  let i = 0;
  let v = n;
  while (v >= 1024 && i < u.length - 1) {
    v /= 1024;
    i++;
  }
  return `${v.toFixed(i === 0 ? 0 : 1)} ${u[i]}`;
}
