"use client";

/**
 * PivotGrid 메인 컴포넌트
 * 다차원 데이터 분석을 위한 피벗 테이블
 */

import React, { useState, useMemo, useCallback } from "react";
import { cn } from "@/lib/utils";
import {
  PivotGridProps,
  PivotResult,
  PivotFieldConfig,
  PivotCellData,
  PivotFlatRow,
  PivotCellValue,
  PivotGridState,
} from "./types";
import { processPivotData, pathToKey } from "./utils/pivotEngine";
import {
  ChevronRight,
  ChevronDown,
  Download,
  Settings,
  RefreshCw,
  Maximize2,
  Minimize2,
} from "lucide-react";
import { Button } from "@/components/ui/button";

// ==================== 서브 컴포넌트 ====================

// 행 헤더 셀
interface RowHeaderCellProps {
  row: PivotFlatRow;
  rowFields: PivotFieldConfig[];
  onToggleExpand: (path: string[]) => void;
}

const RowHeaderCell: React.FC<RowHeaderCellProps> = ({
  row,
  rowFields,
  onToggleExpand,
}) => {
  const indentSize = row.level * 20;

  return (
    <td
      className={cn(
        "border-r border-b border-border bg-muted/50",
        "px-2 py-1.5 text-left text-sm",
        "whitespace-nowrap font-medium",
        row.isExpanded && "bg-muted/70"
      )}
      style={{ paddingLeft: `${8 + indentSize}px` }}
    >
      <div className="flex items-center gap-1">
        {row.hasChildren && (
          <button
            onClick={() => onToggleExpand(row.path)}
            className="p-0.5 hover:bg-accent rounded"
          >
            {row.isExpanded ? (
              <ChevronDown className="h-3.5 w-3.5" />
            ) : (
              <ChevronRight className="h-3.5 w-3.5" />
            )}
          </button>
        )}
        {!row.hasChildren && <span className="w-4" />}
        <span>{row.caption}</span>
      </div>
    </td>
  );
};

// 데이터 셀
interface DataCellProps {
  values: PivotCellValue[];
  isTotal?: boolean;
  onClick?: () => void;
}

const DataCell: React.FC<DataCellProps> = ({
  values,
  isTotal = false,
  onClick,
}) => {
  if (!values || values.length === 0) {
    return (
      <td
        className={cn(
          "border-r border-b border-border",
          "px-2 py-1.5 text-right text-sm",
          isTotal && "bg-primary/5 font-medium"
        )}
      >
        -
      </td>
    );
  }

  // 단일 데이터 필드인 경우
  if (values.length === 1) {
    return (
      <td
        className={cn(
          "border-r border-b border-border",
          "px-2 py-1.5 text-right text-sm tabular-nums",
          isTotal && "bg-primary/5 font-medium",
          onClick && "cursor-pointer hover:bg-accent/50"
        )}
        onClick={onClick}
      >
        {values[0].formattedValue}
      </td>
    );
  }

  // 다중 데이터 필드인 경우
  return (
    <>
      {values.map((val, idx) => (
        <td
          key={idx}
          className={cn(
            "border-r border-b border-border",
            "px-2 py-1.5 text-right text-sm tabular-nums",
            isTotal && "bg-primary/5 font-medium",
            onClick && "cursor-pointer hover:bg-accent/50"
          )}
          onClick={onClick}
        >
          {val.formattedValue}
        </td>
      ))}
    </>
  );
};

// ==================== 메인 컴포넌트 ====================

export const PivotGridComponent: React.FC<PivotGridProps> = ({
  title,
  fields = [],
  totals = {
    showRowGrandTotals: true,
    showColumnGrandTotals: true,
    showRowTotals: true,
    showColumnTotals: true,
  },
  style = {
    theme: "default",
    headerStyle: "default",
    cellPadding: "normal",
    borderStyle: "light",
    alternateRowColors: true,
    highlightTotals: true,
  },
  allowExpandAll = true,
  height = "auto",
  maxHeight,
  exportConfig,
  data: externalData,
  onCellClick,
  onExpandChange,
}) => {
  // ==================== 상태 ====================

  const [pivotState, setPivotState] = useState<PivotGridState>({
    expandedRowPaths: [],
    expandedColumnPaths: [],
    sortConfig: null,
    filterConfig: {},
  });

  const [isFullscreen, setIsFullscreen] = useState(false);

  // 데이터
  const data = externalData || [];

  // ==================== 필드 분류 ====================

  const rowFields = useMemo(
    () =>
      fields
        .filter((f) => f.area === "row" && f.visible !== false)
        .sort((a, b) => (a.areaIndex || 0) - (b.areaIndex || 0)),
    [fields]
  );

  const columnFields = useMemo(
    () =>
      fields
        .filter((f) => f.area === "column" && f.visible !== false)
        .sort((a, b) => (a.areaIndex || 0) - (b.areaIndex || 0)),
    [fields]
  );

  const dataFields = useMemo(
    () =>
      fields
        .filter((f) => f.area === "data" && f.visible !== false)
        .sort((a, b) => (a.areaIndex || 0) - (b.areaIndex || 0)),
    [fields]
  );

  // ==================== 피벗 처리 ====================

  const pivotResult = useMemo<PivotResult | null>(() => {
    if (!data || data.length === 0 || fields.length === 0) {
      return null;
    }

    return processPivotData(
      data,
      fields,
      pivotState.expandedRowPaths,
      pivotState.expandedColumnPaths
    );
  }, [data, fields, pivotState.expandedRowPaths, pivotState.expandedColumnPaths]);

  // ==================== 이벤트 핸들러 ====================

  // 행 확장/축소
  const handleToggleRowExpand = useCallback(
    (path: string[]) => {
      setPivotState((prev) => {
        const pathKey = pathToKey(path);
        const existingIndex = prev.expandedRowPaths.findIndex(
          (p) => pathToKey(p) === pathKey
        );

        let newPaths: string[][];
        if (existingIndex >= 0) {
          newPaths = prev.expandedRowPaths.filter(
            (_, i) => i !== existingIndex
          );
        } else {
          newPaths = [...prev.expandedRowPaths, path];
        }

        onExpandChange?.(newPaths);

        return {
          ...prev,
          expandedRowPaths: newPaths,
        };
      });
    },
    [onExpandChange]
  );

  // 전체 확장
  const handleExpandAll = useCallback(() => {
    if (!pivotResult) return;

    const allRowPaths: string[][] = [];

    pivotResult.flatRows.forEach((row) => {
      if (row.hasChildren) {
        allRowPaths.push(row.path);
      }
    });

    setPivotState((prev) => ({
      ...prev,
      expandedRowPaths: allRowPaths,
      expandedColumnPaths: [],
    }));
  }, [pivotResult]);

  // 전체 축소
  const handleCollapseAll = useCallback(() => {
    setPivotState((prev) => ({
      ...prev,
      expandedRowPaths: [],
      expandedColumnPaths: [],
    }));
  }, []);

  // 셀 클릭
  const handleCellClick = useCallback(
    (rowPath: string[], colPath: string[], values: PivotCellValue[]) => {
      if (!onCellClick) return;

      const cellData: PivotCellData = {
        value: values[0]?.value,
        rowPath,
        columnPath: colPath,
        field: values[0]?.field,
      };

      onCellClick(cellData);
    },
    [onCellClick]
  );

  // CSV 내보내기
  const handleExportCSV = useCallback(() => {
    if (!pivotResult) return;

    const { flatRows, flatColumns, dataMatrix, grandTotals } = pivotResult;

    let csv = "";

    // 헤더 행
    const headerRow = [""].concat(
      flatColumns.map((col) => col.caption || "총계")
    );
    if (totals?.showRowGrandTotals) {
      headerRow.push("총계");
    }
    csv += headerRow.join(",") + "\n";

    // 데이터 행
    flatRows.forEach((row) => {
      const rowData = [row.caption];

      flatColumns.forEach((col) => {
        const cellKey = `${pathToKey(row.path)}|||${pathToKey(col.path)}`;
        const values = dataMatrix.get(cellKey);
        rowData.push(values?.[0]?.value?.toString() || "");
      });

      if (totals?.showRowGrandTotals) {
        const rowTotal = grandTotals.row.get(pathToKey(row.path));
        rowData.push(rowTotal?.[0]?.value?.toString() || "");
      }

      csv += rowData.join(",") + "\n";
    });

    // 열 총계 행
    if (totals?.showColumnGrandTotals) {
      const totalRow = ["총계"];
      flatColumns.forEach((col) => {
        const colTotal = grandTotals.column.get(pathToKey(col.path));
        totalRow.push(colTotal?.[0]?.value?.toString() || "");
      });
      if (totals?.showRowGrandTotals) {
        totalRow.push(grandTotals.grand[0]?.value?.toString() || "");
      }
      csv += totalRow.join(",") + "\n";
    }

    // 다운로드
    const blob = new Blob(["\uFEFF" + csv], {
      type: "text/csv;charset=utf-8;",
    });
    const link = document.createElement("a");
    link.href = URL.createObjectURL(blob);
    link.download = `${title || "pivot"}_export.csv`;
    link.click();
  }, [pivotResult, totals, title]);

  // ==================== 렌더링 ====================

  // 빈 상태
  if (!data || data.length === 0) {
    return (
      <div
        className={cn(
          "flex flex-col items-center justify-center",
          "p-8 text-center text-muted-foreground",
          "border border-dashed border-border rounded-lg"
        )}
      >
        <RefreshCw className="h-8 w-8 mb-2 opacity-50" />
        <p className="text-sm">데이터가 없습니다</p>
        <p className="text-xs mt-1">데이터를 로드하거나 필드를 설정해주세요</p>
      </div>
    );
  }

  // 필드 미설정
  if (fields.length === 0) {
    return (
      <div
        className={cn(
          "flex flex-col items-center justify-center",
          "p-8 text-center text-muted-foreground",
          "border border-dashed border-border rounded-lg"
        )}
      >
        <Settings className="h-8 w-8 mb-2 opacity-50" />
        <p className="text-sm">필드가 설정되지 않았습니다</p>
        <p className="text-xs mt-1">
          행, 열, 데이터 영역에 필드를 배치해주세요
        </p>
      </div>
    );
  }

  // 피벗 결과 없음
  if (!pivotResult) {
    return (
      <div className="flex items-center justify-center p-8">
        <RefreshCw className="h-5 w-5 animate-spin" />
      </div>
    );
  }

  const { flatRows, flatColumns, dataMatrix, grandTotals } = pivotResult;

  return (
    <div
      className={cn(
        "flex flex-col",
        "border border-border rounded-lg overflow-hidden",
        "bg-background",
        isFullscreen && "fixed inset-4 z-50 shadow-2xl"
      )}
      style={{
        height: isFullscreen ? "auto" : height,
        maxHeight: isFullscreen ? "none" : maxHeight,
      }}
    >
      {/* 헤더 툴바 */}
      <div className="flex items-center justify-between px-3 py-2 border-b border-border bg-muted/30">
        <div className="flex items-center gap-2">
          {title && <h3 className="text-sm font-medium">{title}</h3>}
          <span className="text-xs text-muted-foreground">
            ({data.length}건)
          </span>
        </div>

        <div className="flex items-center gap-1">
          {allowExpandAll && (
            <>
              <Button
                variant="ghost"
                size="sm"
                className="h-7 px-2"
                onClick={handleExpandAll}
                title="전체 확장"
              >
                <ChevronDown className="h-4 w-4" />
              </Button>

              <Button
                variant="ghost"
                size="sm"
                className="h-7 px-2"
                onClick={handleCollapseAll}
                title="전체 축소"
              >
                <ChevronRight className="h-4 w-4" />
              </Button>
            </>
          )}

          {exportConfig?.excel && (
            <Button
              variant="ghost"
              size="sm"
              className="h-7 px-2"
              onClick={handleExportCSV}
              title="CSV 내보내기"
            >
              <Download className="h-4 w-4" />
            </Button>
          )}

          <Button
            variant="ghost"
            size="sm"
            className="h-7 px-2"
            onClick={() => setIsFullscreen(!isFullscreen)}
            title={isFullscreen ? "원래 크기" : "전체 화면"}
          >
            {isFullscreen ? (
              <Minimize2 className="h-4 w-4" />
            ) : (
              <Maximize2 className="h-4 w-4" />
            )}
          </Button>
        </div>
      </div>

      {/* 피벗 테이블 */}
      <div className="flex-1 overflow-auto">
        <table className="w-full border-collapse">
          <thead>
            {/* 열 헤더 */}
            <tr className="bg-muted/50">
              {/* 좌상단 코너 (행 필드 라벨) */}
              <th
                className={cn(
                  "border-r border-b border-border",
                  "px-2 py-2 text-left text-xs font-medium",
                  "bg-muted sticky left-0 top-0 z-20"
                )}
                rowSpan={columnFields.length > 0 ? 2 : 1}
              >
                {rowFields.map((f) => f.caption).join(" / ") || "항목"}
              </th>

              {/* 열 헤더 셀 */}
              {flatColumns.map((col, idx) => (
                <th
                  key={idx}
                  className={cn(
                    "border-r border-b border-border",
                    "px-2 py-1.5 text-center text-xs font-medium",
                    "bg-muted/70 sticky top-0 z-10"
                  )}
                  colSpan={dataFields.length || 1}
                >
                  {col.caption || "(전체)"}
                </th>
              ))}

              {/* 행 총계 헤더 */}
              {totals?.showRowGrandTotals && (
                <th
                  className={cn(
                    "border-b border-border",
                    "px-2 py-1.5 text-center text-xs font-medium",
                    "bg-primary/10 sticky top-0 z-10"
                  )}
                  colSpan={dataFields.length || 1}
                >
                  총계
                </th>
              )}
            </tr>

            {/* 데이터 필드 라벨 (다중 데이터 필드인 경우) */}
            {dataFields.length > 1 && (
              <tr className="bg-muted/30">
                {flatColumns.map((col, colIdx) => (
                  <React.Fragment key={colIdx}>
                    {dataFields.map((df, dfIdx) => (
                      <th
                        key={`${colIdx}-${dfIdx}`}
                        className={cn(
                          "border-r border-b border-border",
                          "px-2 py-1 text-center text-xs font-normal",
                          "text-muted-foreground"
                        )}
                      >
                        {df.caption}
                      </th>
                    ))}
                  </React.Fragment>
                ))}
                {totals?.showRowGrandTotals &&
                  dataFields.map((df, dfIdx) => (
                    <th
                      key={`total-${dfIdx}`}
                      className={cn(
                        "border-r border-b border-border",
                        "px-2 py-1 text-center text-xs font-normal",
                        "bg-primary/5 text-muted-foreground"
                      )}
                    >
                      {df.caption}
                    </th>
                  ))}
              </tr>
            )}
          </thead>

          <tbody>
            {flatRows.map((row, rowIdx) => (
              <tr
                key={rowIdx}
                className={cn(
                  style?.alternateRowColors &&
                    rowIdx % 2 === 1 &&
                    "bg-muted/20"
                )}
              >
                {/* 행 헤더 */}
                <RowHeaderCell
                  row={row}
                  rowFields={rowFields}
                  onToggleExpand={handleToggleRowExpand}
                />

                {/* 데이터 셀 */}
                {flatColumns.map((col, colIdx) => {
                  const cellKey = `${pathToKey(row.path)}|||${pathToKey(col.path)}`;
                  const values = dataMatrix.get(cellKey) || [];

                  return (
                    <DataCell
                      key={colIdx}
                      values={values}
                      onClick={
                        onCellClick
                          ? () => handleCellClick(row.path, col.path, values)
                          : undefined
                      }
                    />
                  );
                })}

                {/* 행 총계 */}
                {totals?.showRowGrandTotals && (
                  <DataCell
                    values={grandTotals.row.get(pathToKey(row.path)) || []}
                    isTotal
                  />
                )}
              </tr>
            ))}

            {/* 열 총계 행 */}
            {totals?.showColumnGrandTotals && (
              <tr className="bg-primary/5 font-medium">
                <td
                  className={cn(
                    "border-r border-b border-border",
                    "px-2 py-1.5 text-left text-sm",
                    "bg-primary/10 sticky left-0"
                  )}
                >
                  총계
                </td>

                {flatColumns.map((col, colIdx) => (
                  <DataCell
                    key={colIdx}
                    values={grandTotals.column.get(pathToKey(col.path)) || []}
                    isTotal
                  />
                ))}

                {/* 대총합 */}
                {totals?.showRowGrandTotals && (
                  <DataCell values={grandTotals.grand} isTotal />
                )}
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
};

export default PivotGridComponent;
