'use client';

/**
 * FileInput - 기본 파일 선택 컴포넌트
 *
 * 사용 예시:
 * <FileInput
 *   accept=".pdf,.doc"
 *   maxSize={10}
 *   onFileSelect={(file) => setFile(file)}
 *   onFileRemove={() => setFile(null)}
 * />
 */

import { useState, useRef, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { Upload, X, FileText, AlertCircle } from 'lucide-react';
import { cn } from '@/lib/utils';

export interface FileInputProps {
  /** 파일 선택 시 콜백 */
  onFileSelect: (file: File) => void;
  /** 파일 제거 시 콜백 */
  onFileRemove?: () => void;
  /** 허용 파일 타입 (예: ".pdf,.doc" 또는 "image/*") */
  accept?: string;
  /** 최대 파일 크기 (MB) */
  maxSize?: number;
  /** 비활성화 */
  disabled?: boolean;
  /** 버튼 텍스트 */
  buttonText?: string;
  /** 플레이스홀더 텍스트 */
  placeholder?: string;
  /** 현재 선택된 파일 (외부 제어용) */
  value?: File | null;
  /** 기존 파일 정보 (수정 모드용) */
  existingFile?: {
    name: string;
    url?: string;
  };
  /** 추가 클래스 */
  className?: string;
  /** 에러 상태 */
  error?: boolean;
  /** 에러 메시지 */
  errorMessage?: string;
}

export function FileInput({
  onFileSelect,
  onFileRemove,
  accept = '*/*',
  maxSize = 10,
  disabled = false,
  buttonText = '파일 선택',
  placeholder = '선택된 파일 없음',
  value,
  existingFile,
  className,
  error = false,
  errorMessage,
}: FileInputProps) {
  const [internalFile, setInternalFile] = useState<File | null>(null);
  const [validationError, setValidationError] = useState<string | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  // 외부 제어 또는 내부 상태 사용
  const selectedFile = value !== undefined ? value : internalFile;
  const displayError = errorMessage || validationError;

  const handleClick = useCallback(() => {
    if (!disabled) {
      inputRef.current?.click();
    }
  }, [disabled]);

  const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];

    if (!file) return;

    // 위험한 확장자 차단
    const dangerousExtensions = ['.exe', '.bat', '.cmd', '.sh', '.js', '.jsx', '.ts', '.tsx', '.mjs', '.jar', '.app', '.scr', '.vbs', '.ps1', '.htm', '.html', '.svg', '.swf'];
    const fileExtension = '.' + (file.name.split('.').pop()?.toLowerCase() || '');
    if (dangerousExtensions.includes(fileExtension)) {
      setValidationError('보안상 허용되지 않는 파일 형식입니다.');
      return;
    }

    // accept가 지정된 경우 확장자 검증
    if (accept !== '*/*') {
      const allowedExtensions = accept.split(',').map(ext => ext.trim().toLowerCase());
      const isAllowed = allowedExtensions.some(ext => {
        if (ext.startsWith('.')) return fileExtension === ext;
        if (ext.endsWith('/*')) return file.type.startsWith(ext.replace('/*', '/'));
        return file.type === ext;
      });
      if (!isAllowed) {
        setValidationError(`허용되지 않은 파일 형식입니다. (${accept})`);
        return;
      }
    }

    // 파일 크기 검증
    const fileSizeMB = file.size / (1024 * 1024);
    if (fileSizeMB > maxSize) {
      setValidationError(`파일 크기는 ${maxSize}MB 이하여야 합니다`);
      return;
    }

    setValidationError(null);
    setInternalFile(file);
    onFileSelect(file);

    // input 초기화 (같은 파일 재선택 가능하도록)
    if (inputRef.current) {
      inputRef.current.value = '';
    }
  }, [maxSize, onFileSelect]);

  const handleRemove = useCallback((e: React.MouseEvent) => {
    e.stopPropagation();
    setInternalFile(null);
    setValidationError(null);
    if (inputRef.current) {
      inputRef.current.value = '';
    }
    onFileRemove?.();
  }, [onFileRemove]);

  // 표시할 파일명 결정
  const displayFileName = selectedFile?.name || existingFile?.name;
  const hasFile = !!selectedFile || !!existingFile;

  return (
    <div className={cn('space-y-1', className)}>
      <div
        className={cn(
          'flex items-center gap-2 p-2 border rounded-md bg-background',
          error || displayError ? 'border-red-500' : 'border-input',
          disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:border-primary/50',
        )}
        onClick={handleClick}
      >
        {/* 숨겨진 파일 input */}
        <input
          ref={inputRef}
          type="file"
          accept={accept}
          onChange={handleChange}
          disabled={disabled}
          className="hidden"
        />

        {/* 파일 선택 버튼 */}
        <Button
          type="button"
          variant="outline"
          size="sm"
          disabled={disabled}
          onClick={(e) => {
            e.stopPropagation();
            handleClick();
          }}
          className="shrink-0"
        >
          <Upload className="w-4 h-4 mr-1" />
          {buttonText}
        </Button>

        {/* 파일명 표시 영역 */}
        <div className="flex-1 flex items-center gap-2 min-w-0">
          {hasFile ? (
            <>
              <FileText className="w-4 h-4 text-primary shrink-0" />
              <span className="text-sm truncate">
                {displayFileName}
              </span>
              {selectedFile && (
                <span className="text-xs text-muted-foreground shrink-0">
                  ({(selectedFile.size / 1024).toFixed(1)} KB)
                </span>
              )}
            </>
          ) : (
            <span className="text-sm text-muted-foreground">
              {placeholder}
            </span>
          )}
        </div>

        {/* 파일 제거 버튼 */}
        {hasFile && !disabled && (
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={handleRemove}
            className="shrink-0 h-7 w-7 p-0 hover:bg-destructive/10"
          >
            <X className="w-4 h-4 text-muted-foreground hover:text-destructive" />
          </Button>
        )}
      </div>

      {/* 에러 메시지 */}
      {displayError && (
        <div className="flex items-center gap-1 text-sm text-red-500">
          <AlertCircle className="w-3 h-3" />
          <span>{displayError}</span>
        </div>
      )}

      {/* 허용 파일 형식 안내 */}
      {!displayError && accept !== '*/*' && (
        <p className="text-xs text-muted-foreground">
          허용 형식: {accept}
        </p>
      )}
    </div>
  );
}

export default FileInput;
