/**
 * 파일 업로드 컴포넌트
 *
 * 시방서, 인정서, 전개도 등 파일 업로드 UI
 */

'use client';

import { useState, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { X, Upload, FileText, CheckCircle2 } from 'lucide-react';

interface FileUploadProps {
  label: string;
  accept?: string;
  maxSize?: number; // MB
  currentFile?: {
    url: string;
    filename: string;
  };
  onFileSelect: (file: File) => void;
  onFileRemove?: () => void;
  disabled?: boolean;
  required?: boolean;
}

export default function FileUpload({
  label,
  accept = '*/*',
  maxSize = 10, // 10MB default
  currentFile,
  onFileSelect,
  onFileRemove,
  disabled = false,
  required = false,
}: FileUploadProps) {
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [isDragging, setIsDragging] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const handleFileChange = (file: File | null) => {
    if (!file) {
      setSelectedFile(null);
      setError(null);
      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)) {
      setError('보안상 허용되지 않는 파일 형식입니다.');
      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) {
        setError(`허용되지 않은 파일 형식입니다. (${accept})`);
        return;
      }
    }

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

    setError(null);
    setSelectedFile(file);
    onFileSelect(file);
  };

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0] || null;
    handleFileChange(file);
  };

  const handleDragEnter = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(true);
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
  };

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
  };

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

    const file = e.dataTransfer.files?.[0] || null;
    handleFileChange(file);
  };

  const handleRemove = () => {
    setSelectedFile(null);
    setError(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
    onFileRemove?.();
  };

  const handleClick = () => {
    fileInputRef.current?.click();
  };

  return (
    <div className="space-y-2">
      <Label htmlFor={`file-upload-${label}`}>
        {label}
        {required && <span className="text-red-500 ml-1">*</span>}
      </Label>

      {/* 파일 입력 (숨김) */}
      <Input
        ref={fileInputRef}
        id={`file-upload-${label}`}
        type="file"
        accept={accept}
        onChange={handleInputChange}
        disabled={disabled}
        className="hidden"
      />

      {/* 드래그 앤 드롭 영역 */}
      <div
        onDragEnter={handleDragEnter}
        onDragLeave={handleDragLeave}
        onDragOver={handleDragOver}
        onDrop={handleDrop}
        onClick={handleClick}
        className={`
          border-2 border-dashed rounded-lg p-6
          flex flex-col items-center justify-center
          cursor-pointer transition-colors
          ${isDragging ? 'border-primary bg-primary/5' : 'border-gray-300 hover:border-primary/50'}
          ${disabled ? 'opacity-50 cursor-not-allowed' : ''}
        `}
      >
        {selectedFile || currentFile ? (
          <div className="w-full">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-3">
                <FileText className="w-10 h-10 text-primary" />
                <div>
                  <p className="font-medium text-sm">
                    {selectedFile?.name || currentFile?.filename}
                  </p>
                  <p className="text-xs text-gray-500">
                    {selectedFile
                      ? `${(selectedFile.size / 1024).toFixed(1)} KB`
                      : currentFile?.url && (
                          <a
                            href={currentFile.url}
                            target="_blank"
                            rel="noopener noreferrer"
                            className="text-primary hover:underline"
                            onClick={(e) => e.stopPropagation()}
                          >
                            파일 보기
                          </a>
                        )}
                  </p>
                </div>
                {selectedFile && (
                  <CheckCircle2 className="w-5 h-5 text-green-500 ml-2" />
                )}
              </div>

              {!disabled && (
                <Button
                  type="button"
                  variant="ghost"
                  size="sm"
                  onClick={(e) => {
                    e.stopPropagation();
                    handleRemove();
                  }}
                >
                  <X className="w-4 h-4" />
                </Button>
              )}
            </div>
          </div>
        ) : (
          <>
            <Upload className="w-12 h-12 text-gray-400 mb-3" />
            <p className="text-sm text-gray-600 mb-1">
              클릭하거나 파일을 드래그하여 업로드
            </p>
            <p className="text-xs text-gray-500">
              최대 {maxSize}MB
            </p>
          </>
        )}
      </div>

      {/* 에러 메시지 */}
      {error && (
        <p className="text-sm text-red-500">{error}</p>
      )}

      {/* 도움말 */}
      {!error && accept !== '*/*' && (
        <p className="text-xs text-gray-500">
          허용 파일 형식: {accept}
        </p>
      )}
    </div>
  );
}