"use client";

import React, { useState, useMemo, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { ChevronRight, ChevronLeft, ChevronDown, ChevronUp, ChevronsRight, ChevronsLeft, ChevronsDown, ChevronsUp, Search } from "lucide-react";
import { cn } from "@/lib/utils";

/**
 * DualListBox 아이템 인터페이스
 */
export interface DualListBoxItem {
  id: string;
  label: string;
  description?: string;
  disabled?: boolean;
  [key: string]: any;
}

/**
 * DualListBox 컴포넌트 Props
 */
interface DualListBoxProps {
  // 데이터
  availableItems: DualListBoxItem[];
  selectedItems: DualListBoxItem[];

  // 이벤트
  onSelectionChange: (selectedItems: DualListBoxItem[]) => void;

  // 라벨
  availableLabel?: string;
  selectedLabel?: string;

  // 검색 활성화
  enableSearch?: boolean;

  // 높이 설정
  height?: string;

  // 비활성화
  disabled?: boolean;

  // 커스텀 렌더링
  renderItem?: (item: DualListBoxItem) => React.ReactNode;

  // 스타일
  className?: string;
}

/**
 * Dual List Box 컴포넌트 (좌우 이동 방식)
 *
 * 사용 예시:
 * ```tsx
 * <DualListBox
 *   availableItems={allUsers}
 *   selectedItems={groupMembers}
 *   onSelectionChange={setGroupMembers}
 *   availableLabel="전체 사용자"
 *   selectedLabel="그룹 멤버"
 *   enableSearch
 * />
 * ```
 */
export function DualListBox({
  availableItems = [],
  selectedItems = [],
  onSelectionChange,
  availableLabel = "사용 가능한 항목",
  selectedLabel = "선택된 항목",
  enableSearch = true,
  height = "400px",
  disabled = false,
  renderItem,
  className,
}: DualListBoxProps) {
  // 선택된 아이템 ID 목록 (안전하게 처리)
  const selectedItemIds = useMemo(() => new Set((selectedItems || []).map((item) => item.id)), [selectedItems]);

  // 사용 가능한 아이템 (선택되지 않은 것들만)
  const available = useMemo(
    () => (availableItems || []).filter((item) => !selectedItemIds.has(item.id)),
    [availableItems, selectedItemIds],
  );

  // 좌측 체크된 아이템
  const [leftChecked, setLeftChecked] = useState<Set<string>>(new Set());

  // 우측 체크된 아이템
  const [rightChecked, setRightChecked] = useState<Set<string>>(new Set());

  // 좌측 검색어
  const [leftSearch, setLeftSearch] = useState("");

  // 우측 검색어
  const [rightSearch, setRightSearch] = useState("");

  // 검색 필터링
  const filterItems = useCallback((items: DualListBoxItem[], searchTerm: string) => {
    if (!searchTerm.trim()) return items;
    const term = searchTerm.toLowerCase();
    return items.filter(
      (item) => item.label.toLowerCase().includes(term) || item.description?.toLowerCase().includes(term),
    );
  }, []);

  const filteredAvailable = useMemo(() => filterItems(available, leftSearch), [available, leftSearch, filterItems]);

  const filteredSelected = useMemo(
    () => filterItems(selectedItems, rightSearch),
    [selectedItems, rightSearch, filterItems],
  );

  // 좌측 체크박스 토글
  const handleLeftCheck = useCallback((itemId: string, checked: boolean) => {
    setLeftChecked((prev) => {
      const newSet = new Set(prev);
      if (checked) {
        newSet.add(itemId);
      } else {
        newSet.delete(itemId);
      }
      return newSet;
    });
  }, []);

  // 우측 체크박스 토글
  const handleRightCheck = useCallback((itemId: string, checked: boolean) => {
    setRightChecked((prev) => {
      const newSet = new Set(prev);
      if (checked) {
        newSet.add(itemId);
      } else {
        newSet.delete(itemId);
      }
      return newSet;
    });
  }, []);

  // 좌측 전체 선택/해제
  const handleLeftSelectAll = useCallback(() => {
    if (leftChecked.size === filteredAvailable.length) {
      setLeftChecked(new Set());
    } else {
      setLeftChecked(new Set(filteredAvailable.map((item) => item.id)));
    }
  }, [leftChecked.size, filteredAvailable]);

  // 우측 전체 선택/해제
  const handleRightSelectAll = useCallback(() => {
    if (rightChecked.size === filteredSelected.length) {
      setRightChecked(new Set());
    } else {
      setRightChecked(new Set(filteredSelected.map((item) => item.id)));
    }
  }, [rightChecked.size, filteredSelected]);

  // 선택된 항목 오른쪽으로 이동
  const moveToRight = useCallback(() => {
    const itemsToMove = available.filter((item) => leftChecked.has(item.id));
    onSelectionChange([...selectedItems, ...itemsToMove]);
    setLeftChecked(new Set());
  }, [available, leftChecked, selectedItems, onSelectionChange]);

  // 선택된 항목 왼쪽으로 이동
  const moveToLeft = useCallback(() => {
    const newSelected = selectedItems.filter((item) => !rightChecked.has(item.id));
    onSelectionChange(newSelected);
    setRightChecked(new Set());
  }, [selectedItems, rightChecked, onSelectionChange]);

  // 모든 항목 오른쪽으로 이동
  const moveAllToRight = useCallback(() => {
    onSelectionChange([...selectedItems, ...available]);
    setLeftChecked(new Set());
  }, [available, selectedItems, onSelectionChange]);

  // 모든 항목 왼쪽으로 이동
  const moveAllToLeft = useCallback(() => {
    onSelectionChange([]);
    setRightChecked(new Set());
  }, [onSelectionChange]);

  // 기본 아이템 렌더링
  const defaultRenderItem = useCallback((item: DualListBoxItem) => {
    return (
      <div className="flex flex-col">
        <span className="text-sm font-medium">{item.label}</span>
        {item.description && <span className="text-muted-foreground text-xs">{item.description}</span>}
      </div>
    );
  }, []);

  const itemRenderer = renderItem || defaultRenderItem;

  return (
    <div className={cn("flex flex-col gap-4 sm:flex-row", className)}>
      {/* 좌측 리스트 (사용 가능한 항목) */}
      <div className="flex w-full flex-col gap-2 sm:flex-1">
        <Label className="text-sm font-semibold">{availableLabel}</Label>

        {/* 검색 */}
        {enableSearch && (
          <div className="relative">
            <Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
            <Input
              placeholder="검색..."
              value={leftSearch}
              onChange={(e) => setLeftSearch(e.target.value)}
              className="h-9 w-full pl-9 text-sm"
              disabled={disabled}
            />
          </div>
        )}

        {/* 전체 선택 */}
        <div className="flex items-center gap-2">
          <Checkbox
            id="left-select-all"
            checked={filteredAvailable.length > 0 && leftChecked.size === filteredAvailable.length}
            onCheckedChange={handleLeftSelectAll}
            disabled={disabled || filteredAvailable.length === 0}
          />
          <Label htmlFor="left-select-all" className="text-muted-foreground cursor-pointer text-xs">
            전체 선택 ({filteredAvailable.length}개)
          </Label>
        </div>

        {/* 아이템 리스트 */}
        <div className="bg-background overflow-y-auto rounded-lg border" style={{ height }}>
          {filteredAvailable.length === 0 ? (
            <div className="flex h-full items-center justify-center">
              <p className="text-muted-foreground text-sm">
                {leftSearch ? "검색 결과가 없습니다" : "사용 가능한 항목이 없습니다"}
              </p>
            </div>
          ) : (
            <div className="space-y-1 p-2">
              {filteredAvailable.map((item) => (
                <div
                  key={item.id}
                  className={cn(
                    "hover:bg-muted/50 flex cursor-pointer items-start gap-2 rounded-md p-2 transition-colors",
                    leftChecked.has(item.id) && "bg-muted",
                    item.disabled && "cursor-not-allowed opacity-50",
                  )}
                  onClick={() => !item.disabled && !disabled && handleLeftCheck(item.id, !leftChecked.has(item.id))}
                >
                  <Checkbox
                    checked={leftChecked.has(item.id)}
                    onCheckedChange={(checked) => handleLeftCheck(item.id, checked as boolean)}
                    disabled={disabled || item.disabled}
                    className="mt-0.5"
                  />
                  {itemRenderer(item)}
                </div>
              ))}
            </div>
          )}
        </div>
      </div>

      {/* 중앙 버튼 (이동) - 모바일: 가로 배치, 데스크톱: 세로 배치 */}
      <div className="flex flex-row items-center justify-center gap-2 sm:flex-col sm:justify-center">
        {/* 모두 이동: 모바일은 아래/위, 데스크톱은 오른쪽/왼쪽 */}
        <Button
          variant="outline"
          size="icon"
          onClick={moveAllToRight}
          disabled={disabled || available.length === 0}
          title="모두 이동"
          className="h-9 w-9"
        >
          <ChevronsDown className="h-4 w-4 sm:hidden" />
          <ChevronsRight className="hidden h-4 w-4 sm:inline-flex" />
        </Button>
        <Button
          variant="outline"
          size="icon"
          onClick={moveToRight}
          disabled={disabled || leftChecked.size === 0}
          title="선택된 항목 이동"
          className="h-9 w-9"
        >
          <ChevronDown className="h-4 w-4 sm:hidden" />
          <ChevronRight className="hidden h-4 w-4 sm:inline-flex" />
        </Button>
        <Button
          variant="outline"
          size="icon"
          onClick={moveToLeft}
          disabled={disabled || rightChecked.size === 0}
          title="선택된 항목 되돌리기"
          className="h-9 w-9"
        >
          <ChevronUp className="h-4 w-4 sm:hidden" />
          <ChevronLeft className="hidden h-4 w-4 sm:inline-flex" />
        </Button>
        <Button
          variant="outline"
          size="icon"
          onClick={moveAllToLeft}
          disabled={disabled || selectedItems.length === 0}
          title="모두 되돌리기"
          className="h-9 w-9"
        >
          <ChevronsUp className="h-4 w-4 sm:hidden" />
          <ChevronsLeft className="hidden h-4 w-4 sm:inline-flex" />
        </Button>
      </div>

      {/* 우측 리스트 (선택된 항목) */}
      <div className="flex w-full flex-col gap-2 sm:flex-1">
        <Label className="text-sm font-semibold">{selectedLabel}</Label>

        {/* 검색 */}
        {enableSearch && (
          <div className="relative">
            <Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
            <Input
              placeholder="검색..."
              value={rightSearch}
              onChange={(e) => setRightSearch(e.target.value)}
              className="h-9 w-full pl-9 text-sm"
              disabled={disabled}
            />
          </div>
        )}

        {/* 전체 선택 */}
        <div className="flex items-center gap-2">
          <Checkbox
            id="right-select-all"
            checked={filteredSelected.length > 0 && rightChecked.size === filteredSelected.length}
            onCheckedChange={handleRightSelectAll}
            disabled={disabled || filteredSelected.length === 0}
          />
          <Label htmlFor="right-select-all" className="text-muted-foreground cursor-pointer text-xs">
            전체 선택 ({filteredSelected.length}개)
          </Label>
        </div>

        {/* 아이템 리스트 */}
        <div className="bg-background overflow-y-auto rounded-lg border" style={{ height }}>
          {filteredSelected.length === 0 ? (
            <div className="flex h-full items-center justify-center">
              <p className="text-muted-foreground text-sm">
                {rightSearch ? "검색 결과가 없습니다" : "선택된 항목이 없습니다"}
              </p>
            </div>
          ) : (
            <div className="space-y-1 p-2">
              {filteredSelected.map((item) => (
                <div
                  key={item.id}
                  className={cn(
                    "hover:bg-muted/50 flex cursor-pointer items-start gap-2 rounded-md p-2 transition-colors",
                    rightChecked.has(item.id) && "bg-muted",
                    item.disabled && "cursor-not-allowed opacity-50",
                  )}
                  onClick={() => !item.disabled && !disabled && handleRightCheck(item.id, !rightChecked.has(item.id))}
                >
                  <Checkbox
                    checked={rightChecked.has(item.id)}
                    onCheckedChange={(checked) => handleRightCheck(item.id, checked as boolean)}
                    disabled={disabled || item.disabled}
                    className="mt-0.5"
                  />
                  {itemRenderer(item)}
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
