"use client";

import { useMemo, useCallback } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";
import { Eye, EyeOff, HelpCircle, Trash2, Plus } from "lucide-react";
import type { ComponentConfig, ConditionalRule } from "@/types/report";
import { useReportDesigner } from "@/contexts/ReportDesignerContext";

const TYPE_LABELS: Record<string, string> = {
  text: "텍스트",
  label: "레이블",
  table: "테이블",
  image: "이미지",
  divider: "구분선",
  signature: "서명",
  stamp: "도장",
  pageNumber: "페이지 번호",
  card: "카드",
  calculation: "계산",
  barcode: "바코드",
  checkbox: "체크박스",
};

interface OperatorDef {
  value: ConditionalRule["operator"];
  symbol: string;
  label: string;
  summary: string;
  group: "compare" | "text" | "exist";
}

const OPERATORS: OperatorDef[] = [
  { value: "eq", symbol: "=", label: "같을 때", summary: "가 '$V'일 때", group: "compare" },
  { value: "ne", symbol: "≠", label: "다를 때", summary: "가 '$V'이(가) 아닐 때", group: "compare" },
  { value: "gt", symbol: ">", label: "보다 클 때", summary: "이(가) $V보다 클 때", group: "compare" },
  { value: "lt", symbol: "<", label: "보다 작을 때", summary: "이(가) $V보다 작을 때", group: "compare" },
  { value: "gte", symbol: "≥", label: "이상일 때", summary: "이(가) $V 이상일 때", group: "compare" },
  { value: "lte", symbol: "≤", label: "이하일 때", summary: "이(가) $V 이하일 때", group: "compare" },
  { value: "contains", symbol: "⊃", label: "포함할 때", summary: "에 '$V'이(가) 포함될 때", group: "text" },
  { value: "notEmpty", symbol: "✓", label: "값이 있을 때", summary: "에 값이 있을 때", group: "exist" },
  { value: "empty", symbol: "∅", label: "값이 없을 때", summary: "에 값이 없을 때", group: "exist" },
];

const OPERATOR_GROUPS: { key: OperatorDef["group"]; label: string }[] = [
  { key: "compare", label: "비교" },
  { key: "text", label: "텍스트" },
  { key: "exist", label: "값 유무" },
];

const NO_VALUE_OPERATORS = ["notEmpty", "empty"];

interface CardColumn {
  column_name: string;
  data_type: string;
}

export interface CardColumnLabel {
  columnName: string;
  label: string;
}

interface Props {
  component: ComponentConfig;
  onConfigChange?: (updates: Partial<ComponentConfig>) => void;
  cardColumns?: CardColumn[];
  cardTableName?: string;
  cardColumnLabels?: CardColumnLabel[];
  /** conditionalRules 대신 사용할 키 (격자 모드 분리용) */
  rulesKey?: "conditionalRules" | "gridConditionalRules";
  /** conditionalRule 대신 사용할 키 (격자 모드 분리용) */
  ruleKey?: "conditionalRule" | "gridConditionalRule";
}

const DEFAULT_RULE: ConditionalRule = {
  queryId: "",
  field: "",
  operator: "eq",
  value: "",
  action: "show",
};

export function ConditionalProperties({
  component,
  onConfigChange,
  cardColumns,
  cardTableName,
  cardColumnLabels,
  rulesKey = "conditionalRules",
  ruleKey = "conditionalRule",
}: Props) {
  const { updateComponent, queries, getQueryResult } = useReportDesigner();

  const componentLabel = TYPE_LABELS[component.type] ?? component.type;
  const isCardMode = !!cardColumns;

  const applyUpdate = useCallback(
    (updates: Partial<ComponentConfig>) => {
      if (onConfigChange) onConfigChange(updates);
      else updateComponent(component.id, updates);
    },
    [onConfigChange, updateComponent, component.id],
  );

  /** 단일 rule → 배열로 정규화 (rulesKey/ruleKey 기반) */
  const rules: ConditionalRule[] = useMemo(() => {
    const rulesArr = component[rulesKey] as ConditionalRule[] | undefined;
    const singleRule = component[ruleKey] as ConditionalRule | undefined;
    if (rulesArr && rulesArr.length > 0) {
      return rulesArr;
    }
    if (singleRule) {
      return [singleRule];
    }
    return [];
  }, [component, rulesKey, ruleKey]);

  const action = rules.length > 0 ? rules[0].action : "show";

  const syncRules = useCallback(
    (newRules: ConditionalRule[]) => {
      applyUpdate({
        [rulesKey]: newRules,
        [ruleKey]: newRules.length > 0 ? newRules[0] : undefined,
      });
    },
    [applyUpdate, rulesKey, ruleKey],
  );

  const getQueryFields = (queryId: string): string[] => {
    const result = getQueryResult(queryId);
    return result ? result.fields : [];
  };

  const labelMap = useMemo(() => {
    const map = new Map<string, string>();
    cardColumnLabels?.forEach((cl) => map.set(cl.columnName, cl.label));
    return map;
  }, [cardColumnLabels]);

  const addRule = useCallback(() => {
    const newRule: ConditionalRule = {
      ...DEFAULT_RULE,
      queryId: isCardMode ? "__card__" : (queries[0]?.id || ""),
      action,
    };
    syncRules([...rules, newRule]);
  }, [rules, isCardMode, queries, action, syncRules]);

  const updateRule = useCallback(
    (index: number, patch: Partial<ConditionalRule>) => {
      const updated = rules.map((r, i) => (i === index ? { ...r, ...patch } : r));
      syncRules(updated);
    },
    [rules, syncRules],
  );

  const removeRule = useCallback(
    (index: number) => {
      const updated = rules.filter((_, i) => i !== index);
      syncRules(updated);
    },
    [rules, syncRules],
  );

  const removeAllRules = useCallback(() => {
    syncRules([]);
  }, [syncRules]);

  const updateAction = useCallback(
    (newAction: "show" | "hide") => {
      const updated = rules.map((r) => ({ ...r, action: newAction }));
      syncRules(updated);
    },
    [rules, syncRules],
  );

  const getFieldsForRule = useCallback(
    (rule: ConditionalRule): string[] => {
      if (isCardMode) {
        return cardColumnLabels?.map((cl) => cl.columnName) ?? [];
      }
      return rule.queryId ? getQueryFields(rule.queryId) : [];
    },
    [isCardMode, cardColumnLabels],
  );

  const getFieldDisplayName = useCallback(
    (fieldName: string): string => labelMap.get(fieldName) || fieldName,
    [labelMap],
  );

  const summaryText = useMemo(() => {
    const validRules = rules.filter((r) => r.field && (isCardMode || r.queryId));
    if (validRules.length === 0) return null;

    const parts = validRules.map((rule) => {
      const op = OPERATORS.find((o) => o.value === rule.operator);
      if (!op) return null;
      const fieldLabel = labelMap.get(rule.field) || rule.field;
      const condPart = op.summary.replace("$V", rule.value || "?");
      return `${fieldLabel}${condPart}`;
    }).filter(Boolean);

    if (parts.length === 0) return null;

    const conditionStr = parts.join(", ");
    const actionPart = action === "show"
      ? `이 ${componentLabel}을(를) 보여줍니다`
      : `이 ${componentLabel}을(를) 숨깁니다`;

    if (parts.length === 1) {
      return `${conditionStr} ${actionPart}`;
    }
    return `다음 조건을 모두 만족할 때 ${actionPart}: ${conditionStr}`;
  }, [rules, isCardMode, labelMap, componentLabel, action]);

  const hasNoDataSource = isCardMode
    ? !cardTableName || (cardColumnLabels?.length ?? 0) === 0
    : false;

  return (
    <div className="mt-4 rounded-xl border border-gray-200 bg-gray-50">
      {/* 헤더 */}
      <div className="flex items-center justify-between px-4 pt-4 pb-3">
        <div className="flex items-center gap-2 text-sm font-semibold text-gray-800">
          {action === "hide" ? (
            <EyeOff className="h-4 w-4" />
          ) : (
            <Eye className="h-4 w-4" />
          )}
          표시 조건
          {rules.length > 0 && (
            <span className="inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-blue-100 px-1.5 text-[10px] font-bold text-blue-700">
              {rules.length}
            </span>
          )}
          <TooltipProvider delayDuration={80}>
            <Tooltip>
              <TooltipTrigger asChild>
                <button type="button" className="inline-flex">
                  <HelpCircle className="h-3.5 w-3.5 text-gray-400 cursor-help" />
                </button>
              </TooltipTrigger>
              <TooltipContent
                side="right"
                className="max-w-[300px] bg-gray-700 text-white text-xs leading-relaxed space-y-2 py-2.5"
              >
                <p>
                  데이터 값에 따라 이 {componentLabel}을(를) 자동으로
                  보이거나 숨길 수 있습니다.
                </p>
                <div className="border-t border-gray-500 pt-2 space-y-1">
                  <p className="font-semibold text-gray-300">여러 조건 사용</p>
                  <p>
                    조건을 여러 개 추가하면 모든 조건을 동시에 만족해야
                    결과가 적용됩니다.
                  </p>
                </div>
              </TooltipContent>
            </Tooltip>
          </TooltipProvider>
        </div>
        {rules.length > 0 && (
          <Button
            variant="ghost"
            size="sm"
            onClick={removeAllRules}
            className="h-6 px-2 text-xs text-red-500 hover:bg-red-50 gap-1"
          >
            <Trash2 className="h-3 w-3" />
            전체 삭제
          </Button>
        )}
      </div>

      {/* 본문 */}
      <div className="px-4 pb-4 space-y-3">
        {hasNoDataSource ? (
          <p className="text-xs text-gray-400 text-center py-4">
            {!cardTableName
              ? "데이터 연결 탭에서 테이블을 먼저 선택해주세요."
              : "레이아웃 구성 탭에서 데이터 항목을 먼저 추가해주세요."}
          </p>
        ) : rules.length === 0 ? (
          <Button
            variant="outline"
            size="sm"
            className="w-full text-xs"
            onClick={addRule}
          >
            <Plus className="h-3 w-3 mr-1" />
            조건 추가
          </Button>
        ) : (
          <>
            {/* 결과 동작 (공통) */}
            <div className="rounded-lg border border-gray-200 bg-white p-3 space-y-2.5">
              <p className="text-[11px] font-semibold text-gray-400 uppercase tracking-wide">결과</p>
              <Select
                value={action}
                onValueChange={(v) => updateAction(v as "show" | "hide")}
              >
                <SelectTrigger className="h-8 text-xs">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="show">
                    조건을 만족하면 이 {componentLabel}을(를) 보여줍니다
                  </SelectItem>
                  <SelectItem value="hide">
                    조건을 만족하면 이 {componentLabel}을(를) 숨깁니다
                  </SelectItem>
                </SelectContent>
              </Select>
            </div>

            {/* 조건 목록 */}
            {rules.map((rule, index) => (
              <RuleEditor
                key={index}
                index={index}
                rule={rule}
                isCardMode={isCardMode}
                queries={queries}
                fields={getFieldsForRule(rule)}
                getFieldDisplayName={getFieldDisplayName}
                onUpdate={updateRule}
                onRemove={removeRule}
                showAndLabel={index > 0}
              />
            ))}

            {/* 조건 추가 버튼 */}
            <Button
              variant="outline"
              size="sm"
              className="w-full text-xs"
              onClick={addRule}
            >
              <Plus className="h-3 w-3 mr-1" />
              표시 조건 추가
            </Button>

            {/* 요약 */}
            {summaryText && (
              <div className="rounded-lg border border-blue-100 bg-blue-50/50 px-3 py-2.5">
                <p className="text-[11px] text-blue-500 mb-1 font-medium">요약</p>
                <p className="text-xs text-blue-700 leading-relaxed">{summaryText}</p>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}

/** 개별 조건 편집기 */
interface RuleEditorProps {
  index: number;
  rule: ConditionalRule;
  isCardMode: boolean;
  queries: { id: string; name: string }[];
  fields: string[];
  getFieldDisplayName: (fieldName: string) => string;
  onUpdate: (index: number, patch: Partial<ConditionalRule>) => void;
  onRemove: (index: number) => void;
  showAndLabel: boolean;
}

function RuleEditor({
  index,
  rule,
  isCardMode,
  queries,
  fields,
  getFieldDisplayName,
  onUpdate,
  onRemove,
  showAndLabel,
}: RuleEditorProps) {
  const needsValue = !NO_VALUE_OPERATORS.includes(rule.operator);

  return (
    <div className="space-y-0">
      {showAndLabel && (
        <div className="flex items-center gap-2 py-1">
          <div className="flex-1 border-t border-dashed border-gray-300" />
          <span className="text-[10px] font-bold text-blue-600 bg-blue-50 px-2 py-0.5 rounded-full">동시 만족</span>
          <div className="flex-1 border-t border-dashed border-gray-300" />
        </div>
      )}
      <div className="rounded-lg border border-gray-200 bg-white p-3 space-y-2.5 relative group">
        <div className="flex items-center justify-between">
          <p className="text-[11px] font-semibold text-gray-400 uppercase tracking-wide">
            조건 {index + 1}
          </p>
          <Button
            variant="ghost"
            size="sm"
            onClick={() => onRemove(index)}
            className="h-5 w-5 p-0 text-gray-400 hover:text-red-500 hover:bg-red-50 opacity-0 group-hover:opacity-100 transition-opacity"
          >
            <Trash2 className="h-3 w-3" />
          </Button>
        </div>

        {!isCardMode && (
          <div>
            <label className="text-xs font-medium text-gray-500">데이터 출처</label>
            <Select
              value={rule.queryId || ""}
              onValueChange={(v) => onUpdate(index, { queryId: v, field: "" })}
            >
              <SelectTrigger className="h-8 text-xs">
                <SelectValue placeholder="데이터를 선택하세요" />
              </SelectTrigger>
              <SelectContent>
                {queries.map((q) => (
                  <SelectItem key={q.id} value={q.id}>
                    {q.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        )}

        <div>
          <label className="text-xs font-medium text-gray-500">확인할 항목</label>
          <Select
            value={rule.field || ""}
            onValueChange={(v) => onUpdate(index, { field: v })}
          >
            <SelectTrigger className="h-8 text-xs">
              <SelectValue placeholder="항목을 선택하세요" />
            </SelectTrigger>
            <SelectContent>
              {fields.map((f) => (
                <SelectItem key={f} value={f} className="text-xs">
                  {getFieldDisplayName(f)}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>

        <div className={needsValue ? "grid grid-cols-2 gap-2" : ""}>
          <div>
            <label className="text-xs font-medium text-gray-500">조건</label>
            <Select
              value={rule.operator}
              onValueChange={(v) =>
                onUpdate(index, { operator: v as ConditionalRule["operator"] })
              }
            >
              <SelectTrigger className="h-8 text-xs">
                {rule.operator ? (
                  <span className="flex items-center gap-1.5">
                    <span className="inline-flex h-4 w-4 items-center justify-center rounded bg-gray-100 text-[10px] font-bold text-gray-600">
                      {OPERATORS.find((o) => o.value === rule.operator)?.symbol}
                    </span>
                    {OPERATORS.find((o) => o.value === rule.operator)?.label}
                  </span>
                ) : (
                  <SelectValue placeholder="조건 선택" />
                )}
              </SelectTrigger>
              <SelectContent>
                {OPERATOR_GROUPS.map((group, gi) => (
                  <div key={group.key}>
                    {gi > 0 && <div className="mx-2 my-1 border-t border-gray-100" />}
                    <div className="px-2 py-1 text-[10px] font-semibold text-gray-400">
                      {group.label}
                    </div>
                    {OPERATORS.filter((op) => op.group === group.key).map((op) => (
                      <SelectItem key={op.value} value={op.value} className="text-xs">
                        <span className="flex items-center gap-2">
                          <span className="inline-flex h-4 w-4 items-center justify-center rounded bg-gray-100 text-[10px] font-bold text-gray-600">
                            {op.symbol}
                          </span>
                          {op.label}
                        </span>
                      </SelectItem>
                    ))}
                  </div>
                ))}
              </SelectContent>
            </Select>
          </div>
          {needsValue && (
            <div>
              <label className="text-xs font-medium text-gray-500">기준 값</label>
              <Input
                value={rule.value}
                onChange={(e) => onUpdate(index, { value: e.target.value })}
                placeholder="값 입력"
                className="h-8 text-xs"
              />
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
