"use client";

/**
 * 집계 노드 속성 편집 패널
 * SUM, COUNT, AVG, MIN, MAX 등 집계 연산 설정
 */

import { useEffect, useState, useCallback } from "react";
import { Plus, Trash2, Calculator, Layers, Filter } from "lucide-react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { useFlowEditorStore } from "@/lib/stores/flowEditorStore";
import type { AggregateNodeData, AggregateFunction } from "@/types/node-editor";

interface AggregatePropertiesProps {
  nodeId: string;
  data: AggregateNodeData;
}

// 집계 함수 옵션
const AGGREGATE_FUNCTIONS: Array<{ value: AggregateFunction; label: string; description: string }> = [
  { value: "SUM", label: "합계 (SUM)", description: "숫자 필드의 합계를 계산합니다" },
  { value: "COUNT", label: "개수 (COUNT)", description: "레코드 개수를 계산합니다" },
  { value: "AVG", label: "평균 (AVG)", description: "숫자 필드의 평균을 계산합니다" },
  { value: "MIN", label: "최소 (MIN)", description: "최소값을 찾습니다" },
  { value: "MAX", label: "최대 (MAX)", description: "최대값을 찾습니다" },
  { value: "FIRST", label: "첫번째 (FIRST)", description: "그룹의 첫 번째 값을 가져옵니다" },
  { value: "LAST", label: "마지막 (LAST)", description: "그룹의 마지막 값을 가져옵니다" },
];

// 비교 연산자 옵션
const OPERATORS = [
  { value: "=", label: "같음 (=)" },
  { value: "!=", label: "다름 (!=)" },
  { value: ">", label: "보다 큼 (>)" },
  { value: ">=", label: "크거나 같음 (>=)" },
  { value: "<", label: "보다 작음 (<)" },
  { value: "<=", label: "작거나 같음 (<=)" },
];

export function AggregateProperties({ nodeId, data }: AggregatePropertiesProps) {
  const { updateNode, nodes, edges } = useFlowEditorStore();

  // 로컬 상태
  const [displayName, setDisplayName] = useState(data.displayName || "집계");
  const [groupByFields, setGroupByFields] = useState(data.groupByFields || []);
  const [aggregations, setAggregations] = useState(data.aggregations || []);
  const [havingConditions, setHavingConditions] = useState(data.havingConditions || []);

  // 소스 필드 목록 (연결된 입력 노드에서 가져오기)
  const [sourceFields, setSourceFields] = useState<Array<{ name: string; label?: string; type?: string }>>([]);

  // 데이터 변경 시 로컬 상태 업데이트
  useEffect(() => {
    setDisplayName(data.displayName || "집계");
    setGroupByFields(data.groupByFields || []);
    setAggregations(data.aggregations || []);
    setHavingConditions(data.havingConditions || []);
  }, [data]);

  // 연결된 소스 노드에서 필드 가져오기
  useEffect(() => {
    const inputEdges = edges.filter((edge) => edge.target === nodeId);
    const sourceNodeIds = inputEdges.map((edge) => edge.source);
    const sourceNodes = nodes.filter((node) => sourceNodeIds.includes(node.id));

    const fields: Array<{ name: string; label?: string; type?: string }> = [];
    sourceNodes.forEach((node) => {
      if (node.data.fields) {
        node.data.fields.forEach((field: any) => {
          fields.push({
            name: field.name,
            label: field.label || field.displayName,
            type: field.type,
          });
        });
      }
    });

    setSourceFields(fields);
  }, [nodeId, nodes, edges]);

  // 저장 함수
  const saveToNode = useCallback(
    (updates: Partial<AggregateNodeData>) => {
      updateNode(nodeId, {
        displayName,
        groupByFields,
        aggregations,
        havingConditions,
        ...updates,
      });
    },
    [nodeId, updateNode, displayName, groupByFields, aggregations, havingConditions]
  );

  // 그룹 기준 필드 토글
  const handleGroupByToggle = (fieldName: string, checked: boolean) => {
    let newGroupByFields;
    if (checked) {
      const field = sourceFields.find((f) => f.name === fieldName);
      newGroupByFields = [...groupByFields, { field: fieldName, fieldLabel: field?.label }];
    } else {
      newGroupByFields = groupByFields.filter((f) => f.field !== fieldName);
    }
    setGroupByFields(newGroupByFields);
    saveToNode({ groupByFields: newGroupByFields });
  };

  // 집계 연산 추가
  const handleAddAggregation = () => {
    const newAggregation = {
      id: `agg_${Date.now()}`,
      sourceField: "",
      sourceFieldLabel: "",
      function: "SUM" as AggregateFunction,
      outputField: "",
      outputFieldLabel: "",
    };
    const newAggregations = [...aggregations, newAggregation];
    setAggregations(newAggregations);
    saveToNode({ aggregations: newAggregations });
  };

  // 집계 연산 삭제
  const handleRemoveAggregation = (index: number) => {
    const newAggregations = aggregations.filter((_, i) => i !== index);
    setAggregations(newAggregations);
    saveToNode({ aggregations: newAggregations });
  };

  // 집계 연산 변경
  const handleAggregationChange = (index: number, field: string, value: any) => {
    const newAggregations = [...aggregations];

    if (field === "sourceField") {
      const sourceField = sourceFields.find((f) => f.name === value);
      newAggregations[index] = {
        ...newAggregations[index],
        sourceField: value,
        sourceFieldLabel: sourceField?.label,
        // 출력 필드명 자동 생성 (예: sum_amount)
        outputField:
          newAggregations[index].outputField ||
          `${newAggregations[index].function.toLowerCase()}_${value}`,
      };
    } else if (field === "function") {
      newAggregations[index] = {
        ...newAggregations[index],
        function: value,
        // 출력 필드명 업데이트
        outputField: newAggregations[index].sourceField
          ? `${value.toLowerCase()}_${newAggregations[index].sourceField}`
          : newAggregations[index].outputField,
      };
    } else {
      newAggregations[index] = { ...newAggregations[index], [field]: value };
    }

    setAggregations(newAggregations);
    saveToNode({ aggregations: newAggregations });
  };

  // HAVING 조건 추가
  const handleAddHavingCondition = () => {
    const newCondition = {
      field: "",
      operator: "=",
      value: "",
    };
    const newConditions = [...havingConditions, newCondition];
    setHavingConditions(newConditions);
    saveToNode({ havingConditions: newConditions });
  };

  // HAVING 조건 삭제
  const handleRemoveHavingCondition = (index: number) => {
    const newConditions = havingConditions.filter((_, i) => i !== index);
    setHavingConditions(newConditions);
    saveToNode({ havingConditions: newConditions });
  };

  // HAVING 조건 변경
  const handleHavingConditionChange = (index: number, field: string, value: any) => {
    const newConditions = [...havingConditions];
    newConditions[index] = { ...newConditions[index], [field]: value };
    setHavingConditions(newConditions);
    saveToNode({ havingConditions: newConditions });
  };

  // 집계 결과 필드 목록 (HAVING 조건에서 선택용)
  const aggregatedFields = aggregations
    .filter((agg) => agg.outputField)
    .map((agg) => ({
      name: agg.outputField,
      label: agg.outputFieldLabel || agg.outputField,
    }));

  return (
    <div>
      <div className="space-y-4 p-4 pb-8">
        {/* 헤더 */}
        <div className="flex items-center gap-2 rounded-md bg-purple-50 p-2">
          <Calculator className="h-4 w-4 text-purple-600" />
          <span className="font-semibold text-purple-600">집계 노드</span>
        </div>

        {/* 기본 정보 */}
        <div>
          <h3 className="mb-3 text-sm font-semibold">기본 정보</h3>
          <div>
            <Label htmlFor="displayName" className="text-xs">
              표시 이름
            </Label>
            <Input
              id="displayName"
              value={displayName}
              onChange={(e) => {
                setDisplayName(e.target.value);
                saveToNode({ displayName: e.target.value });
              }}
              className="mt-1"
              placeholder="노드 표시 이름"
            />
          </div>
        </div>

        {/* 그룹 기준 필드 */}
        <div>
          <div className="mb-2 flex items-center gap-2">
            <Layers className="h-4 w-4 text-purple-600" />
            <h3 className="text-sm font-semibold">그룹 기준 필드</h3>
          </div>
          <p className="mb-2 text-xs text-muted-foreground">
            선택한 필드를 기준으로 데이터를 그룹화합니다. 선택하지 않으면 전체 데이터를 하나의 그룹으로 처리합니다.
          </p>

          {sourceFields.length === 0 ? (
            <div className="rounded border border-dashed bg-muted p-3 text-center text-xs text-muted-foreground">
              연결된 소스 노드가 없습니다
            </div>
          ) : (
            <div className="max-h-40 overflow-y-auto rounded border bg-muted p-2">
              <div className="space-y-1">
                {sourceFields.map((field) => {
                  const isChecked = groupByFields.some((f) => f.field === field.name);
                  return (
                    <div
                      key={field.name}
                      className="flex items-center gap-2 rounded px-2 py-1 hover:bg-purple-50"
                    >
                      <Checkbox
                        id={`groupby_${field.name}`}
                        checked={isChecked}
                        onCheckedChange={(checked) => handleGroupByToggle(field.name, checked as boolean)}
                      />
                      <label
                        htmlFor={`groupby_${field.name}`}
                        className="flex-1 cursor-pointer text-xs"
                      >
                        <span className="font-medium">{field.label || field.name}</span>
                        {field.label && field.label !== field.name && (
                          <span className="ml-1 text-muted-foreground/70">({field.name})</span>
                        )}
                      </label>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {groupByFields.length > 0 && (
            <div className="mt-2 flex flex-wrap gap-1">
              {groupByFields.map((field) => (
                <span
                  key={field.field}
                  className="inline-flex items-center rounded bg-purple-100 px-2 py-0.5 text-xs text-purple-700"
                >
                  {field.fieldLabel || field.field}
                </span>
              ))}
            </div>
          )}
        </div>

        {/* 집계 연산 */}
        <div>
          <div className="mb-2 flex items-center justify-between">
            <div className="flex items-center gap-2">
              <Calculator className="h-4 w-4 text-purple-600" />
              <h3 className="text-sm font-semibold">집계 연산</h3>
            </div>
            <Button size="sm" variant="outline" onClick={handleAddAggregation} className="h-7 px-2 text-xs">
              <Plus className="mr-1 h-3 w-3" />
              연산 추가
            </Button>
          </div>
          <p className="mb-2 text-xs text-muted-foreground">SUM, COUNT, AVG 등 집계 연산을 설정합니다.</p>

          {aggregations.length === 0 ? (
            <div className="rounded border border-dashed bg-muted p-4 text-center text-xs text-muted-foreground">
              집계 연산을 추가하세요
            </div>
          ) : (
            <div className="space-y-3">
              {aggregations.map((agg, index) => (
                <div key={agg.id || index} className="rounded border bg-purple-50 p-3">
                  <div className="mb-2 flex items-center justify-between">
                    <span className="text-xs font-medium text-purple-700">집계 #{index + 1}</span>
                    <Button
                      size="sm"
                      variant="ghost"
                      onClick={() => handleRemoveAggregation(index)}
                      className="h-6 w-6 p-0 text-destructive hover:text-destructive"
                    >
                      <Trash2 className="h-3 w-3" />
                    </Button>
                  </div>

                  <div className="space-y-2">
                    {/* 집계 함수 선택 */}
                    <div>
                      <Label className="text-xs text-muted-foreground">집계 함수</Label>
                      <Select
                        value={agg.function}
                        onValueChange={(value) =>
                          handleAggregationChange(index, "function", value as AggregateFunction)
                        }
                      >
                        <SelectTrigger className="mt-1 h-8 text-xs">
                          <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                          {AGGREGATE_FUNCTIONS.map((func) => (
                            <SelectItem key={func.value} value={func.value} className="text-xs">
                              <div>
                                <div className="font-medium">{func.label}</div>
                                <div className="text-muted-foreground/70">{func.description}</div>
                              </div>
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>

                    {/* 소스 필드 선택 */}
                    <div>
                      <Label className="text-xs text-muted-foreground">소스 필드</Label>
                      <Select
                        value={agg.sourceField || ""}
                        onValueChange={(value) => handleAggregationChange(index, "sourceField", value)}
                      >
                        <SelectTrigger className="mt-1 h-8 text-xs">
                          <SelectValue placeholder="집계할 필드 선택" />
                        </SelectTrigger>
                        <SelectContent>
                          {sourceFields.length === 0 ? (
                            <div className="p-2 text-center text-xs text-muted-foreground/70">
                              연결된 소스 노드가 없습니다
                            </div>
                          ) : (
                            sourceFields.map((field) => (
                              <SelectItem key={field.name} value={field.name} className="text-xs">
                                <div className="flex items-center justify-between gap-2">
                                  <span className="font-medium">{field.label || field.name}</span>
                                  {field.label && field.label !== field.name && (
                                    <span className="text-muted-foreground font-mono text-xs">
                                      {field.name}
                                    </span>
                                  )}
                                </div>
                              </SelectItem>
                            ))
                          )}
                        </SelectContent>
                      </Select>
                    </div>

                    {/* 출력 필드명 */}
                    <div>
                      <Label className="text-xs text-muted-foreground">출력 필드명</Label>
                      <Input
                        value={agg.outputField || ""}
                        onChange={(e) => handleAggregationChange(index, "outputField", e.target.value)}
                        placeholder="예: total_amount"
                        className="mt-1 h-8 text-xs"
                      />
                      <p className="mt-1 text-xs text-muted-foreground/70">
                        집계 결과가 저장될 필드명입니다
                      </p>
                    </div>

                    {/* 출력 필드 라벨 */}
                    <div>
                      <Label className="text-xs text-muted-foreground">출력 필드 라벨 (선택)</Label>
                      <Input
                        value={agg.outputFieldLabel || ""}
                        onChange={(e) => handleAggregationChange(index, "outputFieldLabel", e.target.value)}
                        placeholder="예: 총 금액"
                        className="mt-1 h-8 text-xs"
                      />
                    </div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* HAVING 조건 (선택) */}
        <div>
          <div className="mb-2 flex items-center justify-between">
            <div className="flex items-center gap-2">
              <Filter className="h-4 w-4 text-purple-600" />
              <h3 className="text-sm font-semibold">집계 후 필터 (HAVING)</h3>
            </div>
            <Button
              size="sm"
              variant="outline"
              onClick={handleAddHavingCondition}
              className="h-7 px-2 text-xs"
              disabled={aggregations.length === 0}
            >
              <Plus className="mr-1 h-3 w-3" />
              조건 추가
            </Button>
          </div>
          <p className="mb-2 text-xs text-muted-foreground">집계 결과에 대한 필터링 조건을 설정합니다 (선택 사항).</p>

          {havingConditions.length === 0 ? (
            <div className="rounded border border-dashed bg-muted p-3 text-center text-xs text-muted-foreground/70">
              집계 후 필터링이 필요하면 조건을 추가하세요
            </div>
          ) : (
            <div className="space-y-2">
              {havingConditions.map((condition, index) => (
                <div key={index} className="flex items-center gap-2 rounded border bg-muted p-2">
                  {/* 집계 결과 필드 선택 */}
                  <Select
                    value={condition.field || ""}
                    onValueChange={(value) => handleHavingConditionChange(index, "field", value)}
                  >
                    <SelectTrigger className="h-8 w-32 text-xs">
                      <SelectValue placeholder="필드" />
                    </SelectTrigger>
                    <SelectContent>
                      {aggregatedFields.map((field) => (
                        <SelectItem key={field.name} value={field.name} className="text-xs">
                          {field.label}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>

                  {/* 연산자 선택 */}
                  <Select
                    value={condition.operator || "="}
                    onValueChange={(value) => handleHavingConditionChange(index, "operator", value)}
                  >
                    <SelectTrigger className="h-8 w-24 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      {OPERATORS.map((op) => (
                        <SelectItem key={op.value} value={op.value} className="text-xs">
                          {op.label}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>

                  {/* 비교값 */}
                  <Input
                    value={condition.value || ""}
                    onChange={(e) => handleHavingConditionChange(index, "value", e.target.value)}
                    placeholder="값"
                    className="h-8 flex-1 text-xs"
                  />

                  {/* 삭제 버튼 */}
                  <Button
                    size="sm"
                    variant="ghost"
                    onClick={() => handleRemoveHavingCondition(index)}
                    className="h-6 w-6 p-0 text-destructive hover:text-destructive"
                  >
                    <Trash2 className="h-3 w-3" />
                  </Button>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* 미리보기 */}
        {(groupByFields.length > 0 || aggregations.length > 0) && (
          <div className="rounded border bg-muted p-3">
            <h4 className="mb-2 text-xs font-semibold text-foreground">집계 결과 미리보기</h4>
            <div className="text-xs text-muted-foreground">
              <div className="mb-1">
                <span className="font-medium">그룹 기준:</span>{" "}
                {groupByFields.length > 0
                  ? groupByFields.map((f) => f.fieldLabel || f.field).join(", ")
                  : "전체 (그룹 없음)"}
              </div>
              <div>
                <span className="font-medium">집계 컬럼:</span>{" "}
                {aggregations.length > 0
                  ? aggregations
                      .filter((a) => a.outputField)
                      .map((a) => `${a.function}(${a.sourceFieldLabel || a.sourceField}) → ${a.outputFieldLabel || a.outputField}`)
                      .join(", ")
                  : "없음"}
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

