/**
 * 엑셀 내보내기 유틸리티
 * xlsx 라이브러리를 사용하여 데이터를 엑셀 파일로 변환
 */

import * as XLSX from "xlsx";

/**
 * 데이터를 엑셀 파일로 내보내기
 * @param data 내보낼 데이터 배열
 * @param fileName 파일명 (기본: "export.xlsx")
 * @param sheetName 시트명 (기본: "Sheet1")
 * @param includeHeaders 헤더 포함 여부 (기본: true)
 */
export async function exportToExcel(
  data: Record<string, any>[],
  fileName: string = "export.xlsx",
  sheetName: string = "Sheet1",
  includeHeaders: boolean = true
): Promise<void> {
  try {
    console.log("📥 엑셀 내보내기 시작:", {
      dataCount: data.length,
      fileName,
      sheetName,
      includeHeaders,
    });

    if (data.length === 0) {
      throw new Error("내보낼 데이터가 없습니다.");
    }

    // 워크북 생성
    const workbook = XLSX.utils.book_new();

    // 데이터를 워크시트로 변환
    const worksheet = XLSX.utils.json_to_sheet(data, {
      header: includeHeaders ? undefined : [],
      skipHeader: !includeHeaders,
    });

    // 컬럼 너비 자동 조정
    const columnWidths = autoSizeColumns(data);
    worksheet["!cols"] = columnWidths;

    // 워크시트를 워크북에 추가
    XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);

    // 파일 다운로드
    XLSX.writeFile(workbook, fileName);

    console.log("✅ 엑셀 내보내기 완료:", fileName);
  } catch (error) {
    console.error("❌ 엑셀 내보내기 실패:", error);
    throw error;
  }
}

/**
 * 컬럼 너비 자동 조정
 */
function autoSizeColumns(data: Record<string, any>[]): Array<{ wch: number }> {
  if (data.length === 0) return [];

  const keys = Object.keys(data[0]);
  const columnWidths: Array<{ wch: number }> = [];

  keys.forEach((key) => {
    // 헤더 길이
    let maxWidth = key.length;

    // 데이터 길이 확인
    data.forEach((row) => {
      const value = row[key];
      const valueLength = value ? String(value).length : 0;
      maxWidth = Math.max(maxWidth, valueLength);
    });

    // 최소 10, 최대 50으로 제한
    columnWidths.push({ wch: Math.min(Math.max(maxWidth, 10), 50) });
  });

  return columnWidths;
}

/**
 * 엑셀 파일을 읽어서 JSON 데이터로 변환
 * @param file 읽을 파일
 * @param sheetName 읽을 시트명 (기본: 첫 번째 시트)
 * @returns JSON 데이터 배열
 */
export async function importFromExcel(
  file: File,
  sheetName?: string
): Promise<Record<string, any>[]> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = (e) => {
      try {
        const data = e.target?.result;
        if (!data) {
          reject(new Error("파일을 읽을 수 없습니다."));
          return;
        }

        // 워크북 읽기 (cellDates: 엑셀 시리얼 날짜를 JS Date 객체로 변환)
        const workbook = XLSX.read(data, { type: "binary", cellDates: true });

        // 시트 선택 (지정된 시트 또는 첫 번째 시트)
        const targetSheetName = sheetName || workbook.SheetNames[0];
        const worksheet = workbook.Sheets[targetSheetName];

        if (!worksheet) {
          reject(new Error(`시트 "${targetSheetName}"를 찾을 수 없습니다.`));
          return;
        }

        // JSON으로 변환 (빈 셀도 포함하여 모든 컬럼 키 유지)
        const jsonData = XLSX.utils.sheet_to_json(worksheet, {
          defval: "",
        });

        // Date 객체를 yyyy-mm-dd 문자열로 변환
        const processedData = (jsonData as Record<string, any>[]).map((row) => {
          const newRow: Record<string, any> = {};
          for (const [key, value] of Object.entries(row)) {
            if (value instanceof Date && !isNaN(value.getTime())) {
              const y = value.getUTCFullYear();
              const m = String(value.getUTCMonth() + 1).padStart(2, "0");
              const d = String(value.getUTCDate()).padStart(2, "0");
              newRow[key] = `${y}-${m}-${d}`;
            } else {
              newRow[key] = value;
            }
          }
          return newRow;
        });

        console.log("✅ 엑셀 가져오기 완료:", {
          sheetName: targetSheetName,
          rowCount: processedData.length,
        });

        resolve(processedData);
      } catch (error) {
        console.error("❌ 엑셀 가져오기 실패:", error);
        reject(error);
      }
    };

    reader.onerror = () => {
      reject(new Error("파일 읽기 중 오류가 발생했습니다."));
    };

    reader.readAsBinaryString(file);
  });
}

/**
 * 엑셀 파일의 시트 목록 가져오기
 */
export async function getExcelSheetNames(file: File): Promise<string[]> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = (e) => {
      try {
        const data = e.target?.result;
        if (!data) {
          reject(new Error("파일을 읽을 수 없습니다."));
          return;
        }

        const workbook = XLSX.read(data, { type: "binary" });
        resolve(workbook.SheetNames);
      } catch (error) {
        console.error("❌ 시트 목록 가져오기 실패:", error);
        reject(error);
      }
    };

    reader.onerror = () => {
      reject(new Error("파일 읽기 중 오류가 발생했습니다."));
    };

    reader.readAsBinaryString(file);
  });
}

