import { useState, useRef, useCallback, type DragEvent, type ChangeEvent } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { SectionWrapper } from '../report/ui/SectionWrapper';
import { VideoFilled, FileTextFilled } from '../icons/FilledIcons';

// ─── Types ───

type UploadCategory = 'all' | 'image' | 'video' | 'text';

interface UploadedAsset {
  id: string;
  file: File;
  category: 'image' | 'video' | 'text';
  previewUrl: string | null;
  name: string;
  size: string;
  uploadedAt: Date;
}

// ─── Helpers ───

function categorize(file: File): 'image' | 'video' | 'text' {
  if (file.type.startsWith('image/')) return 'image';
  if (file.type.startsWith('video/')) return 'video';
  return 'text';
}

function formatSize(bytes: number): string {
  if (bytes >= 1_048_576) return `${(bytes / 1_048_576).toFixed(1)} MB`;
  if (bytes >= 1024) return `${Math.round(bytes / 1024)} KB`;
  return `${bytes} B`;
}

function uid() {
  return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
}

const categoryConfig: Record<UploadCategory, { label: string }> = {
  all: { label: '전체' },
  image: { label: 'Image' },
  video: { label: 'Video' },
  text: { label: 'Text' },
};

const categoryBadge: Record<'image' | 'video' | 'text', string> = {
  image: 'bg-[#F3F0FF] text-[#4A3A7C] shadow-[2px_3px_6px_rgba(155,138,212,0.12)]',
  video: 'bg-[#FFF0F0] text-[#7C3A4B] shadow-[2px_3px_6px_rgba(212,136,154,0.12)]',
  text: 'bg-[#FFF6ED] text-[#7C5C3A] shadow-[2px_3px_6px_rgba(212,168,114,0.12)]',
};

const ACCEPT_MAP: Record<string, string> = {
  'image/*': '.jpg,.jpeg,.png,.gif,.webp,.svg',
  'video/*': '.mp4,.mov,.webm,.avi',
  'text/*': '.txt,.md,.doc,.docx,.pdf,.csv,.json',
};
const ALL_ACCEPT = Object.values(ACCEPT_MAP).join(',');

// ─── Component ───

export default function MyAssetUpload() {
  const [assets, setAssets] = useState<UploadedAsset[]>([]);
  const [activeFilter, setActiveFilter] = useState<UploadCategory>('all');
  const [isDragOver, setIsDragOver] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  const processFiles = useCallback((files: FileList | File[]) => {
    const newAssets: UploadedAsset[] = Array.from(files).map((file) => {
      const cat = categorize(file);
      const previewUrl =
        cat === 'image' || cat === 'video'
          ? URL.createObjectURL(file)
          : null;
      return {
        id: uid(),
        file,
        category: cat,
        previewUrl,
        name: file.name,
        size: formatSize(file.size),
        uploadedAt: new Date(),
      };
    });
    setAssets((prev) => [...newAssets, ...prev]);
  }, []);

  const handleDrop = useCallback(
    (e: DragEvent) => {
      e.preventDefault();
      setIsDragOver(false);
      if (e.dataTransfer.files.length) processFiles(e.dataTransfer.files);
    },
    [processFiles],
  );

  const handleInputChange = useCallback(
    (e: ChangeEvent<HTMLInputElement>) => {
      if (e.target.files?.length) {
        processFiles(e.target.files);
        e.target.value = '';
      }
    },
    [processFiles],
  );

  const removeAsset = useCallback((id: string) => {
    setAssets((prev) => {
      const found = prev.find((a) => a.id === id);
      if (found?.previewUrl) URL.revokeObjectURL(found.previewUrl);
      return prev.filter((a) => a.id !== id);
    });
  }, []);

  const filtered =
    activeFilter === 'all' ? assets : assets.filter((a) => a.category === activeFilter);

  const counts = {
    all: assets.length,
    image: assets.filter((a) => a.category === 'image').length,
    video: assets.filter((a) => a.category === 'video').length,
    text: assets.filter((a) => a.category === 'text').length,
  };

  return (
    <SectionWrapper
      id="my-asset-upload"
      title="My Assets"
      subtitle="나의 에셋 업로드"
    >
      {/* Drop Zone */}
      <div
        onDragOver={(e) => { e.preventDefault(); setIsDragOver(true); }}
        onDragLeave={() => setIsDragOver(false)}
        onDrop={handleDrop}
        onClick={() => inputRef.current?.click()}
        className={`relative rounded-2xl border-2 border-dashed p-10 md:p-14 text-center cursor-pointer transition-all mb-8 ${
          isDragOver
            ? 'border-[#9B8AD4] bg-[#F3F0FF]/60 scale-[1.01]'
            : 'border-slate-200 bg-slate-50/50 hover:border-[#D5CDF5] hover:bg-[#F3F0FF]/20'
        }`}
      >
        <input
          ref={inputRef}
          type="file"
          multiple
          accept={ALL_ACCEPT}
          onChange={handleInputChange}
          className="hidden"
        />

        {/* Upload Icon */}
        <div className="flex justify-center mb-4">
          <div className="w-14 h-14 rounded-2xl bg-[#F3F0FF] flex items-center justify-center shadow-[3px_4px_12px_rgba(155,138,212,0.15)]">
            <svg width="28" height="28" viewBox="0 0 24 24" fill="none">
              <path
                d="M12 16V4M12 4L8 8M12 4L16 8"
                stroke="#9B8AD4"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              />
              <path
                d="M4 14V18C4 19.1 4.9 20 6 20H18C19.1 20 20 19.1 20 18V14"
                stroke="#9B8AD4"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              />
            </svg>
          </div>
        </div>

        <p className="text-[#0A1128] font-semibold mb-1">
          파일을 드래그하거나 클릭하여 업로드
        </p>
        <p className="text-sm text-slate-400">
          Image, Video, Text 파일 지원 (JPG, PNG, MP4, MOV, TXT, PDF, DOC 등)
        </p>

        {/* File Type Badges */}
        <div className="flex justify-center gap-2 mt-4">
          {(['image', 'video', 'text'] as const).map((cat) => (
            <span
              key={cat}
              className={`rounded-full px-3 py-1 text-xs font-medium ${categoryBadge[cat]}`}
            >
              {cat === 'image' ? 'Image' : cat === 'video' ? 'Video' : 'Text'}
            </span>
          ))}
        </div>
      </div>

      {/* Filter Tabs + Count */}
      {assets.length > 0 && (
        <>
          <div className="flex flex-wrap items-center gap-2 mb-6">
            {(Object.keys(categoryConfig) as UploadCategory[]).map((key) => (
              <button
                key={key}
                onClick={() => setActiveFilter(key)}
                className={`rounded-full px-4 py-2 text-sm font-medium transition-all ${
                  activeFilter === key
                    ? 'bg-gradient-to-r from-[#4F1DA1] to-[#021341] text-white shadow-md'
                    : 'bg-white border border-slate-200 text-slate-600 hover:bg-slate-50 shadow-[2px_3px_6px_rgba(0,0,0,0.04)]'
                }`}
              >
                {categoryConfig[key].label}
                <span className="ml-2 opacity-70">{counts[key]}</span>
              </button>
            ))}
          </div>

          {/* Uploaded Assets Grid */}
          <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
            <AnimatePresence mode="popLayout">
              {filtered.map((asset) => (
                <motion.div
                  key={asset.id}
                  layout
                  className="bg-white rounded-2xl border border-slate-100 overflow-hidden shadow-[3px_4px_12px_rgba(0,0,0,0.06)] hover:shadow-[4px_6px_16px_rgba(0,0,0,0.09)] transition-shadow group"
                  initial={{ opacity: 0, scale: 0.95 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.9 }}
                  transition={{ duration: 0.25 }}
                >
                  {/* Preview Area */}
                  <div className="relative h-40 bg-slate-50 flex items-center justify-center overflow-hidden">
                    {asset.category === 'image' && asset.previewUrl && (
                      <img
                        src={asset.previewUrl}
                        alt={asset.name}
                        className="w-full h-full object-cover"
                      />
                    )}
                    {asset.category === 'video' && asset.previewUrl && (
                      <video
                        src={asset.previewUrl}
                        className="w-full h-full object-cover"
                        muted
                        playsInline
                        onMouseOver={(e) => (e.target as HTMLVideoElement).play()}
                        onMouseOut={(e) => {
                          const v = e.target as HTMLVideoElement;
                          v.pause();
                          v.currentTime = 0;
                        }}
                      />
                    )}
                    {asset.category === 'text' && (
                      <div className="flex flex-col items-center gap-2">
                        <FileTextFilled size={36} className="text-[#D4A872]" />
                        <span className="text-xs text-slate-400 font-medium">
                          {asset.name.split('.').pop()?.toUpperCase()}
                        </span>
                      </div>
                    )}

                    {/* Remove Button */}
                    <button
                      onClick={() => removeAsset(asset.id)}
                      className="absolute top-2 right-2 w-7 h-7 rounded-full bg-white/90 backdrop-blur-sm border border-slate-100 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity shadow-sm hover:bg-[#FFF0F0]"
                    >
                      <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
                        <path d="M2 2L10 10M10 2L2 10" stroke="#7C3A4B" strokeWidth="1.5" strokeLinecap="round" />
                      </svg>
                    </button>

                    {/* Category Badge */}
                    <span
                      className={`absolute top-2 left-2 rounded-full px-3 py-1 text-xs font-semibold ${categoryBadge[asset.category]}`}
                    >
                      {asset.category === 'image'
                        ? 'Image'
                        : asset.category === 'video'
                          ? 'Video'
                          : 'Text'}
                    </span>

                    {/* Video Duration Overlay */}
                    {asset.category === 'video' && (
                      <div className="absolute bottom-2 right-2 flex items-center gap-1 bg-black/50 backdrop-blur-sm rounded-full px-2 py-1">
                        <VideoFilled size={10} className="text-white" />
                        <span className="text-xs text-white font-medium">Video</span>
                      </div>
                    )}
                  </div>

                  {/* Info */}
                  <div className="p-4">
                    <p className="text-sm font-medium text-[#0A1128] truncate mb-1">
                      {asset.name}
                    </p>
                    <p className="text-xs text-slate-400">{asset.size}</p>
                  </div>
                </motion.div>
              ))}
            </AnimatePresence>
          </div>
        </>
      )}
    </SectionWrapper>
  );
}
