/**
 * V3 메타 컴포넌트 - Field 렌더러
 * 
 * V2를 래핑하지 않고 자체적으로 완전히 동작하는 입력 컴포넌트
 * webType에 따라 적절한 shadcn/ui 컴포넌트로 렌더링
 * formData 기반 데이터 바인딩 지원
 */

"use client";

import React, { useEffect, useState, useCallback } from "react";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { Button } from "@/components/ui/button";
import { Check, ChevronsUpDown, Upload, X } from "lucide-react";
import { cn } from "@/lib/utils";
import { FieldComponentConfig } from "@/lib/api/metaComponent";
import apiClient from "@/lib/api/client";

interface FieldRendererProps {
  id: string;
  config: FieldComponentConfig;
  // 데이터 바인딩 (상위에서 전달)
  formData?: Record<string, any>;
  onFormDataChange?: (fieldName: string, value: any) => void;
  // 컨텍스트
  tableName?: string;
  companyCode?: string;
  screenId?: number;
  // UI 모드
  isDesignMode?: boolean;
  disabled?: boolean;
  className?: string;
}

export function FieldRenderer({
  id,
  config,
  formData,
  onFormDataChange,
  tableName,
  companyCode,
  screenId,
  isDesignMode = false,
  disabled = false,
  className,
}: FieldRendererProps) {
  // 현재 값: formData[binding]에서 읽기
  const binding = config.binding || "";
  const currentValue = formData?.[binding] ?? config.defaultValue ?? "";

  // Entity Search 상태
  const [entitySearchOpen, setEntitySearchOpen] = useState(false);
  const [entityOptions, setEntityOptions] = useState<any[]>([]);
  const [entitySearchTerm, setEntitySearchTerm] = useState("");
  const [entityLoading, setEntityLoading] = useState(false);

  // Category 상태
  const [categoryOptions, setCategoryOptions] = useState<any[]>([]);
  const [categoryLoading, setCategoryLoading] = useState(false);

  // File Upload 상태
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [filePreview, setFilePreview] = useState<string | null>(null);
  const [isDragging, setIsDragging] = useState(false);

  // 값 변경 핸들러
  const handleChange = (newValue: any) => {
    if (isDesignMode) return; // 디자인 모드에서는 값 변경 불가
    if ((config as any).readonly) return; // 읽기 전용이면 변경 불가 (타입에 추가 예정)
    
    if (onFormDataChange && binding) {
      onFormDataChange(binding, newValue);
    }
  };

  // autoFill 설정 확인
  const autoFillConfig = (config as any)._originalConfig?.autoFill || (config as any).autoFill;
  
  // 실제 disabled 상태: 디자인 모드 OR disabled prop OR readonly OR autoFill
  const isDisabled = isDesignMode || disabled || (config as any).readonly || (autoFillConfig?.enabled && !!currentValue);

  // autoFill 로직: 마운트 시 자동으로 데이터 로드
  useEffect(() => {
    if (!autoFillConfig?.enabled || !companyCode || currentValue || isDesignMode) return;

    const fetchAutoFillData = async () => {
      try {
        const response = await apiClient.post(
          `/api/table-management/tables/${autoFillConfig.sourceTable}/data`,
          {
            page: 1,
            size: 1,
            filters: {
              [autoFillConfig.filterColumn]: companyCode,
            },
          }
        );

        if (response.data?.success && response.data.data?.length > 0) {
          const value = response.data.data[0][autoFillConfig.displayColumn];
          handleChange(value);
        }
      } catch (error) {
        console.error("[FieldRenderer] autoFill 에러:", error);
      }
    };

    fetchAutoFillData();
  }, [autoFillConfig, companyCode, currentValue, isDesignMode]);

  // Category 데이터 로드
  useEffect(() => {
    if (config.webType !== "category" || isDesignMode) return;

    const fetchCategories = async () => {
      setCategoryLoading(true);
      try {
        const response = await apiClient.get("/api/admin/categories/tree");
        
        if (response.data?.success) {
          let categories = response.data.data || [];
          
          // categoryGroupCode 필터링
          const categoryGroupCode = (config as any).categoryGroupCode;
          if (categoryGroupCode) {
            categories = categories.filter((cat: any) => cat.groupCode === categoryGroupCode);
          }
          
          setCategoryOptions(categories);
        }
      } catch (error) {
        console.error("[FieldRenderer] category 로드 에러:", error);
      } finally {
        setCategoryLoading(false);
      }
    };

    fetchCategories();
  }, [config.webType, isDesignMode]);

  // Entity Search: debounced 검색
  const searchEntityDebounced = useCallback(
    async (searchTerm: string) => {
      if (!config.join?.sourceTable || !searchTerm) {
        setEntityOptions([]);
        return;
      }

      setEntityLoading(true);
      try {
        const response = await apiClient.post(
          `/api/table-management/tables/${config.join.sourceTable}/data`,
          {
            page: 1,
            size: 20,
            search: searchTerm,
          }
        );

        if (response.data?.success) {
          setEntityOptions(response.data.data || []);
        }
      } catch (error) {
        console.error("[FieldRenderer] entity search 에러:", error);
      } finally {
        setEntityLoading(false);
      }
    },
    [config.join]
  );

  // Entity Search: debounce 적용
  useEffect(() => {
    if (config.webType !== "entity" || !entitySearchOpen) return;

    const timer = setTimeout(() => {
      searchEntityDebounced(entitySearchTerm);
    }, 300);

    return () => clearTimeout(timer);
  }, [entitySearchTerm, entitySearchOpen, config.webType, searchEntityDebounced]);

  // File Upload: 파일 선택 핸들러
  const handleFileSelect = (file: File | null) => {
    if (!file) return;

    const fileConfig = (config as any).fileConfig;
    
    // 파일 크기 검증
    if (fileConfig?.maxSize && file.size > fileConfig.maxSize * 1024 * 1024) {
      alert(`파일 크기는 ${fileConfig.maxSize}MB를 초과할 수 없습니다.`);
      return;
    }

    // 파일 타입 검증
    if (fileConfig?.accept && !fileConfig.accept.split(",").some((type: string) => file.type.includes(type.trim()))) {
      alert(`허용된 파일 형식: ${fileConfig.accept}`);
      return;
    }

    setSelectedFile(file);
    handleChange(file.name);

    // 이미지 미리보기
    if (file.type.startsWith("image/")) {
      const reader = new FileReader();
      reader.onload = (e) => setFilePreview(e.target?.result as string);
      reader.readAsDataURL(file);
    } else {
      setFilePreview(null);
    }
  };

  // File Upload: 드래그앤드롭
  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(true);
  };

  const handleDragLeave = () => {
    setIsDragging(false);
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);

    const file = e.dataTransfer.files[0];
    if (file) handleFileSelect(file);
  };

  // 렌더링할 입력 컴포넌트 선택
  const renderInputField = () => {
    const webType = config.webType || "text";

    switch (webType) {
      // ============ 텍스트 계열 ============
      case "text":
      case "email":
      case "tel":
      case "url":
      case "password":
        return (
          <Input
            id={id}
            type={webType}
            value={currentValue || ""}
            onChange={(e) => handleChange(e.target.value)}
            placeholder={config.placeholder}
            disabled={isDisabled}
            maxLength={config.validation?.max}
            className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}
          />
        );

      // ============ 숫자 입력 ============
      case "number":
        return (
          <Input
            id={id}
            type="number"
            value={currentValue || ""}
            onChange={(e) => handleChange(e.target.value ? Number(e.target.value) : "")}
            placeholder={config.placeholder}
            disabled={isDisabled}
            min={config.validation?.min}
            max={config.validation?.max}
            className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}
          />
        );

      // ============ 텍스트 영역 ============
      case "textarea":
        return (
          <Textarea
            id={id}
            value={currentValue || ""}
            onChange={(e) => handleChange(e.target.value)}
            placeholder={config.placeholder}
            disabled={isDisabled}
            maxLength={config.validation?.max}
            rows={4}
            className={cn("text-xs sm:text-sm", className)}
          />
        );

      // ============ 날짜/시간 ============
      case "date":
        return (
          <Input
            id={id}
            type="date"
            value={currentValue || ""}
            onChange={(e) => handleChange(e.target.value)}
            disabled={isDisabled}
            className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}
          />
        );

      case "datetime":
        return (
          <Input
            id={id}
            type="datetime-local"
            value={currentValue || ""}
            onChange={(e) => handleChange(e.target.value)}
            disabled={isDisabled}
            className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}
          />
        );

      // ============ Select (드롭다운) ============
      case "select":
        return (
          <Select
            value={currentValue || ""}
            onValueChange={handleChange}
            disabled={isDisabled}
          >
            <SelectTrigger id={id} className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}>
              <SelectValue placeholder={config.placeholder || "선택하세요"} />
            </SelectTrigger>
            <SelectContent>
              {config.options?.map((option) => (
                <SelectItem key={option.value} value={option.value} className="text-xs sm:text-sm">
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        );

      // ============ 체크박스 ============
      case "checkbox":
        return (
          <div className="flex items-center space-x-2">
            <Checkbox
              id={id}
              checked={!!currentValue}
              onCheckedChange={handleChange}
              disabled={isDisabled}
            />
            <label
              htmlFor={id}
              className="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 sm:text-sm"
            >
              {config.label}
            </label>
          </div>
        );

      // ============ 라디오 그룹 ============
      case "radio":
        return (
          <RadioGroup
            value={currentValue || ""}
            onValueChange={handleChange}
            disabled={isDisabled}
          >
            {config.options?.map((option) => (
              <div key={option.value} className="flex items-center space-x-2">
                <RadioGroupItem value={option.value} id={`${id}-${option.value}`} />
                <Label htmlFor={`${id}-${option.value}`} className="text-xs sm:text-sm">
                  {option.label}
                </Label>
              </div>
            ))}
          </RadioGroup>
        );

      // ============ 토글 스위치 ============
      case "toggle":
        return (
          <div className="flex items-center space-x-2">
            <Switch
              id={id}
              checked={!!currentValue}
              onCheckedChange={handleChange}
              disabled={isDisabled}
            />
            <Label htmlFor={id} className="text-xs sm:text-sm">
              {config.label}
            </Label>
          </div>
        );

      // ============ 파일 업로드 (간단 버전) ============
      case "file":
        const fileConfig = (config as any).fileConfig;
        
        return (
          <div className="space-y-2">
            <div
              onDragOver={handleDragOver}
              onDragLeave={handleDragLeave}
              onDrop={handleDrop}
              className={cn(
                "flex flex-col items-center justify-center rounded-lg border-2 border-dashed p-4 transition-colors",
                isDragging ? "border-primary bg-primary/5" : "border-muted-foreground/25",
                isDisabled && "cursor-not-allowed opacity-50"
              )}
            >
              {filePreview ? (
                <div className="relative">
                  <img src={filePreview} alt="미리보기" className="max-h-32 rounded" />
                  <Button
                    type="button"
                    size="icon"
                    variant="destructive"
                    className="absolute -right-2 -top-2 h-6 w-6"
                    onClick={() => {
                      setSelectedFile(null);
                      setFilePreview(null);
                      handleChange("");
                    }}
                    disabled={isDisabled}
                  >
                    <X className="h-3 w-3" />
                  </Button>
                </div>
              ) : (
                <>
                  <Upload className="mb-2 h-8 w-8 text-muted-foreground" />
                  <p className="text-xs text-muted-foreground sm:text-sm">
                    {selectedFile ? selectedFile.name : "파일을 드래그하거나 클릭하세요"}
                  </p>
                  {fileConfig?.accept && (
                    <p className="text-[10px] text-muted-foreground">허용: {fileConfig.accept}</p>
                  )}
                </>
              )}
              <Input
                id={id}
                type="file"
                accept={fileConfig?.accept}
                onChange={(e) => {
                  const file = e.target.files?.[0];
                  if (file) handleFileSelect(file);
                }}
                disabled={isDisabled}
                className="hidden"
              />
              {!filePreview && (
                <label
                  htmlFor={id}
                  className={cn(
                    "mt-2 cursor-pointer rounded-md bg-primary px-3 py-1 text-xs text-primary-foreground hover:bg-primary/90",
                    isDisabled && "pointer-events-none"
                  )}
                >
                  파일 선택
                </label>
              )}
            </div>
          </div>
        );

      // ============ 엔티티 (간단 텍스트 입력, 향후 검색 기능 추가) ============
      case "entity":
        // join 설정이 있으면 검색 가능한 combobox
        if (config.join?.sourceTable) {
          const displayValue = entityOptions.find(
            (opt) => opt[config.join!.valueColumn] === currentValue
          )?.[config.join!.displayColumn] || currentValue;

          return (
            <Popover open={entitySearchOpen} onOpenChange={setEntitySearchOpen}>
              <PopoverTrigger asChild>
                <Button
                  id={id}
                  variant="outline"
                  role="combobox"
                  aria-expanded={entitySearchOpen}
                  disabled={isDisabled}
                  className={cn(
                    "h-8 w-full justify-between text-xs sm:h-10 sm:text-sm",
                    !currentValue && "text-muted-foreground",
                    className
                  )}
                >
                  {displayValue || config.placeholder || "검색하세요"}
                  <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                </Button>
              </PopoverTrigger>
              <PopoverContent
                className="p-0"
                style={{ width: "var(--radix-popover-trigger-width)" }}
                align="start"
              >
                <Command>
                  <CommandInput
                    placeholder="검색..."
                    value={entitySearchTerm}
                    onValueChange={setEntitySearchTerm}
                    className="text-xs sm:text-sm"
                  />
                  <CommandList>
                    {entityLoading ? (
                      <div className="py-6 text-center text-xs text-muted-foreground">로딩 중...</div>
                    ) : entityOptions.length === 0 ? (
                      <CommandEmpty className="text-xs sm:text-sm">
                        결과가 없습니다.
                      </CommandEmpty>
                    ) : (
                      <CommandGroup>
                        {entityOptions.map((option) => {
                          const optionValue = option[config.join!.valueColumn];
                          const optionLabel = option[config.join!.displayColumn];

                          return (
                            <CommandItem
                              key={optionValue}
                              value={optionValue}
                              onSelect={() => {
                                handleChange(optionValue);
                                setEntitySearchOpen(false);
                              }}
                              className="text-xs sm:text-sm"
                            >
                              <Check
                                className={cn(
                                  "mr-2 h-4 w-4",
                                  currentValue === optionValue ? "opacity-100" : "opacity-0"
                                )}
                              />
                              {optionLabel}
                            </CommandItem>
                          );
                        })}
                      </CommandGroup>
                    )}
                  </CommandList>
                </Command>
              </PopoverContent>
            </Popover>
          );
        }

        // join 설정 없으면 일반 텍스트 입력
        return (
          <Input
            id={id}
            type="text"
            value={currentValue || ""}
            onChange={(e) => handleChange(e.target.value)}
            placeholder={config.placeholder || `${config.join?.displayColumn || "항목"} 입력`}
            disabled={isDisabled}
            className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}
          />
        );

      // ============ 카테고리 (드롭다운) ============
      case "category":
        return (
          <Select
            value={currentValue || ""}
            onValueChange={handleChange}
            disabled={isDisabled || categoryLoading}
          >
            <SelectTrigger id={id} className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}>
              <SelectValue placeholder={categoryLoading ? "로딩 중..." : config.placeholder || "카테고리 선택"} />
            </SelectTrigger>
            <SelectContent>
              {categoryOptions.map((category) => (
                <SelectItem
                  key={category.categoryCode}
                  value={category.categoryCode}
                  className="text-xs sm:text-sm"
                >
                  {category.categoryName}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        );

      // ============ 채번 필드 (읽기 전용) ============
      case "numbering":
        return (
          <Input
            id={id}
            type="text"
            value={currentValue || "(자동 생성)"}
            readOnly
            disabled
            className={cn("h-8 text-xs sm:h-10 sm:text-sm bg-muted", className)}
          />
        );

      // ============ 기본 (텍스트) ============
      default:
        return (
          <Input
            id={id}
            type="text"
            value={currentValue || ""}
            onChange={(e) => handleChange(e.target.value)}
            placeholder={config.placeholder}
            disabled={isDisabled}
            className={cn("h-8 text-xs sm:h-10 sm:text-sm", className)}
          />
        );
    }
  };

  // checkbox, toggle 타입은 자체 라벨 포함
  const hasInternalLabel = config.webType === "checkbox" || config.webType === "toggle";

  // 라벨 없이 렌더링
  if (hasInternalLabel || !config.label) {
    return (
      <div className={cn("space-y-1", className)}>
        {renderInputField()}
      </div>
    );
  }

  // 라벨과 함께 렌더링
  return (
    <div className={cn("space-y-1.5", className)}>
      <Label htmlFor={id} className="text-xs font-medium sm:text-sm">
        {config.label}
        {config.required && <span className="ml-1 text-destructive">*</span>}
      </Label>
      {renderInputField()}
      {config.placeholder && (
        <p className="text-[10px] text-muted-foreground sm:text-xs">
          {config.placeholder}
        </p>
      )}
    </div>
  );
}
