"use client";

import React, { useState, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Search, X, ChevronLeft, ChevronRight } from "lucide-react";
import { useDebounce } from "@/hooks/use-debounce";
import { searchMaterialsForDialog, MaterialSearchItem } from "./material-service";

/**
 * 자재 다중 선택 Dialog 컴포넌트
 *
 * @description
 * - TanStack Table을 사용한 효율적인 자재 다중 선택 Dialog
 * - 페이지네이션으로 데이터를 조회하고 클라이언트 사이드에서 검색 필터링
 * - 버튼 클릭 시 Dialog가 열리고, 여러 자재를 선택한 후 확인 버튼으로 완료
 * - 최대 선택 개수 제한 가능
 *
 * @MaterialSearchItem_Structure
 * 상태에서 관리되는 자재 객체의 형태:
 * ```typescript
 * interface MaterialSearchItem {
 *   materialCode: string;        // 자재코드 (MATNR)
 *   materialName: string;        // 자재명 (ZZNAME)
 *   displayText: string;         // 표시용 텍스트 (code + " - " + name)
 * }
 * ```
 *
 * @state
 * - open: Dialog 열림/닫힘 상태
 * - selectedMaterials: 현재 선택된 자재들 (배열)
 * - tempSelectedMaterials: Dialog 내에서 임시로 선택된 자재들 (확인 버튼 클릭 전까지)
 * - searchQuery: 검색어
 * - currentPage: 현재 페이지
 * - searchResults: 검색 결과
 * - isSearching: 검색 중 상태
 * - error: 에러 상태
 *
 * @callback
 * - onMaterialsSelect: 자재 선택 완료 시 호출되는 콜백
 *   - 매개변수: MaterialSearchItem[]
 *   - 선택된 자재들의 배열 (빈 배열일 수도 있음)
 *
 * @usage
 * ```tsx
 * <MaterialSelectorDialogMulti
 *   triggerLabel="자재 선택 (다중)"
 *   selectedMaterials={selectedMaterials}
 *   onMaterialsSelect={(materials) => {
 *     setSelectedMaterials(materials);
 *     console.log('선택된 자재들:', materials);
 *   }}
 *   maxSelections={5}
 *   placeholder="자재코드를 검색하세요..."
 * />
 * ```
 */

interface MaterialSelectorDialogMultiProps {
  /** Dialog를 여는 트리거 버튼 텍스트 */
  triggerLabel?: string;
  /** 현재 선택된 자재들 */
  selectedMaterials?: MaterialSearchItem[];
  /** 자재 선택 완료 시 호출되는 콜백 */
  onMaterialsSelect?: (materials: MaterialSearchItem[]) => void;
  /** 최대 선택 가능한 자재 개수 */
  maxSelections?: number;
  /** 검색 입력창 placeholder */
  placeholder?: string;
  /** Dialog 제목 */
  title?: string;
  /** Dialog 설명 */
  description?: string;
  /** 트리거 버튼 비활성화 여부 */
  disabled?: boolean;
  /** 트리거 버튼 variant */
  triggerVariant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
  /** 제외할 자재코드들 */
  excludeMaterialCodes?: Set<string>;
  /** 트리거 버튼에서 선택된 자재들을 표시할지 여부 */
  showSelectedInTrigger?: boolean;
}

export function MaterialSelectorDialogMulti({
  triggerLabel = "자재 선택",
  selectedMaterials = [],
  onMaterialsSelect,
  maxSelections,
  placeholder = "자재코드를 검색하세요...",
  title = "자재 선택 (다중)",
  description,
  disabled = false,
  triggerVariant = "outline",
  excludeMaterialCodes,
  showSelectedInTrigger = true,
}: MaterialSelectorDialogMultiProps) {
  // Dialog 열림/닫힘 상태
  const [open, setOpen] = useState(false);

  // Dialog 내에서 임시로 선택된 자재들 (확인 버튼 클릭 전까지)
  const [tempSelectedMaterials, setTempSelectedMaterials] = useState<MaterialSearchItem[]>([]);

  // 검색어
  const [searchQuery, setSearchQuery] = useState("");

  // 페이지네이션 상태
  const [currentPage, setCurrentPage] = useState(1);
  const [searchResults, setSearchResults] = useState<MaterialSearchItem[]>([]);
  const [pagination, setPagination] = useState({
    page: 1,
    perPage: 10,
    total: 0,
    pageCount: 0,
    hasNextPage: false,
    hasPrevPage: false,
  });

  // 로딩 상태
  const [isSearching, setIsSearching] = useState(false);

  // 에러 상태
  const [error, setError] = useState<string | null>(null);

  // Debounce 적용된 검색어
  const debouncedSearchQuery = useDebounce(searchQuery, 300);

  // Dialog 설명 동적 생성
  const dialogDescription = description ||
    (maxSelections
      ? `원하는 자재를 검색하고 선택해주세요. (최대 ${maxSelections}개)`
      : "원하는 자재를 검색하고 선택해주세요."
    );

  // 검색 실행 함수
  const performSearch = useCallback(async (query: string, page: number = 1) => {
    setIsSearching(true);
    setError(null);

    try {
      const result = await searchMaterialsForDialog(query, page, 10);

      if (result.success) {
        setSearchResults(result.data);
        setPagination(result.pagination);
        setCurrentPage(page);
      } else {
        setSearchResults([]);
        setError(result.error || "검색 중 오류가 발생했습니다.");
        setPagination({
          page: 1,
          perPage: 10,
          total: 0,
          pageCount: 0,
          hasNextPage: false,
          hasPrevPage: false,
        });
      }
    } catch (err) {
      console.error("자재 검색 실패:", err);
      setSearchResults([]);
      setError("검색 중 오류가 발생했습니다.");
      setPagination({
        page: 1,
        perPage: 10,
        total: 0,
        pageCount: 0,
        hasNextPage: false,
        hasPrevPage: false,
      });
    } finally {
      setIsSearching(false);
    }
  }, []);

  // Dialog 열림 시 초기화 및 첫 검색
  const handleOpenChange = useCallback((newOpen: boolean) => {
    setOpen(newOpen);
    if (newOpen) {
      setTempSelectedMaterials([...selectedMaterials]);
      setSearchQuery("");
      setCurrentPage(1);
      // 초기 데이터 로드
      performSearch("", 1);
    }
  }, [selectedMaterials, performSearch]);

  // 검색어 변경 시 검색 실행
  React.useEffect(() => {
    if (open) {
      setCurrentPage(1);
      performSearch(debouncedSearchQuery, 1);
    }
  }, [debouncedSearchQuery, performSearch, open]);

  // 페이지 변경 처리
  const handlePageChange = useCallback((newPage: number) => {
    if (newPage >= 1 && newPage <= pagination.pageCount) {
      setCurrentPage(newPage);
      performSearch(debouncedSearchQuery, newPage);
    }
  }, [pagination.pageCount, performSearch, debouncedSearchQuery]);

  // 자재 선택/해제 처리
  const handleMaterialToggle = useCallback((material: MaterialSearchItem) => {
    setTempSelectedMaterials(prev => {
      const isSelected = prev.some(m => m.materialCode === material.materialCode);
      if (isSelected) {
        // 선택 해제
        return prev.filter(m => m.materialCode !== material.materialCode);
      } else {
        // 선택 추가 (최대 개수 확인)
        if (maxSelections && prev.length >= maxSelections) {
          return prev; // 최대 개수에 도달한 경우 추가하지 않음
        }
        return [...prev, material];
      }
    });
  }, [maxSelections]);

  // 전체 선택 해제
  const handleClearAll = useCallback(() => {
    setTempSelectedMaterials([]);
  }, []);

  // 확인 버튼 클릭 시 선택 완료
  const handleConfirm = useCallback(() => {
    onMaterialsSelect?.(tempSelectedMaterials);
    setOpen(false);
  }, [tempSelectedMaterials, onMaterialsSelect]);

  // 취소 버튼 클릭 시
  const handleCancel = useCallback(() => {
    setTempSelectedMaterials([...selectedMaterials]);
    setOpen(false);
  }, [selectedMaterials]);

  // 개별 자재 제거 (트리거 버튼에서)
  const handleRemoveMaterial = useCallback((materialToRemove: MaterialSearchItem, e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    const newMaterials = selectedMaterials.filter(
      (material) => !(material.materialCode === materialToRemove.materialCode &&
                     material.materialName === materialToRemove.materialName)
    );
    onMaterialsSelect?.(newMaterials);
  }, [selectedMaterials, onMaterialsSelect]);

  // 트리거 버튼 렌더링
  const renderTriggerContent = () => {
    if (selectedMaterials.length === 0) {
      return triggerLabel;
    }

    if (!showSelectedInTrigger) {
      return `${triggerLabel} (${selectedMaterials.length}개)`;
    }

    return (
      <div className="flex flex-wrap gap-1 items-center max-w-full">
        <span className="shrink-0">{triggerLabel}:</span>
        {selectedMaterials.slice(0, 2).map((material) => (
          <Badge
            key={`${material.materialCode}-${material.materialName}`}
            variant="secondary"
            className="gap-1 pr-1 max-w-[120px]"
          >
            <span className="truncate text-xs">
              {material.materialName}
            </span>
            {!disabled && (
              <button
                type="button"
                className="ml-1 h-3 w-3 rounded-sm hover:bg-red-100 flex items-center justify-center"
                onClick={(e) => handleRemoveMaterial(material, e)}
              >
                <X className="h-3 w-3 hover:text-red-500" />
              </button>
            )}
          </Badge>
        ))}
        {selectedMaterials.length > 2 && (
          <Badge variant="outline" className="text-xs">
            +{selectedMaterials.length - 2}개
          </Badge>
        )}
      </div>
    );
  };

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      <DialogTrigger asChild>
        <Button
          variant={triggerVariant}
          disabled={disabled}
          className="min-h-[2.5rem] h-auto justify-start"
        >
          {renderTriggerContent()}
        </Button>
      </DialogTrigger>

      <DialogContent className="max-w-4xl max-h-[80vh]">
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          <DialogDescription>{dialogDescription}</DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          {/* 검색 입력창 */}
          <div className="relative">
            <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" />
            <Input
              placeholder={placeholder}
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              className="pl-10"
            />
          </div>

          {/* 선택된 자재들 표시 */}
          {tempSelectedMaterials.length > 0 && (
            <div className="p-3 bg-blue-50 rounded-lg border">
              <div className="flex items-center justify-between mb-2">
                <span className="text-sm font-medium text-blue-900">
                  선택됨: {tempSelectedMaterials.length}
                  {maxSelections && `/${maxSelections}`}개
                </span>
                <Button variant="ghost" size="sm" onClick={handleClearAll}>
                  전체 해제
                </Button>
              </div>
              <div className="flex flex-wrap gap-1">
                {tempSelectedMaterials.map((material) => (
                  <Badge key={material.materialCode} variant="secondary" className="gap-1 pr-1">
                    <span className="text-xs">{material.displayText}</span>
                    <button
                      type="button"
                      onClick={() => handleMaterialToggle(material)}
                      className="ml-1 h-3 w-3 rounded-sm hover:bg-red-100 flex items-center justify-center"
                    >
                      <X className="h-3 w-3 hover:text-red-500" />
                    </button>
                  </Badge>
                ))}
              </div>
            </div>
          )}

          {/* 테이블 */}
          <div className="border rounded-lg max-h-96 overflow-y-auto">
            {isSearching ? (
              <div className="p-8 text-center text-muted-foreground">
                검색 중...
              </div>
            ) : error ? (
              <div className="p-8 text-center text-red-500">
                {error}
              </div>
            ) : (
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="w-12">선택</TableHead>
                    <TableHead>자재코드</TableHead>
                    <TableHead>자재명</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {searchResults.length === 0 ? (
                    <TableRow>
                      <TableCell colSpan={3} className="text-center py-8 text-muted-foreground">
                        {debouncedSearchQuery.trim() ? "검색 결과가 없습니다." : "자재가 없습니다."}
                      </TableCell>
                    </TableRow>
                  ) : (
                    searchResults.map((material) => {
                      const isExcluded = excludeMaterialCodes?.has(material.materialCode);
                      const isSelected = tempSelectedMaterials.some(m => m.materialCode === material.materialCode);
                      const isMaxReached = Boolean(maxSelections && tempSelectedMaterials.length >= maxSelections && !isSelected);

                      return (
                        <TableRow
                          key={material.materialCode}
                          className={`cursor-pointer hover:bg-muted/50 ${
                            isExcluded || isMaxReached ? 'opacity-50 cursor-not-allowed' : ''
                          } ${isSelected ? 'bg-blue-50' : ''}`}
                          onClick={() => {
                            if (!isExcluded && !isMaxReached) {
                              handleMaterialToggle(material);
                            }
                          }}
                        >
                          <TableCell>
                            <Checkbox
                              checked={isSelected}
                              disabled={isExcluded || isMaxReached}
                              onCheckedChange={() => {
                                if (!isExcluded && !isMaxReached) {
                                  handleMaterialToggle(material);
                                }
                              }}
                            />
                          </TableCell>
                          <TableCell className="font-mono text-sm">
                            {material.materialCode}
                            {isExcluded && (
                              <span className="ml-2 text-xs bg-red-100 text-red-600 px-2 py-1 rounded">
                                제외됨
                              </span>
                            )}
                            {isMaxReached && (
                              <span className="ml-2 text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded">
                                최대 선택
                              </span>
                            )}
                          </TableCell>
                          <TableCell>{material.materialName}</TableCell>
                        </TableRow>
                      );
                    })
                  )}
                </TableBody>
              </Table>
            )}
          </div>

          {/* 페이지네이션 */}
          {searchResults.length > 0 && pagination.pageCount > 1 && (
            <div className="flex items-center justify-between">
              <div className="text-sm text-muted-foreground">
                총 {pagination.total}개 중 {(pagination.page - 1) * pagination.perPage + 1}-
                {Math.min(pagination.page * pagination.perPage, pagination.total)}개 표시
              </div>
              <div className="flex items-center gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handlePageChange(currentPage - 1)}
                  disabled={!pagination.hasPrevPage || isSearching}
                >
                  <ChevronLeft className="h-4 w-4" />
                  이전
                </Button>
                <span className="text-sm">
                  {pagination.page} / {pagination.pageCount}
                </span>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handlePageChange(currentPage + 1)}
                  disabled={!pagination.hasNextPage || isSearching}
                >
                  다음
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
            </div>
          )}
        </div>

        <DialogFooter className="gap-2">
          <Button variant="outline" onClick={handleCancel}>
            취소
          </Button>
          {tempSelectedMaterials.length > 0 && (
            <Button variant="ghost" onClick={handleClearAll}>
              전체 해제
            </Button>
          )}
          <Button onClick={handleConfirm}>
            확인 ({tempSelectedMaterials.length}개)
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

/**
 * 사용 예시:
 *
 * ```tsx
 * const [selectedMaterials, setSelectedMaterials] = useState<MaterialSearchItem[]>([]);
 *
 * return (
 *   <MaterialSelectorDialogMulti
 *     triggerLabel="자재 선택"
 *     selectedMaterials={selectedMaterials}
 *     onMaterialsSelect={(materials) => {
 *       setSelectedMaterials(materials);
 *       console.log('선택된 자재들:', materials.map(m => ({
 *         code: m.materialCode,
 *         name: m.materialName,
 *         displayText: m.displayText
 *       })));
 *     }}
 *     maxSelections={5}
 *     title="필수 자재 선택"
 *     description="프로젝트에 필요한 자재들을 선택해주세요."
 *     showSelectedInTrigger={true}
 *   />
 * );
 * ```
 *
 * @advanced_usage
 * ```tsx
 * // 제외할 자재가 있는 경우
 * const excludedCodes = new Set(['MAT001', 'MAT002']);
 *
 * <MaterialSelectorDialogMulti
 *   selectedMaterials={selectedMaterials}
 *   onMaterialsSelect={setSelectedMaterials}
 *   excludeMaterialCodes={excludedCodes}
 *   maxSelections={3}
 *   triggerVariant="default"
 *   showSelectedInTrigger={false}
 * />
 * ```
 */
