"use client";

/**
 * pop-card-list 런타임 컴포넌트 (V2 - 이미지 참조 기반 재설계)
 *
 * 테이블의 각 행이 하나의 카드로 표시됩니다.
 * 카드 구조:
 * - 헤더: 코드 + 제목
 * - 본문: 이미지(왼쪽) + 라벨-값 목록(오른쪽)
 */

import React, { useEffect, useState, useRef } from "react";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import type {
  PopCardListConfig,
  CardTemplateConfig,
  CardFieldBinding,
} from "../types";
import { DEFAULT_CARD_IMAGE } from "../types";
import { dataApi } from "@/lib/api/data";

interface PopCardListComponentProps {
  config?: PopCardListConfig;
  className?: string;
}

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

export function PopCardListComponent({
  config,
  className,
}: PopCardListComponentProps) {
  const layoutMode = config?.layoutMode || "grid";
  const cardSize = config?.cardSize || "medium";
  const cardsPerRow = config?.cardsPerRow || 3;
  const dataSource = config?.dataSource;
  const template = config?.cardTemplate;

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

  // 이미지 URL 없는 항목 카운트 (toast 중복 방지용)
  const missingImageCountRef = useRef(0);
  const toastShownRef = useRef(false);

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

    const fetchData = async () => {
      setLoading(true);
      setError(null);
      missingImageCountRef.current = 0;
      toastShownRef.current = false;

      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;

        // 개수 제한
        const size =
          dataSource.limit?.mode === "limited" && dataSource.limit?.count
            ? dataSource.limit.count
            : 100;

        // TODO: 조인 지원은 추후 구현
        // 현재는 단일 테이블 조회만 지원

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

  // 이미지 URL 없는 항목 체크 및 toast 표시
  useEffect(() => {
    if (
      !loading &&
      rows.length > 0 &&
      template?.image?.enabled &&
      template?.image?.imageColumn &&
      !toastShownRef.current
    ) {
      const imageColumn = template.image.imageColumn;
      const missingCount = rows.filter((row) => !row[imageColumn]).length;

      if (missingCount > 0) {
        missingImageCountRef.current = missingCount;
        toastShownRef.current = true;
        toast.warning(
          `${missingCount}개 항목의 이미지 URL이 없어 기본 이미지로 표시됩니다`
        );
      }
    }
  }, [loading, rows, template?.image]);


  // 레이아웃 클래스 (스크롤 지원)
  const layoutClass =
    layoutMode === "vertical"
      ? "flex flex-col gap-3 h-full overflow-y-auto"
      : layoutMode === "horizontal"
        ? "flex flex-row gap-3 h-full overflow-x-auto pb-2"
        : "grid gap-3 h-full overflow-y-auto";

  // 그리드 스타일
  const gridStyle =
    layoutMode === "grid"
      ? { gridTemplateColumns: `repeat(${cardsPerRow}, minmax(0, 1fr))` }
      : undefined;

  // 설정 미완료 상태
  if (!dataSource?.tableName) {
    return (
      <div
        className={`flex h-full w-full items-center justify-center rounded-md border border-dashed bg-muted/30 p-4 ${className || ""}`}
      >
        <p className="text-sm text-muted-foreground">
          데이터 소스를 설정해주세요.
        </p>
      </div>
    );
  }

  // 로딩 중
  if (loading) {
    return (
      <div
        className={`flex h-full w-full items-center justify-center rounded-md border bg-muted/30 p-4 ${className || ""}`}
      >
        <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
      </div>
    );
  }

  // 에러 상태
  if (error) {
    return (
      <div
        className={`flex h-full w-full items-center justify-center rounded-md border border-destructive/50 bg-destructive/10 p-4 ${className || ""}`}
      >
        <p className="text-sm text-destructive">{error}</p>
      </div>
    );
  }

  // 데이터 없음
  if (rows.length === 0) {
    return (
      <div
        className={`flex h-full w-full items-center justify-center rounded-md border border-dashed bg-muted/30 p-4 ${className || ""}`}
      >
        <p className="text-sm text-muted-foreground">데이터가 없습니다.</p>
      </div>
    );
  }

  return (
    <div className={`h-full w-full ${layoutClass} ${className || ""}`} style={gridStyle}>
      {rows.map((row, index) => (
        <Card
          key={index}
          row={row}
          template={template}
          cardSize={cardSize}
          isHorizontal={layoutMode === "horizontal"}
        />
      ))}
    </div>
  );
}

// ===== 카드 크기별 설정 =====
const CARD_SIZE_CONFIG = {
  small: {
    minHeight: "min-h-[120px]",
    minWidth: "min-w-[200px]",
    imageSize: "h-14 w-14",
    padding: "p-2",
    gap: "gap-2",
    headerPadding: "px-2 py-1.5",
    codeText: "text-[10px]",
    titleText: "text-xs",
  },
  medium: {
    minHeight: "min-h-[140px]",
    minWidth: "min-w-[260px]",
    imageSize: "h-16 w-16",
    padding: "p-3",
    gap: "gap-3",
    headerPadding: "px-3 py-2",
    codeText: "text-xs",
    titleText: "text-sm",
  },
  large: {
    minHeight: "min-h-[180px]",
    minWidth: "min-w-[320px]",
    imageSize: "h-20 w-20",
    padding: "p-4",
    gap: "gap-4",
    headerPadding: "px-4 py-2.5",
    codeText: "text-xs",
    titleText: "text-base",
  },
};

// ===== 카드 컴포넌트 =====

function Card({
  row,
  template,
  cardSize,
  isHorizontal,
}: {
  row: RowData;
  template?: CardTemplateConfig;
  cardSize: "small" | "medium" | "large";
  isHorizontal: boolean;
}) {
  const header = template?.header;
  const image = template?.image;
  const body = template?.body;

  // 크기별 설정
  const sizeConfig = CARD_SIZE_CONFIG[cardSize];

  // 헤더 값 추출
  const codeValue = header?.codeField ? row[header.codeField] : null;
  const titleValue = header?.titleField ? row[header.titleField] : null;

  // 이미지 URL 결정
  const imageUrl =
    image?.enabled && image?.imageColumn && row[image.imageColumn]
      ? String(row[image.imageColumn])
      : image?.defaultImage || DEFAULT_CARD_IMAGE;

  return (
    <div
      className={`rounded-lg border bg-card shadow-sm overflow-hidden ${sizeConfig.minHeight} ${
        isHorizontal ? `flex-shrink-0 ${sizeConfig.minWidth}` : ""
      }`}
    >
      {/* 헤더 영역 */}
      {(codeValue !== null || titleValue !== null) && (
        <div className={`border-b bg-muted/30 ${sizeConfig.headerPadding}`}>
          <div className="flex items-center gap-2">
            {codeValue !== null && (
              <span className={`font-semibold text-muted-foreground ${sizeConfig.codeText}`}>
                {formatValue(codeValue)}
              </span>
            )}
            {titleValue !== null && (
              <span className={`font-medium truncate ${sizeConfig.titleText}`}>
                {formatValue(titleValue)}
              </span>
            )}
          </div>
        </div>
      )}

      {/* 본문 영역 */}
      <div className={`flex ${sizeConfig.padding} ${sizeConfig.gap}`}>
        {/* 이미지 (왼쪽) */}
        {image?.enabled && (
          <div className="flex-shrink-0">
            <div className={`${sizeConfig.imageSize} rounded-md border bg-muted/30 flex items-center justify-center overflow-hidden`}>
              <img
                src={imageUrl}
                alt=""
                className="h-full w-full object-contain p-1"
                onError={(e) => {
                  // 이미지 로드 실패 시 기본 이미지로 대체
                  const target = e.target as HTMLImageElement;
                  if (target.src !== DEFAULT_CARD_IMAGE) {
                    target.src = DEFAULT_CARD_IMAGE;
                  }
                }}
              />
            </div>
          </div>
        )}

        {/* 필드 목록 (오른쪽) */}
        <div className="flex-1 min-w-0">
          {body?.fields && body.fields.length > 0 ? (
            <div className={cardSize === "small" ? "space-y-1" : "space-y-1.5"}>
              {body.fields.map((field) => (
                <FieldRow key={field.id} field={field} row={row} cardSize={cardSize} />
              ))}
            </div>
          ) : (
            <div className="flex h-full items-center justify-center text-xs text-muted-foreground">
              본문 필드를 추가하세요
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ===== 필드 행 컴포넌트 =====

function FieldRow({
  field,
  row,
  cardSize,
}: {
  field: CardFieldBinding;
  row: RowData;
  cardSize: "small" | "medium" | "large";
}) {
  const value = row[field.columnName];

  // 크기별 텍스트 설정
  const textSize = cardSize === "small" ? "text-[10px]" : "text-xs";
  const labelMinWidth = cardSize === "small" ? "min-w-[50px]" : "min-w-[60px]";

  return (
    <div className={`flex items-baseline gap-1.5 ${textSize}`}>
      {/* 라벨 */}
      <span className={`flex-shrink-0 text-muted-foreground ${labelMinWidth}`}>
        {field.label}
      </span>
      {/* 값 */}
      <span
        className="font-medium truncate"
        style={field.textColor ? { color: field.textColor } : undefined}
      >
        {formatValue(value)}
      </span>
    </div>
  );
}

// ===== 값 포맷팅 =====

function formatValue(value: unknown): string {
  if (value === null || value === undefined) {
    return "-";
  }
  if (typeof value === "number") {
    return value.toLocaleString();
  }
  if (typeof value === "boolean") {
    return value ? "예" : "아니오";
  }
  if (value instanceof Date) {
    return value.toLocaleDateString();
  }
  // ISO 날짜 문자열 감지 및 포맷
  if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value)) {
    const date = new Date(value);
    if (!isNaN(date.getTime())) {
      // MM-DD 형식으로 표시
      return `${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
    }
  }
  return String(value);
}
