"use client";

import React, { useState, useEffect, useCallback } from "react";
import { DashboardElement, QueryResult, ListWidgetConfig, FieldGroup } from "../types";
import { Button } from "@/components/ui/button";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Card } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { getApiUrl } from "@/lib/utils/apiUrl";
import { Truck, Clock, MapPin, Package, Info } from "lucide-react";

interface ListWidgetProps {
  element: DashboardElement;
  onConfigUpdate?: (config: Partial<DashboardElement>) => void;
}

/**
 * 리스트 위젯 컴포넌트
 * - DB 쿼리 또는 REST API로 데이터 가져오기
 * - 테이블 형태로 데이터 표시
 * - 페이지네이션, 정렬, 검색 기능
 */
export function ListWidget({ element, onConfigUpdate }: ListWidgetProps) {
  const [data, setData] = useState<QueryResult | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [currentPage, setCurrentPage] = useState(1);

  // 행 상세 팝업 상태
  const [detailPopupOpen, setDetailPopupOpen] = useState(false);
  const [detailPopupData, setDetailPopupData] = useState<Record<string, any> | null>(null);
  const [detailPopupLoading, setDetailPopupLoading] = useState(false);
  const [additionalDetailData, setAdditionalDetailData] = useState<Record<string, any> | null>(null);

  const config = element.listConfig || {
    columnMode: "auto",
    viewMode: "table",
    columns: [],
    pageSize: 10,
    enablePagination: true,
    showHeader: true,
    stripedRows: true,
    compactMode: false,
    cardColumns: 3,
  };

  // 행 클릭 핸들러 - 팝업 열기
  const handleRowClick = useCallback(
    async (row: Record<string, any>) => {
      // 팝업이 비활성화되어 있으면 무시
      if (!config.rowDetailPopup?.enabled) return;

      setDetailPopupData(row);
      setDetailPopupOpen(true);
      setAdditionalDetailData(null);
      setDetailPopupLoading(false);

      // 추가 데이터 조회 설정이 있으면 실행
      const additionalQuery = config.rowDetailPopup?.additionalQuery;
      if (additionalQuery?.enabled) {
        const queryMode = additionalQuery.queryMode || "table";

        // 커스텀 쿼리 모드
        if (queryMode === "custom" && additionalQuery.customQuery) {
          setDetailPopupLoading(true);
          try {
            // 쿼리에서 {컬럼명} 형태의 파라미터를 실제 값으로 치환
            let query = additionalQuery.customQuery;
            // console.log("🔍 [ListWidget] 커스텀 쿼리 파라미터 치환 시작");
            // console.log("🔍 [ListWidget] 클릭한 행 데이터:", row);
            // console.log("🔍 [ListWidget] 행 컬럼 목록:", Object.keys(row));

            Object.keys(row).forEach((key) => {
              const value = row[key];
              const placeholder = new RegExp(`\\{${key}\\}`, "g");
              // SQL 인젝션 방지를 위해 값 이스케이프
              const safeValue = typeof value === "string" ? value.replace(/'/g, "''") : value;
              query = query.replace(placeholder, String(safeValue ?? ""));
              // console.log(`🔍 [ListWidget] 치환: {${key}} → ${safeValue}`);
            });

            // console.log("🔍 [ListWidget] 최종 쿼리:", query);

            const { dashboardApi } = await import("@/lib/api/dashboard");
            const result = await dashboardApi.executeQuery(query);
            // console.log("🔍 [ListWidget] 쿼리 결과:", result);

            if (result.success && result.rows.length > 0) {
              setAdditionalDetailData(result.rows[0]);
            } else {
              setAdditionalDetailData({});
            }
          } catch (error) {
            console.error("커스텀 쿼리 실행 실패:", error);
            setAdditionalDetailData({});
          } finally {
            setDetailPopupLoading(false);
          }
        }
        // 테이블 조회 모드
        else if (queryMode === "table" && additionalQuery.tableName && additionalQuery.matchColumn) {
          const sourceColumn = additionalQuery.sourceColumn || additionalQuery.matchColumn;
          const matchValue = row[sourceColumn];

          if (matchValue !== undefined && matchValue !== null) {
            setDetailPopupLoading(true);
            try {
              const query = `
                SELECT *
                FROM ${additionalQuery.tableName}
                WHERE ${additionalQuery.matchColumn} = '${matchValue}'
                LIMIT 1;
              `;

              const { dashboardApi } = await import("@/lib/api/dashboard");
              const result = await dashboardApi.executeQuery(query);

              if (result.success && result.rows.length > 0) {
                setAdditionalDetailData(result.rows[0]);
              } else {
                setAdditionalDetailData({});
              }
            } catch (error) {
              console.error("추가 데이터 로드 실패:", error);
              setAdditionalDetailData({});
            } finally {
              setDetailPopupLoading(false);
            }
          }
        }
      }
    },
    [config.rowDetailPopup],
  );

  // 값 포맷팅 함수
  const formatValue = (value: any, format?: string): string => {
    if (value === null || value === undefined) return "-";

    switch (format) {
      case "date":
        try {
          const dateVal = new Date(value);
          return dateVal.toLocaleDateString("ko-KR", { timeZone: "Asia/Seoul" });
        } catch {
          return String(value);
        }
      case "datetime":
        try {
          const dateVal = new Date(value);
          return dateVal.toLocaleString("ko-KR", { timeZone: "Asia/Seoul" });
        } catch {
          return String(value);
        }
      case "number":
        return Number(value).toLocaleString("ko-KR");
      case "currency":
        return `${Number(value).toLocaleString("ko-KR")}원`;
      case "boolean":
        return value ? "예" : "아니오";
      case "distance":
        return typeof value === "number" ? `${value.toFixed(1)} km` : String(value);
      case "duration":
        return typeof value === "number" ? `${value}분` : String(value);
      default:
        return String(value);
    }
  };

  // 아이콘 렌더링
  const renderIcon = (icon?: string, color?: string) => {
    const colorClass =
      color === "blue"
        ? "text-blue-600"
        : color === "orange"
          ? "text-orange-600"
          : color === "green"
            ? "text-green-600"
            : color === "red"
              ? "text-red-600"
              : color === "purple"
                ? "text-purple-600"
                : "text-gray-600";

    switch (icon) {
      case "truck":
        return <Truck className={`h-4 w-4 ${colorClass}`} />;
      case "clock":
        return <Clock className={`h-4 w-4 ${colorClass}`} />;
      case "map":
        return <MapPin className={`h-4 w-4 ${colorClass}`} />;
      case "package":
        return <Package className={`h-4 w-4 ${colorClass}`} />;
      default:
        return <Info className={`h-4 w-4 ${colorClass}`} />;
    }
  };

  // 필드 그룹 렌더링
  const renderFieldGroup = (group: FieldGroup, data: Record<string, any>) => {
    const colorClass =
      group.color === "blue"
        ? "text-blue-600"
        : group.color === "orange"
          ? "text-orange-600"
          : group.color === "green"
            ? "text-green-600"
            : group.color === "red"
              ? "text-red-600"
              : group.color === "purple"
                ? "text-purple-600"
                : "text-gray-600";

    return (
      <div key={group.id} className="rounded-lg border p-4">
        <div className={`mb-3 flex items-center gap-2 text-sm font-semibold ${colorClass}`}>
          {renderIcon(group.icon, group.color)}
          {group.title}
        </div>
        <div className="grid grid-cols-1 gap-3 text-xs sm:grid-cols-2">
          {group.fields.map((field) => (
            <div key={field.column} className="flex flex-col gap-0.5">
              <span className="text-muted-foreground text-[10px] font-medium tracking-wide uppercase">
                {field.label}
              </span>
              <span className="font-medium break-words">{formatValue(data[field.column], field.format)}</span>
            </div>
          ))}
        </div>
      </div>
    );
  };

  // 기본 필드 그룹 생성 (설정이 없을 경우)
  const getDefaultFieldGroups = (row: Record<string, any>, additional: Record<string, any> | null): FieldGroup[] => {
    const groups: FieldGroup[] = [];
    const displayColumns = config.rowDetailPopup?.additionalQuery?.displayColumns;
    const queryMode = config.rowDetailPopup?.additionalQuery?.queryMode || "table";

    // 커스텀 쿼리 모드일 때는 additional 데이터를 우선 사용
    // row와 additional을 병합하되, 커스텀 쿼리 결과(additional)가 우선
    const mergedData =
      queryMode === "custom" && additional && Object.keys(additional).length > 0
        ? { ...row, ...additional } // additional이 row를 덮어씀
        : row;

    // 기본 정보 그룹 - displayColumns가 있으면 해당 컬럼만, 없으면 전체
    let basicFields: { column: string; label: string }[] = [];

    if (displayColumns && displayColumns.length > 0) {
      // DisplayColumnConfig 형식 지원
      // 커스텀 쿼리 모드일 때는 mergedData에서 컬럼 확인
      basicFields = displayColumns
        .map((colConfig) => {
          const column = typeof colConfig === "object" ? colConfig.column : colConfig;
          const label = typeof colConfig === "object" ? colConfig.label : colConfig;
          return { column, label };
        })
        .filter((item) => item.column in mergedData);
    } else {
      // 전체 컬럼 - 커스텀 쿼리 모드일 때는 additional 컬럼만 표시
      if (queryMode === "custom" && additional && Object.keys(additional).length > 0) {
        basicFields = Object.keys(additional).map((key) => ({ column: key, label: key }));
      } else {
        basicFields = Object.keys(row).map((key) => ({ column: key, label: key }));
      }
    }

    groups.push({
      id: "basic",
      title: "기본 정보",
      icon: "info",
      color: "gray",
      fields: basicFields.map((item) => ({
        column: item.column,
        label: item.label,
        format: "text",
      })),
    });

    // 추가 데이터가 있고 vehicles 테이블인 경우 운행/공차 정보 추가 (테이블 모드일 때만)
    if (queryMode === "table" && additional && Object.keys(additional).length > 0) {
      // 운행 정보
      if (additional.last_trip_start || additional.last_trip_end) {
        groups.push({
          id: "trip",
          title: "운행 정보",
          icon: "truck",
          color: "blue",
          fields: [
            { column: "last_trip_start", label: "시작", format: "datetime" },
            { column: "last_trip_end", label: "종료", format: "datetime" },
            { column: "last_trip_distance", label: "거리", format: "distance" },
            { column: "last_trip_time", label: "시간", format: "duration" },
            { column: "departure", label: "출발지", format: "text" },
            { column: "arrival", label: "도착지", format: "text" },
          ],
        });
      }

      // 공차 정보
      if (additional.last_empty_start) {
        groups.push({
          id: "empty",
          title: "공차 정보",
          icon: "package",
          color: "orange",
          fields: [
            { column: "last_empty_start", label: "시작", format: "datetime" },
            { column: "last_empty_end", label: "종료", format: "datetime" },
            { column: "last_empty_distance", label: "거리", format: "distance" },
            { column: "last_empty_time", label: "시간", format: "duration" },
          ],
        });
      }
    }

    return groups;
  };

  // 데이터 로드
  useEffect(() => {
    const loadData = async () => {
      if (!element.dataSource || (!element.dataSource.query && !element.dataSource.endpoint)) {
        return;
      }

      setIsLoading(true);
      setError(null);

      try {
        let queryResult: QueryResult;

        // REST API vs Database 분기
        if (element.dataSource.type === "api" && element.dataSource.endpoint) {
          // REST API - 백엔드 프록시를 통한 호출
          const params = new URLSearchParams();
          if (element.dataSource.queryParams) {
            Object.entries(element.dataSource.queryParams).forEach(([key, value]) => {
              if (key && value) {
                params.append(key, value);
              }
            });
          }

          // 요청 메서드 (기본값: GET)
          const requestMethod = element.dataSource.method || "GET";

          // 요청 body (POST, PUT, PATCH인 경우)
          let requestBody = undefined;
          if (["POST", "PUT", "PATCH"].includes(requestMethod) && element.dataSource.body) {
            try {
              requestBody =
                typeof element.dataSource.body === "string"
                  ? JSON.parse(element.dataSource.body)
                  : element.dataSource.body;
            } catch {
              requestBody = element.dataSource.body;
            }
          }

          // headers를 KeyValuePair[] 에서 객체로 변환
          const headersObj: Record<string, string> = {};
          if (element.dataSource.headers && Array.isArray(element.dataSource.headers)) {
            element.dataSource.headers.forEach((h: any) => {
              if (h.key && h.value) {
                headersObj[h.key] = h.value;
              }
            });
          } else if (element.dataSource.headers && typeof element.dataSource.headers === "object") {
            Object.assign(headersObj, element.dataSource.headers);
          }

          const response = await fetch(getApiUrl("/api/dashboards/fetch-external-api"), {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            credentials: "include",
            body: JSON.stringify({
              url: element.dataSource.endpoint,
              method: requestMethod,
              headers: headersObj,
              queryParams: Object.fromEntries(params),
              body: requestBody,
              externalConnectionId: element.dataSource.externalConnectionId,
            }),
          });

          if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
          }

          const result = await response.json();

          if (!result.success) {
            throw new Error(result.message || "외부 API 호출 실패");
          }

          const apiData = result.data;

          // JSON Path 처리
          let processedData = apiData;
          if (element.dataSource.jsonPath) {
            const paths = element.dataSource.jsonPath.split(".");
            for (const path of paths) {
              if (processedData && typeof processedData === "object" && path in processedData) {
                processedData = processedData[path];
              } else {
                throw new Error(`JSON Path "${element.dataSource.jsonPath}"에서 데이터를 찾을 수 없습니다`);
              }
            }
          }

          const rows = Array.isArray(processedData) ? processedData : [processedData];
          const columns = rows.length > 0 ? Object.keys(rows[0]) : [];

          queryResult = {
            columns,
            rows,
            totalRows: rows.length,
            executionTime: 0,
          };
        } else if (element.dataSource.query) {
          // Database (현재 DB 또는 외부 DB)
          if (element.dataSource.connectionType === "external" && element.dataSource.externalConnectionId) {
            // 외부 DB
            const { ExternalDbConnectionAPI } = await import("@/lib/api/externalDbConnection");
            const externalResult = await ExternalDbConnectionAPI.executeQuery(
              parseInt(element.dataSource.externalConnectionId),
              element.dataSource.query,
            );
            if (!externalResult.success) {
              throw new Error(externalResult.message || "외부 DB 쿼리 실행 실패");
            }
            queryResult = {
              columns: externalResult.data.columns,
              rows: externalResult.data.rows,
              totalRows: externalResult.data.rowCount,
              executionTime: 0,
            };
          } else {
            // 현재 DB
            const { dashboardApi } = await import("@/lib/api/dashboard");
            const result = await dashboardApi.executeQuery(element.dataSource.query);
            queryResult = {
              columns: result.columns,
              rows: result.rows,
              totalRows: result.rowCount,
              executionTime: 0,
            };
          }
        } else {
          throw new Error("데이터 소스가 올바르게 설정되지 않았습니다");
        }

        setData(queryResult);
      } catch (err) {
        setError(err instanceof Error ? err.message : "데이터 로딩 실패");
      } finally {
        setIsLoading(false);
      }
    };

    loadData();

    // 자동 새로고침 설정
    const refreshInterval = element.dataSource?.refreshInterval;
    if (refreshInterval && refreshInterval > 0) {
      const interval = setInterval(loadData, refreshInterval);
      return () => clearInterval(interval);
    }
  }, [
    element.dataSource?.query,
    element.dataSource?.connectionType,
    element.dataSource?.externalConnectionId,
    element.dataSource?.endpoint,
    element.dataSource?.refreshInterval,
  ]);

  // 로딩 중
  if (isLoading) {
    return (
      <div className="flex h-full w-full items-center justify-center">
        <div className="text-center">
          <div className="border-primary mx-auto mb-2 h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" />
          <div className="text-foreground text-sm">데이터 로딩 중...</div>
        </div>
      </div>
    );
  }

  // 에러
  if (error) {
    return (
      <div className="flex h-full w-full items-center justify-center">
        <div className="text-center">
          <div className="mb-2 text-2xl">⚠️</div>
          <div className="text-destructive text-sm font-medium">오류 발생</div>
          <div className="text-muted-foreground mt-1 text-xs">{error}</div>
        </div>
      </div>
    );
  }

  // 데이터 없음
  if (!data) {
    return (
      <div className="flex h-full w-full flex-col items-center justify-center gap-4 p-4">
        <div className="text-center">
          <div className="mb-2 text-4xl">📋</div>
          <div className="text-foreground text-sm font-medium">리스트를 설정하세요</div>
          <div className="text-muted-foreground mt-1 text-xs">⚙️ 버튼을 클릭하여 데이터 소스와 컬럼을 설정해주세요</div>
        </div>
      </div>
    );
  }

  // 컬럼 설정이 없으면 자동으로 모든 컬럼 표시
  const displayColumns =
    config.columns.length > 0
      ? config.columns
      : data.columns.map((col) => ({
          id: col,
          name: col,
          dataKey: col,
          visible: true,
        }));

  // 페이지네이션
  const totalPages = Math.ceil(data.rows.length / config.pageSize);
  const startIdx = (currentPage - 1) * config.pageSize;
  const endIdx = startIdx + config.pageSize;
  const paginatedRows = config.enablePagination ? data.rows.slice(startIdx, endIdx) : data.rows;

  return (
    <div className="flex h-full w-full flex-col p-4">
      {/* 제목 - 항상 표시 */}
      <div className="mb-4">
        <h3 className="text-foreground text-sm font-semibold">{element.customTitle || element.title}</h3>
      </div>

      {/* 테이블 뷰 */}
      {config.viewMode === "table" && (
        <div className={`flex-1 overflow-auto rounded-lg ${config.compactMode ? "text-xs" : "text-sm"}`}>
          <Table>
            {config.showHeader && (
              <TableHeader>
                <TableRow>
                  {displayColumns
                    .filter((col) => col.visible)
                    .map((col) => (
                      <TableHead
                        key={col.id}
                        className={col.align === "center" ? "text-center" : col.align === "right" ? "text-right" : ""}
                        style={{ width: col.width ? `${col.width}px` : undefined }}
                      >
                        {col.label || col.name}
                      </TableHead>
                    ))}
                </TableRow>
              </TableHeader>
            )}
            <TableBody>
              {paginatedRows.length === 0 ? (
                <TableRow>
                  <TableCell
                    colSpan={displayColumns.filter((col) => col.visible).length}
                    className="text-muted-foreground text-center"
                  >
                    데이터가 없습니다
                  </TableCell>
                </TableRow>
              ) : (
                paginatedRows.map((row, idx) => (
                  <TableRow
                    key={idx}
                    className={`${config.stripedRows ? "" : ""} ${config.rowDetailPopup?.enabled ? "hover:bg-muted/50 cursor-pointer transition-colors" : ""}`}
                    onClick={() => handleRowClick(row)}
                  >
                    {displayColumns
                      .filter((col) => col.visible)
                      .map((col) => (
                        <TableCell
                          key={col.id}
                          className={col.align === "center" ? "text-center" : col.align === "right" ? "text-right" : ""}
                        >
                          {String(row[col.dataKey || col.field] ?? "")}
                        </TableCell>
                      ))}
                  </TableRow>
                ))
              )}
            </TableBody>
          </Table>
        </div>
      )}

      {/* 카드 뷰 */}
      {config.viewMode === "card" && (
        <div className="flex-1 overflow-auto">
          {paginatedRows.length === 0 ? (
            <div className="text-muted-foreground flex h-full items-center justify-center">데이터가 없습니다</div>
          ) : (
            <div
              className={`grid gap-4 ${config.compactMode ? "text-xs" : "text-sm"}`}
              style={{
                gridTemplateColumns: `repeat(${config.cardColumns || 3}, minmax(0, 1fr))`,
              }}
            >
              {paginatedRows.map((row, idx) => (
                <Card
                  key={idx}
                  className={`p-4 transition-shadow hover:shadow-md ${config.rowDetailPopup?.enabled ? "cursor-pointer" : ""}`}
                  onClick={() => handleRowClick(row)}
                >
                  <div className="space-y-2">
                    {displayColumns
                      .filter((col) => col.visible)
                      .map((col) => (
                        <div key={col.id}>
                          <div className="text-muted-foreground text-xs font-medium">{col.label || col.name}</div>
                          <div
                            className={`text-foreground font-medium ${col.align === "center" ? "text-center" : col.align === "right" ? "text-right" : ""}`}
                          >
                            {String(row[col.dataKey || col.field] ?? "")}
                          </div>
                        </div>
                      ))}
                  </div>
                </Card>
              ))}
            </div>
          )}
        </div>
      )}

      {/* 페이지네이션 */}
      {config.enablePagination && totalPages > 1 && (
        <div className="mt-4 flex items-center justify-between text-sm">
          <div className="text-foreground">
            {startIdx + 1}-{Math.min(endIdx, data.rows.length)} / {data.rows.length}개
          </div>
          <div className="flex gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
              disabled={currentPage === 1}
            >
              이전
            </Button>
            <div className="flex items-center gap-1 px-2">
              <span className="text-foreground">{currentPage}</span>
              <span className="text-muted-foreground">/</span>
              <span className="text-muted-foreground">{totalPages}</span>
            </div>
            <Button
              variant="outline"
              size="sm"
              onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}
              disabled={currentPage === totalPages}
            >
              다음
            </Button>
          </div>
        </div>
      )}

      {/* 행 상세 팝업 */}
      <Dialog open={detailPopupOpen} onOpenChange={setDetailPopupOpen}>
        <DialogContent className="max-h-[90vh] max-w-[600px] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{config.rowDetailPopup?.title || "상세 정보"}</DialogTitle>
            <DialogDescription>
              {detailPopupLoading
                ? "추가 정보를 로딩 중입니다..."
                : detailPopupData
                  ? `${Object.values(detailPopupData)
                      .filter((v) => v && typeof v === "string")
                      .slice(0, 2)
                      .join(" - ")}`
                  : "선택된 항목의 상세 정보입니다."}
            </DialogDescription>
          </DialogHeader>

          {detailPopupLoading ? (
            <div className="flex items-center justify-center py-8">
              <div className="border-primary mx-auto mb-2 h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" />
            </div>
          ) : (
            <div className="space-y-4">
              {detailPopupData && (
                <>
                  {/* 설정된 필드 그룹이 있으면 사용, 없으면 기본 그룹 생성 */}
                  {config.rowDetailPopup?.fieldGroups && config.rowDetailPopup.fieldGroups.length > 0
                    ? // 설정된 필드 그룹 렌더링
                      config.rowDetailPopup.fieldGroups.map((group) =>
                        renderFieldGroup(group, { ...detailPopupData, ...additionalDetailData }),
                      )
                    : // 기본 필드 그룹 렌더링
                      getDefaultFieldGroups(detailPopupData, additionalDetailData).map((group) =>
                        renderFieldGroup(group, { ...detailPopupData, ...additionalDetailData }),
                      )}
                </>
              )}
            </div>
          )}

          <DialogFooter>
            <Button onClick={() => setDetailPopupOpen(false)}>닫기</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
