"use client";

/**
 * pop-string-list 런타임 컴포넌트
 *
 * 리스트 모드: 엑셀형 행/열 (CSS Grid)
 * 카드 모드: 셀 병합 가능한 카드 (CSS Grid + colSpan/rowSpan)
 * 오버플로우: visibleRows 제한 + "전체보기" 확장
 */

import { useState, useEffect, useCallback } from "react";
import { ChevronDown, ChevronUp, Loader2, AlertCircle, ChevronsUpDown } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { dataApi } from "@/lib/api/data";
import type {
  PopStringListConfig,
  CardGridConfig,
  ListColumnConfig,
  CardCellDefinition,
} from "./types";

// ===== 유틸리티 =====

/**
 * 컬럼명에서 실제 데이터 키를 추출
 * 조인 컬럼은 "테이블명.컬럼명" 형식으로 저장됨 -> "컬럼명"만 추출
 * 일반 컬럼은 그대로 반환
 */
function resolveColumnName(name: string): string {
  if (!name) return name;
  const dotIdx = name.lastIndexOf(".");
  return dotIdx >= 0 ? name.substring(dotIdx + 1) : name;
}

// ===== Props =====

interface PopStringListComponentProps {
  config?: PopStringListConfig;
  className?: string;
}

// 테이블 행 데이터 타입
type RowData = Record<string, unknown>;

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

export function PopStringListComponent({
  config,
  className,
}: PopStringListComponentProps) {
  const displayMode = config?.displayMode || "list";
  const header = config?.header;
  const overflow = config?.overflow;
  const dataSource = config?.dataSource;
  const listColumns = config?.listColumns || [];
  const cardGrid = config?.cardGrid;

  // 데이터 상태
  const [rows, setRows] = useState<RowData[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [expanded, setExpanded] = useState(false);

  // 오버플로우 계산 (JSON 복원 시 string 유입 방어)
  const visibleRows = Number(overflow?.visibleRows) || 5;
  const maxExpandRows = Number(overflow?.maxExpandRows) || 20;
  const showExpandButton = overflow?.showExpandButton ?? true;

  // 표시할 데이터 슬라이스
  const visibleData = expanded
    ? rows.slice(0, maxExpandRows)
    : rows.slice(0, visibleRows);
  const hasMore = rows.length > visibleRows;

  // 확장/축소 토글
  const toggleExpanded = useCallback(() => {
    setExpanded((prev) => !prev);
  }, []);

  // 데이터 조회
  useEffect(() => {
    if (!dataSource?.tableName) {
      setLoading(false);
      setRows([]);
      return;
    }

    const fetchData = async () => {
      setLoading(true);
      setError(null);

      try {
        // 필터 조건 구성
        const filters: Record<string, unknown> = {};
        if (dataSource.filters && dataSource.filters.length > 0) {
          dataSource.filters.forEach((f) => {
            if (f.column && f.value) {
              filters[f.column] = f.value;
            }
          });
        }

        // 정렬 조건
        const sortBy = dataSource.sort?.column;
        const sortOrder = dataSource.sort?.direction;

        // 개수 제한 (string 유입 방어: Number 캐스팅)
        const size =
          dataSource.limit?.mode === "limited" && dataSource.limit?.count
            ? Number(dataSource.limit.count)
            : maxExpandRows;

        const result = await dataApi.getTableData(dataSource.tableName, {
          page: 1,
          size,
          sortBy: sortOrder ? sortBy : undefined,
          sortOrder,
          filters: Object.keys(filters).length > 0 ? filters : undefined,
        });

        setRows(result.data || []);
      } catch (err) {
        const message =
          err instanceof Error ? err.message : "데이터 조회 실패";
        setError(message);
        setRows([]);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [dataSource, maxExpandRows]);

  // 로딩 상태
  if (loading) {
    return (
      <div className="flex h-full w-full items-center justify-center">
        <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
      </div>
    );
  }

  // 에러 상태
  if (error) {
    return (
      <div className="flex h-full w-full flex-col items-center justify-center gap-1 p-2">
        <AlertCircle className="h-4 w-4 text-destructive" />
        <span className="text-xs text-destructive">{error}</span>
      </div>
    );
  }

  // 테이블 미선택
  if (!dataSource?.tableName) {
    return (
      <div className="flex h-full w-full items-center justify-center p-2">
        <span className="text-xs text-muted-foreground">
          테이블을 선택하세요
        </span>
      </div>
    );
  }

  // 데이터 없음
  if (rows.length === 0) {
    return (
      <div className="flex h-full w-full items-center justify-center p-2">
        <span className="text-xs text-muted-foreground">
          데이터가 없습니다
        </span>
      </div>
    );
  }

  return (
    <div className={`flex h-full w-full flex-col overflow-hidden ${className || ""}`}>
      {/* 헤더 */}
      {header?.enabled && header.label && (
        <div className="shrink-0 border-b px-3 py-2">
          <span className="text-sm font-medium">{header.label}</span>
        </div>
      )}

      {/* 컨텐츠 */}
      <div className="flex-1 overflow-auto">
        {displayMode === "list" ? (
          <ListModeView
            columns={listColumns}
            data={visibleData}
          />
        ) : (
          <CardModeView
            cardGrid={cardGrid}
            data={visibleData}
          />
        )}
      </div>

      {/* 전체보기 버튼 */}
      {showExpandButton && hasMore && (
        <div className="shrink-0 border-t px-3 py-1.5">
          <Button
            variant="ghost"
            size="sm"
            onClick={toggleExpanded}
            className="h-7 w-full text-xs text-muted-foreground"
          >
            {expanded ? (
              <>
                <ChevronUp className="mr-1 h-3 w-3" />
                접기
              </>
            ) : (
              <>
                <ChevronDown className="mr-1 h-3 w-3" />
                전체보기 ({rows.length}건)
              </>
            )}
          </Button>
        </div>
      )}
    </div>
  );
}

// ===== 리스트 모드 =====

interface ListModeViewProps {
  columns: ListColumnConfig[];
  data: RowData[];
}

function ListModeView({ columns, data }: ListModeViewProps) {
  // 런타임 컬럼 전환 상태
  // key: 컬럼 인덱스, value: 현재 활성 컬럼명 (alternateColumns 중 하나 또는 원래 columnName)
  const [activeColumns, setActiveColumns] = useState<Record<number, string>>({});

  if (columns.length === 0) {
    return (
      <div className="flex h-full items-center justify-center p-2">
        <span className="text-xs text-muted-foreground">
          컬럼을 설정하세요
        </span>
      </div>
    );
  }

  const gridCols = columns.map((c) => c.width || "1fr").join(" ");

  return (
    <div className="w-full">
      {/* 헤더 행 */}
      <div
        className="border-b bg-muted/50"
        style={{ display: "grid", gridTemplateColumns: gridCols }}
      >
        {columns.map((col, colIdx) => {
          const hasAlternates = (col.alternateColumns || []).length > 0;
          const currentColName = activeColumns[colIdx] || col.columnName;
          // 원래 컬럼이면 기존 라벨, 전환된 컬럼이면 컬럼명 부분만 표시
          const currentLabel =
            currentColName === col.columnName
              ? col.label
              : resolveColumnName(currentColName);

          if (hasAlternates) {
            // 전환 가능한 헤더: Popover 드롭다운
            return (
              <Popover key={col.columnName}>
                <PopoverTrigger asChild>
                  <button
                    className="flex w-full items-center justify-between px-2 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted/80 transition-colors"
                    style={{ textAlign: col.align || "left" }}
                  >
                    <span className="truncate">{currentLabel}</span>
                    <ChevronsUpDown className="ml-1 h-3 w-3 shrink-0 opacity-50" />
                  </button>
                </PopoverTrigger>
                <PopoverContent className="w-auto min-w-[120px] p-1" align="start">
                  <div className="flex flex-col">
                    {/* 원래 컬럼 */}
                    <button
                      className={cn(
                        "rounded px-2 py-1 text-left text-xs transition-colors",
                        currentColName === col.columnName
                          ? "bg-primary/10 text-primary font-medium"
                          : "hover:bg-muted"
                      )}
                      onClick={() => {
                        setActiveColumns((prev) => {
                          const next = { ...prev };
                          delete next[colIdx];
                          return next;
                        });
                      }}
                    >
                      {col.label} (기본)
                    </button>
                    {/* 대체 컬럼들 */}
                    {(col.alternateColumns || []).map((altCol) => {
                      const altLabel = resolveColumnName(altCol);
                      return (
                        <button
                          key={altCol}
                          className={cn(
                            "rounded px-2 py-1 text-left text-xs transition-colors",
                            currentColName === altCol
                              ? "bg-primary/10 text-primary font-medium"
                              : "hover:bg-muted"
                          )}
                          onClick={() => {
                            setActiveColumns((prev) => ({
                              ...prev,
                              [colIdx]: altCol,
                            }));
                          }}
                        >
                          {altLabel}
                        </button>
                      );
                    })}
                  </div>
                </PopoverContent>
              </Popover>
            );
          }

          // 전환 없는 일반 헤더
          return (
            <div
              key={col.columnName}
              className="px-2 py-1.5 text-xs font-medium text-muted-foreground"
              style={{ textAlign: col.align || "left" }}
            >
              {col.label}
            </div>
          );
        })}
      </div>

      {/* 데이터 행 */}
      {data.map((row, i) => (
        <div
          key={i}
          className="border-b last:border-b-0 hover:bg-muted/30 transition-colors"
          style={{ display: "grid", gridTemplateColumns: gridCols }}
        >
          {columns.map((col, colIdx) => {
            const currentColName = activeColumns[colIdx] || col.columnName;
            const resolvedKey = resolveColumnName(currentColName);
            return (
              <div
                key={`${col.columnName}-${colIdx}`}
                className="px-2 py-1.5 text-xs truncate"
                style={{ textAlign: col.align || "left" }}
              >
                {String(row[resolvedKey] ?? "")}
              </div>
            );
          })}
        </div>
      ))}
    </div>
  );
}

// ===== 카드 모드 =====

interface CardModeViewProps {
  cardGrid?: CardGridConfig;
  data: RowData[];
}

function CardModeView({ cardGrid, data }: CardModeViewProps) {
  if (!cardGrid || (cardGrid.cells || []).length === 0) {
    return (
      <div className="flex h-full items-center justify-center p-2">
        <span className="text-xs text-muted-foreground">
          카드 레이아웃을 설정하세요
        </span>
      </div>
    );
  }

  return (
    <div className="space-y-2 p-2">
      {data.map((row, i) => (
        <div
          key={i}
          className="rounded-md border"
          style={{
            display: "grid",
            gridTemplateColumns:
              cardGrid.colWidths && cardGrid.colWidths.length > 0
                ? cardGrid.colWidths.map((w) => `minmax(30px, ${w || "1fr"})`).join(" ")
                : "1fr",
            gridTemplateRows:
              cardGrid.rowHeights && cardGrid.rowHeights.length > 0
                ? cardGrid.rowHeights
                    .map((h) => {
                      if (!h) return "minmax(32px, auto)";
                      // px 값 -> minmax(Npx, auto): 최소 높이 보장 + 컨텐츠에 맞게 확장
                      if (h.endsWith("px")) {
                        return `minmax(${h}, auto)`;
                      }
                      // fr 값 -> 마이그레이션 호환: px 변환 후 minmax 적용
                      const px = Math.round(parseFloat(h) * 32) || 32;
                      return `minmax(${px}px, auto)`;
                    })
                    .join(" ")
                : `repeat(${Number(cardGrid.rows) || 1}, minmax(32px, auto))`,
            gap: `${Number(cardGrid.gap) || 0}px`,
          }}
        >
          {(cardGrid.cells || []).map((cell) => {
            // 가로 정렬 매핑
            const justifyMap = { left: "flex-start", center: "center", right: "flex-end" } as const;
            const alignItemsMap = { top: "flex-start", middle: "center", bottom: "flex-end" } as const;
            return (
              <div
                key={cell.id}
                className="overflow-hidden p-1.5"
                style={{
                  display: "flex",
                  flexDirection: "column",
                  justifyContent: alignItemsMap[cell.verticalAlign || "top"],
                  alignItems: justifyMap[cell.align || "left"],
                  gridColumn: `${Number(cell.col) || 1} / span ${Number(cell.colSpan) || 1}`,
                  gridRow: `${Number(cell.row) || 1} / span ${Number(cell.rowSpan) || 1}`,
                  border: cardGrid.showBorder
                    ? "1px solid hsl(var(--border))"
                    : "none",
                }}
              >
                {renderCellContent(cell, row)}
              </div>
            );
          })}
        </div>
      ))}
    </div>
  );
}

// ===== 셀 컨텐츠 렌더링 =====

function renderCellContent(cell: CardCellDefinition, row: RowData): React.ReactNode {
  const value = row[cell.columnName];
  const displayValue = value != null ? String(value) : "";

  switch (cell.type) {
    case "image":
      return displayValue ? (
        <img
          src={displayValue}
          alt={cell.label || cell.columnName}
          className="h-full max-h-[200px] w-full object-cover rounded"
        />
      ) : (
        <div className="flex h-full items-center justify-center bg-muted rounded">
          <span className="text-[10px] text-muted-foreground">No Image</span>
        </div>
      );

    case "badge":
      return (
        <span className="inline-flex items-center rounded-full bg-primary/10 px-2 py-0.5 text-[10px] font-medium text-primary">
          {displayValue}
        </span>
      );

    case "button":
      return (
        <Button variant="outline" size="sm" className="h-6 text-[10px]">
          {cell.label || displayValue}
        </Button>
      );

    case "text":
    default: {
      // 글자 크기 매핑
      const fontSizeClass =
        cell.fontSize === "sm"
          ? "text-[10px]"
          : cell.fontSize === "lg"
            ? "text-sm"
            : "text-xs"; // md (기본)
      const isLabelLeft = cell.labelPosition === "left";

      return (
        <div className={isLabelLeft ? "flex items-baseline gap-1" : "flex flex-col"}>
          {cell.label && (
            <span className="text-[10px] text-muted-foreground shrink-0">
              {cell.label}{isLabelLeft ? ":" : ""}
            </span>
          )}
          <span className={`${fontSizeClass} truncate`}>{displayValue}</span>
        </div>
      );
    }
  }
}
