"use client";

import React, { useState, useEffect, useCallback, useMemo } from "react";
import {
  GripVertical,
  Plus,
  X,
  Search,
  ChevronRight,
  ChevronDown,
  Package,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from "@/components/ui/dialog";
import { entityJoinApi } from "@/lib/api/entityJoin";
import { apiClient } from "@/lib/api/client";

// ─── 타입 정의 ───

interface BomItemNode {
  tempId: string;
  id?: string;
  bom_id?: string;
  parent_detail_id: string | null;
  seq_no: number;
  level: number;
  child_item_id: string;
  child_item_code: string;
  child_item_name: string;
  child_item_type: string;
  quantity: string;
  unit: string;
  loss_rate: string;
  remark: string;
  children: BomItemNode[];
  _isNew?: boolean;
  _isDeleted?: boolean;
}

interface ItemInfo {
  id: string;
  item_number: string;
  item_name: string;
  type: string;
  unit: string;
  division: string;
}

interface BomItemEditorProps {
  component?: any;
  formData?: Record<string, any>;
  companyCode?: string;
  isDesignMode?: boolean;
  selectedRowsData?: any[];
  onChange?: (flatData: any[]) => void;
  bomId?: string;
}

// 임시 ID 생성
let tempIdCounter = 0;
const generateTempId = () => `temp_${Date.now()}_${++tempIdCounter}`;

// ─── 품목 검색 모달 ───

interface ItemSearchModalProps {
  open: boolean;
  onClose: () => void;
  onSelect: (item: ItemInfo) => void;
  companyCode?: string;
}

function ItemSearchModal({
  open,
  onClose,
  onSelect,
  companyCode,
}: ItemSearchModalProps) {
  const [searchText, setSearchText] = useState("");
  const [items, setItems] = useState<ItemInfo[]>([]);
  const [loading, setLoading] = useState(false);

  const searchItems = useCallback(
    async (query: string) => {
      setLoading(true);
      try {
        const result = await entityJoinApi.getTableDataWithJoins("item_info", {
          page: 1,
          size: 50,
          search: query
            ? { item_number: query, item_name: query }
            : undefined,
          enableEntityJoin: true,
          companyCodeOverride: companyCode,
        });
        setItems(result.data || []);
      } catch (error) {
        console.error("[BomItemEditor] 품목 검색 실패:", error);
      } finally {
        setLoading(false);
      }
    },
    [companyCode],
  );

  useEffect(() => {
    if (open) {
      setSearchText("");
      searchItems("");
    }
  }, [open, searchItems]);

  const handleSearch = () => {
    searchItems(searchText);
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter") {
      e.preventDefault();
      handleSearch();
    }
  };

  return (
    <Dialog open={open} onOpenChange={onClose}>
      <DialogContent className="max-w-[95vw] sm:max-w-[600px]">
        <DialogHeader>
          <DialogTitle className="text-base sm:text-lg">품목 검색</DialogTitle>
          <DialogDescription className="text-xs sm:text-sm">
            하위 품목으로 추가할 품목을 선택하세요.
          </DialogDescription>
        </DialogHeader>

        <div className="flex gap-2">
          <Input
            value={searchText}
            onChange={(e) => setSearchText(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder="품목코드 또는 품목명"
            className="h-8 text-xs sm:h-10 sm:text-sm"
          />
          <Button
            onClick={handleSearch}
            size="sm"
            className="h-8 sm:h-10"
          >
            <Search className="mr-1 h-4 w-4" />
            검색
          </Button>
        </div>

        <div className="max-h-[300px] overflow-y-auto rounded-md border">
          {loading ? (
            <div className="flex items-center justify-center py-8">
              <span className="text-muted-foreground text-sm">검색 중...</span>
            </div>
          ) : items.length === 0 ? (
            <div className="flex items-center justify-center py-8">
              <span className="text-muted-foreground text-sm">
                검색 결과가 없습니다.
              </span>
            </div>
          ) : (
            <table className="w-full text-xs sm:text-sm">
              <thead className="bg-muted/50 sticky top-0">
                <tr>
                  <th className="px-3 py-2 text-left font-medium">품목코드</th>
                  <th className="px-3 py-2 text-left font-medium">품목명</th>
                  <th className="px-3 py-2 text-left font-medium">구분</th>
                  <th className="px-3 py-2 text-left font-medium">단위</th>
                </tr>
              </thead>
              <tbody>
                {items.map((item) => (
                  <tr
                    key={item.id}
                    onClick={() => {
                      onSelect(item);
                      onClose();
                    }}
                    className="hover:bg-accent cursor-pointer border-t transition-colors"
                  >
                    <td className="px-3 py-2 font-mono">
                      {item.item_number}
                    </td>
                    <td className="px-3 py-2">{item.item_name}</td>
                    <td className="px-3 py-2">{item.type}</td>
                    <td className="px-3 py-2">{item.unit}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </DialogContent>
    </Dialog>
  );
}

// ─── 트리 노드 행 렌더링 ───

interface TreeNodeRowProps {
  node: BomItemNode;
  depth: number;
  expanded: boolean;
  hasChildren: boolean;
  onToggle: () => void;
  onFieldChange: (tempId: string, field: string, value: string) => void;
  onDelete: (tempId: string) => void;
  onAddChild: (parentTempId: string) => void;
}

function TreeNodeRow({
  node,
  depth,
  expanded,
  hasChildren,
  onToggle,
  onFieldChange,
  onDelete,
  onAddChild,
}: TreeNodeRowProps) {
  const indentPx = depth * 32;

  return (
    <div
      className={cn(
        "group flex items-center gap-2 rounded-md border px-2 py-1.5",
        "transition-colors hover:bg-accent/30",
        depth > 0 && "ml-2 border-l-2 border-l-primary/20",
      )}
      style={{ marginLeft: `${indentPx}px` }}
    >
      {/* 드래그 핸들 */}
      <GripVertical className="text-muted-foreground h-4 w-4 shrink-0 cursor-grab" />

      {/* 펼침/접기 */}
      <button
        onClick={onToggle}
        className={cn(
          "flex h-5 w-5 shrink-0 items-center justify-center rounded",
          hasChildren
            ? "hover:bg-accent cursor-pointer"
            : "cursor-default opacity-0",
        )}
      >
        {hasChildren &&
          (expanded ? (
            <ChevronDown className="h-3.5 w-3.5" />
          ) : (
            <ChevronRight className="h-3.5 w-3.5" />
          ))}
      </button>

      {/* 순번 */}
      <span className="text-muted-foreground w-6 shrink-0 text-center text-xs font-medium">
        {node.seq_no}
      </span>

      {/* 품목코드 */}
      <span className="w-24 shrink-0 truncate font-mono text-xs font-medium">
        {node.child_item_code || "-"}
      </span>

      {/* 품목명 */}
      <span className="min-w-[80px] flex-1 truncate text-xs">
        {node.child_item_name || "-"}
      </span>

      {/* 레벨 뱃지 */}
      {node.level > 0 && (
        <span className="bg-primary/10 text-primary shrink-0 rounded px-1.5 py-0.5 text-[10px] font-semibold">
          L{node.level}
        </span>
      )}

      {/* 수량 */}
      <Input
        value={node.quantity}
        onChange={(e) =>
          onFieldChange(node.tempId, "quantity", e.target.value)
        }
        className="h-7 w-16 shrink-0 text-center text-xs"
        placeholder="수량"
      />

      {/* 품목구분 셀렉트 */}
      <Select
        value={node.child_item_type || ""}
        onValueChange={(val) =>
          onFieldChange(node.tempId, "child_item_type", val)
        }
      >
        <SelectTrigger className="h-7 w-20 shrink-0 text-xs">
          <SelectValue placeholder="구분" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="assembly">조립</SelectItem>
          <SelectItem value="process">공정</SelectItem>
          <SelectItem value="purchase">구매</SelectItem>
          <SelectItem value="outsource">외주</SelectItem>
        </SelectContent>
      </Select>

      {/* 하위 추가 버튼 */}
      <Button
        variant="ghost"
        size="icon"
        className="h-7 w-7 shrink-0"
        onClick={() => onAddChild(node.tempId)}
        title="하위 품목 추가"
      >
        <Plus className="h-3.5 w-3.5" />
      </Button>

      {/* 삭제 버튼 */}
      <Button
        variant="ghost"
        size="icon"
        className="text-destructive hover:bg-destructive/10 h-7 w-7 shrink-0"
        onClick={() => onDelete(node.tempId)}
        title="삭제"
      >
        <X className="h-3.5 w-3.5" />
      </Button>
    </div>
  );
}

// ─── 메인 컴포넌트 ───

export function BomItemEditorComponent({
  component,
  formData,
  companyCode,
  isDesignMode = false,
  selectedRowsData,
  onChange,
  bomId: propBomId,
}: BomItemEditorProps) {
  const [treeData, setTreeData] = useState<BomItemNode[]>([]);
  const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());
  const [loading, setLoading] = useState(false);
  const [itemSearchOpen, setItemSearchOpen] = useState(false);
  const [addTargetParentId, setAddTargetParentId] = useState<string | null>(
    null,
  );

  // BOM ID 결정
  const bomId = useMemo(() => {
    if (propBomId) return propBomId;
    if (formData?.id) return formData.id as string;
    if (selectedRowsData?.[0]?.id) return selectedRowsData[0].id as string;
    return null;
  }, [propBomId, formData, selectedRowsData]);

  // ─── 데이터 로드 ───

  const loadBomDetails = useCallback(
    async (id: string) => {
      if (!id) return;
      setLoading(true);
      try {
        const result = await entityJoinApi.getTableDataWithJoins("bom_detail", {
          page: 1,
          size: 500,
          search: { bom_id: id },
          sortBy: "seq_no",
          sortOrder: "asc",
          enableEntityJoin: true,
        });

        const rows = result.data || [];
        const tree = buildTree(rows);
        setTreeData(tree);

        // 1레벨 기본 펼침
        const firstLevelIds = new Set<string>(
          tree.map((n) => n.tempId || n.id || ""),
        );
        setExpandedNodes(firstLevelIds);
      } catch (error) {
        console.error("[BomItemEditor] 데이터 로드 실패:", error);
      } finally {
        setLoading(false);
      }
    },
    [],
  );

  useEffect(() => {
    if (bomId && !isDesignMode) {
      loadBomDetails(bomId);
    }
  }, [bomId, isDesignMode, loadBomDetails]);

  // ─── 트리 빌드 ───

  const buildTree = (flatData: any[]): BomItemNode[] => {
    const nodeMap = new Map<string, BomItemNode>();
    const roots: BomItemNode[] = [];

    flatData.forEach((item) => {
      const tempId = item.id || generateTempId();
      nodeMap.set(item.id || tempId, {
        tempId,
        id: item.id,
        bom_id: item.bom_id,
        parent_detail_id: item.parent_detail_id || null,
        seq_no: Number(item.seq_no) || 0,
        level: Number(item.level) || 0,
        child_item_id: item.child_item_id || "",
        child_item_code: item.child_item_code || "",
        child_item_name: item.child_item_name || "",
        child_item_type: item.child_item_type || "",
        quantity: item.quantity || "1",
        unit: item.unit || "EA",
        loss_rate: item.loss_rate || "0",
        remark: item.remark || "",
        children: [],
      });
    });

    flatData.forEach((item) => {
      const nodeId = item.id || "";
      const node = nodeMap.get(nodeId);
      if (!node) return;

      if (item.parent_detail_id && nodeMap.has(item.parent_detail_id)) {
        nodeMap.get(item.parent_detail_id)!.children.push(node);
      } else {
        roots.push(node);
      }
    });

    // 순번 정렬
    const sortChildren = (nodes: BomItemNode[]) => {
      nodes.sort((a, b) => a.seq_no - b.seq_no);
      nodes.forEach((n) => sortChildren(n.children));
    };
    sortChildren(roots);

    return roots;
  };

  // ─── 트리 -> 평면 변환 (onChange 콜백용) ───

  const flattenTree = useCallback((nodes: BomItemNode[]): any[] => {
    const result: any[] = [];
    const traverse = (
      items: BomItemNode[],
      parentId: string | null,
      level: number,
    ) => {
      items.forEach((node, idx) => {
        result.push({
          id: node.id,
          tempId: node.tempId,
          bom_id: node.bom_id,
          parent_detail_id: parentId,
          seq_no: String(idx + 1),
          level: String(level),
          child_item_id: node.child_item_id,
          child_item_code: node.child_item_code,
          child_item_name: node.child_item_name,
          child_item_type: node.child_item_type,
          quantity: node.quantity,
          unit: node.unit,
          loss_rate: node.loss_rate,
          remark: node.remark,
          _isNew: node._isNew,
          _targetTable: "bom_detail",
        });
        if (node.children.length > 0) {
          traverse(node.children, node.id || node.tempId, level + 1);
        }
      });
    };
    traverse(nodes, null, 0);
    return result;
  }, []);

  // 트리 변경 시 부모에게 알림
  const notifyChange = useCallback(
    (newTree: BomItemNode[]) => {
      setTreeData(newTree);
      onChange?.(flattenTree(newTree));
    },
    [onChange, flattenTree],
  );

  // ─── 노드 조작 함수들 ───

  // 트리에서 특정 노드 찾기 (재귀)
  const findAndUpdate = (
    nodes: BomItemNode[],
    targetTempId: string,
    updater: (node: BomItemNode) => BomItemNode | null,
  ): BomItemNode[] => {
    const result: BomItemNode[] = [];
    for (const node of nodes) {
      if (node.tempId === targetTempId) {
        const updated = updater(node);
        if (updated) result.push(updated);
      } else {
        result.push({
          ...node,
          children: findAndUpdate(node.children, targetTempId, updater),
        });
      }
    }
    return result;
  };

  // 필드 변경
  const handleFieldChange = useCallback(
    (tempId: string, field: string, value: string) => {
      const newTree = findAndUpdate(treeData, tempId, (node) => ({
        ...node,
        [field]: value,
      }));
      notifyChange(newTree);
    },
    [treeData, notifyChange],
  );

  // 노드 삭제
  const handleDelete = useCallback(
    (tempId: string) => {
      const newTree = findAndUpdate(treeData, tempId, () => null);
      notifyChange(newTree);
    },
    [treeData, notifyChange],
  );

  // 하위 품목 추가 시작 (모달 열기)
  const handleAddChild = useCallback((parentTempId: string) => {
    setAddTargetParentId(parentTempId);
    setItemSearchOpen(true);
  }, []);

  // 루트 품목 추가 시작
  const handleAddRoot = useCallback(() => {
    setAddTargetParentId(null);
    setItemSearchOpen(true);
  }, []);

  // 품목 선택 후 추가
  const handleItemSelect = useCallback(
    (item: ItemInfo) => {
      const newNode: BomItemNode = {
        tempId: generateTempId(),
        parent_detail_id: null,
        seq_no: 0,
        level: 0,
        child_item_id: item.id,
        child_item_code: item.item_number || "",
        child_item_name: item.item_name || "",
        child_item_type: item.type || "",
        quantity: "1",
        unit: item.unit || "EA",
        loss_rate: "0",
        remark: "",
        children: [],
        _isNew: true,
      };

      let newTree: BomItemNode[];

      if (addTargetParentId === null) {
        // 루트에 추가
        newNode.seq_no = treeData.length + 1;
        newNode.level = 0;
        newTree = [...treeData, newNode];
      } else {
        // 특정 노드 하위에 추가
        newTree = findAndUpdate(treeData, addTargetParentId, (parent) => {
          newNode.parent_detail_id = parent.id || parent.tempId;
          newNode.seq_no = parent.children.length + 1;
          newNode.level = parent.level + 1;
          return {
            ...parent,
            children: [...parent.children, newNode],
          };
        });
        // 부모 노드 펼침
        setExpandedNodes((prev) => new Set([...prev, addTargetParentId]));
      }

      notifyChange(newTree);
    },
    [addTargetParentId, treeData, notifyChange],
  );

  // 펼침/접기 토글
  const toggleExpand = useCallback((tempId: string) => {
    setExpandedNodes((prev) => {
      const next = new Set(prev);
      if (next.has(tempId)) next.delete(tempId);
      else next.add(tempId);
      return next;
    });
  }, []);

  // ─── 재귀 렌더링 ───

  const renderNodes = (nodes: BomItemNode[], depth: number) => {
    return nodes.map((node) => {
      const isExpanded = expandedNodes.has(node.tempId);
      return (
        <React.Fragment key={node.tempId}>
          <TreeNodeRow
            node={node}
            depth={depth}
            expanded={isExpanded}
            hasChildren={node.children.length > 0}
            onToggle={() => toggleExpand(node.tempId)}
            onFieldChange={handleFieldChange}
            onDelete={handleDelete}
            onAddChild={handleAddChild}
          />
          {isExpanded &&
            node.children.length > 0 &&
            renderNodes(node.children, depth + 1)}
        </React.Fragment>
      );
    });
  };

  // ─── 디자인 모드 ───

  if (isDesignMode) {
    return (
      <div className="rounded-md border border-dashed p-6 text-center">
        <Package className="text-muted-foreground mx-auto mb-2 h-8 w-8" />
        <p className="text-muted-foreground text-sm font-medium">
          BOM 하위 품목 편집기
        </p>
        <p className="text-muted-foreground text-xs">
          트리 구조로 하위 품목을 관리합니다
        </p>
      </div>
    );
  }

  // ─── 메인 렌더링 ───

  return (
    <div className="space-y-3">
      {/* 헤더 */}
      <div className="flex items-center justify-between">
        <h4 className="text-sm font-semibold">하위 품목 구성</h4>
        <Button
          onClick={handleAddRoot}
          size="sm"
          className="h-8 text-xs"
        >
          <Plus className="mr-1 h-3.5 w-3.5" />
          품목추가
        </Button>
      </div>

      {/* 트리 목록 */}
      <div className="space-y-1">
        {loading ? (
          <div className="flex items-center justify-center py-8">
            <span className="text-muted-foreground text-sm">로딩 중...</span>
          </div>
        ) : treeData.length === 0 ? (
          <div className="flex flex-col items-center justify-center rounded-md border border-dashed py-8">
            <Package className="text-muted-foreground mb-2 h-8 w-8" />
            <p className="text-muted-foreground text-sm">
              하위 품목이 없습니다.
            </p>
            <p className="text-muted-foreground text-xs">
              &quot;품목추가&quot; 버튼을 눌러 추가하세요.
            </p>
          </div>
        ) : (
          renderNodes(treeData, 0)
        )}
      </div>

      {/* 품목 검색 모달 */}
      <ItemSearchModal
        open={itemSearchOpen}
        onClose={() => setItemSearchOpen(false)}
        onSelect={handleItemSelect}
        companyCode={companyCode}
      />
    </div>
  );
}

export default BomItemEditorComponent;
