/**
 * File 필드 컴포넌트
 * 파일/이미지 첨부 (드래그 앤 드롭 + 파일 선택)
 *
 * API 연동 전: File 객체를 로컬 상태로 관리, URL.createObjectURL로 미리보기
 * API 연동 시: POST /v1/files/upload (multipart)
 */

'use client';

import { useState, useRef, useCallback } from 'react';
import { Upload, X, FileIcon, ImageIcon } from 'lucide-react';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import type { DynamicFieldRendererProps, FileConfig } from '../types';

interface LocalFile {
  file: File;
  previewUrl?: string;
}

function formatFileSize(bytes: number): string {
  if (bytes < 1024) return `${bytes}B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
}

function isImageFile(file: File): boolean {
  return file.type.startsWith('image/');
}

export function FileField({
  field,
  value,
  onChange,
  error,
  disabled,
}: DynamicFieldRendererProps) {
  const fieldKey = field.field_key || `field_${field.id}`;
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [localFiles, setLocalFiles] = useState<LocalFile[]>([]);
  const [isDragOver, setIsDragOver] = useState(false);

  const config = (field.properties || {}) as FileConfig;
  const accept = config.accept || '*';
  const maxSize = config.maxSize || 10485760; // 10MB
  const maxFiles = config.maxFiles || 1;
  const showPreview = config.preview !== false;

  // 파일 추가
  const addFiles = useCallback((newFiles: FileList | File[]) => {
    const files = Array.from(newFiles);
    const validFiles: LocalFile[] = [];

    for (const file of files) {
      if (localFiles.length + validFiles.length >= maxFiles) break;
      if (file.size > maxSize) continue;

      const previewUrl = showPreview && isImageFile(file)
        ? URL.createObjectURL(file)
        : undefined;
      validFiles.push({ file, previewUrl });
    }

    if (validFiles.length === 0) return;

    const updated = [...localFiles, ...validFiles];
    setLocalFiles(updated);
    // 단일 파일이면 File 객체, 복수면 배열 이름을 저장
    onChange(maxFiles === 1
      ? updated[0]?.file.name || null
      : updated.map(f => f.file.name)
    );
  }, [localFiles, maxFiles, maxSize, showPreview, onChange]);

  // 파일 제거
  const removeFile = (index: number) => {
    const file = localFiles[index];
    if (file.previewUrl) URL.revokeObjectURL(file.previewUrl);
    const updated = localFiles.filter((_, i) => i !== index);
    setLocalFiles(updated);
    onChange(updated.length === 0 ? null : (
      maxFiles === 1 ? updated[0]?.file.name : updated.map(f => f.file.name)
    ));
  };

  // 드래그 핸들러
  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    if (!disabled) setIsDragOver(true);
  };
  const handleDragLeave = () => setIsDragOver(false);
  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragOver(false);
    if (!disabled && e.dataTransfer.files.length > 0) {
      addFiles(e.dataTransfer.files);
    }
  };

  const canAddMore = localFiles.length < maxFiles;
  // value가 이미 있으면 (서버에서 받은 파일명) 기존 파일 표시
  const existingFileName = typeof value === 'string' && value && localFiles.length === 0 ? value : null;

  return (
    <div>
      <Label htmlFor={fieldKey}>
        {field.field_name}
        {field.is_required && <span className="text-red-500"> *</span>}
      </Label>

      {/* 드래그 앤 드롭 영역 */}
      {canAddMore && !disabled && (
        <div
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onDrop={handleDrop}
          className={`mt-1 flex flex-col items-center justify-center rounded-lg border-2 border-dashed p-6 transition-colors cursor-pointer ${
            isDragOver ? 'border-primary bg-primary/5' : 'border-muted-foreground/25 hover:border-muted-foreground/50'
          } ${error ? 'border-red-500' : ''}`}
          onClick={() => fileInputRef.current?.click()}
        >
          <Upload className="h-8 w-8 text-muted-foreground mb-2" />
          <p className="text-sm text-muted-foreground">
            파일을 드래그하거나 클릭하여 선택
          </p>
          <p className="text-xs text-muted-foreground mt-1">
            최대 {formatFileSize(maxSize)}
            {accept !== '*' && ` (${accept})`}
          </p>
        </div>
      )}

      <input
        ref={fileInputRef}
        type="file"
        id={fieldKey}
        accept={accept}
        multiple={maxFiles > 1}
        className="hidden"
        onChange={(e) => e.target.files && addFiles(e.target.files)}
      />

      {/* 기존 파일 (서버에서 받은) */}
      {existingFileName && (
        <div className="mt-2 flex items-center gap-2 rounded-md border p-2">
          <FileIcon className="h-4 w-4 text-muted-foreground shrink-0" />
          <span className="text-sm truncate flex-1">{existingFileName}</span>
        </div>
      )}

      {/* 선택된 파일 목록 */}
      {localFiles.length > 0 && (
        <div className="mt-2 space-y-2">
          {localFiles.map((lf, index) => (
            <div key={index} className="flex items-center gap-2 rounded-md border p-2">
              {/* 이미지 미리보기 */}
              {lf.previewUrl ? (
                <img
                  src={lf.previewUrl}
                  alt={lf.file.name}
                  className="h-10 w-10 rounded object-cover shrink-0"
                />
              ) : (
                isImageFile(lf.file)
                  ? <ImageIcon className="h-4 w-4 text-muted-foreground shrink-0" />
                  : <FileIcon className="h-4 w-4 text-muted-foreground shrink-0" />
              )}
              <div className="flex-1 min-w-0">
                <p className="text-sm truncate">{lf.file.name}</p>
                <p className="text-xs text-muted-foreground">{formatFileSize(lf.file.size)}</p>
              </div>
              {!disabled && (
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-6 w-6 shrink-0"
                  onClick={() => removeFile(index)}
                >
                  <X className="h-3 w-3" />
                </Button>
              )}
            </div>
          ))}
        </div>
      )}

      {error && (
        <p className="text-xs text-red-500 mt-1">{error}</p>
      )}
      {!error && field.description && (
        <p className="text-xs text-muted-foreground mt-1">
          * {field.description}
        </p>
      )}
    </div>
  );
}
