'use client';

import * as React from 'react';
import { useProjectAlbum } from './project-album-context.jsx';

const HTML_EXTS = new Set(['html', 'htm']);
const MAX_BYTES = 25 * 1024 * 1024; // 25MB hard cap across both endpoints

function fileKind(file) {
  const name = String(file?.name || '').toLowerCase();
  const ext = (name.match(/\.([a-z0-9]+)$/) || [, ''])[1];
  const mime = String(file?.type || '').toLowerCase();
  if (HTML_EXTS.has(ext) || mime === 'text/html') return 'html';
  return 'disk';
}

export default function ProjectDropZone({ projectId, children }) {
  const { refreshLibrary } = useProjectAlbum();
  const [dragging, setDragging] = React.useState(false);
  const [, setBusy] = React.useState(false);
  const busyRef = React.useRef(false);
  const handleFilesRef = React.useRef(null);
  const [toast, setToast] = React.useState(null);
  const counterRef = React.useRef(0);

  React.useEffect(() => {
    function onDragEnter(e) {
      if (!e.dataTransfer || !Array.from(e.dataTransfer.types || []).includes('Files')) return;
      counterRef.current += 1;
      setDragging(true);
    }
    function onDragLeave() {
      counterRef.current = Math.max(0, counterRef.current - 1);
      if (counterRef.current === 0) setDragging(false);
    }
    function onDragOver(e) {
      if (!e.dataTransfer || !Array.from(e.dataTransfer.types || []).includes('Files')) return;
      e.preventDefault();
      e.dataTransfer.dropEffect = 'copy';
    }
    function onDrop(e) {
      if (!e.dataTransfer || !e.dataTransfer.files || !e.dataTransfer.files.length) return;
      e.preventDefault();
      counterRef.current = 0;
      setDragging(false);
      handleFilesRef.current?.(Array.from(e.dataTransfer.files));
    }

    window.addEventListener('dragenter', onDragEnter);
    window.addEventListener('dragleave', onDragLeave);
    window.addEventListener('dragover', onDragOver);
    window.addEventListener('drop', onDrop);
    return () => {
      window.removeEventListener('dragenter', onDragEnter);
      window.removeEventListener('dragleave', onDragLeave);
      window.removeEventListener('dragover', onDragOver);
      window.removeEventListener('drop', onDrop);
    };
  }, []);

  const uploadOne = React.useCallback(async (file) => {
    if (file.size > MAX_BYTES) {
      return { ok: false, name: file.name, error: `Too large (>${MAX_BYTES} bytes)` };
    }
    const kind = fileKind(file);
    const form = new FormData();
    form.set('project_id', projectId);
    if (kind === 'html') {
      form.set('file', file);
      const res = await fetch('/api/artifacts/upload', { method: 'POST', body: form });
      const json = await res.json().catch(() => ({}));
      return { ok: res.ok, name: file.name, error: json?.error };
    }
    // Disk file path — note disk endpoint expects `files` field (array-style)
    form.set('files', file);
    const res = await fetch('/api/disk/files', { method: 'POST', body: form });
    const json = await res.json().catch(() => ({}));
    return { ok: res.ok, name: file.name, error: json?.error };
  }, [projectId]);

  const handleFiles = React.useCallback(async (files) => {
    if (!files.length || busyRef.current) return;
    busyRef.current = true;
    setBusy(true);
    try {
      setToast({ kind: 'info', text: `Uploading ${files.length} file${files.length > 1 ? 's' : ''}…` });
      const results = await Promise.all(files.map(uploadOne));
      const okCount = results.filter((r) => r.ok).length;
      const failures = results.filter((r) => !r.ok);
      if (failures.length === 0) {
        setToast({ kind: 'ok', text: `Uploaded ${okCount} file${okCount > 1 ? 's' : ''}.` });
      } else if (okCount > 0) {
        setToast({ kind: 'warn', text: `Uploaded ${okCount}, ${failures.length} failed (${failures[0].error || 'error'}).` });
      } else {
        setToast({ kind: 'err', text: `Upload failed: ${failures[0].error || 'unknown error'}` });
      }
      if (okCount > 0) {
        await refreshLibrary();
      }
      setTimeout(() => setToast(null), 4500);
    } finally {
      busyRef.current = false;
      setBusy(false);
    }
  }, [refreshLibrary, uploadOne]);

  React.useEffect(() => {
    handleFilesRef.current = handleFiles;
  }, [handleFiles]);

  return (
    <>
      {children}
      {dragging ? (
        <div role="status" aria-live="polite" style={overlayStyle}>
          <div style={overlayCardStyle}>
            <div style={overlayTitleStyle}>Drop to upload</div>
            <div style={overlayHintStyle}>HTML files become artifacts · others land in Disk</div>
          </div>
        </div>
      ) : null}
      {toast ? (
        <div role="status" aria-live="polite" style={{ ...toastStyle, ...toastTone[toast.kind] }}>
          {toast.text}
        </div>
      ) : null}
    </>
  );
}

const overlayStyle = {
  position: 'fixed',
  inset: 0,
  zIndex: 9000,
  background: 'rgba(10, 8, 6, 0.45)',
  backdropFilter: 'blur(6px)',
  WebkitBackdropFilter: 'blur(6px)',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  pointerEvents: 'none',
  transition: 'opacity 120ms ease',
};

const overlayCardStyle = {
  border: '2px dashed rgba(255,255,255,0.6)',
  borderRadius: 16,
  padding: '32px 48px',
  background: 'rgba(20,16,12,0.7)',
  color: '#f5efe7',
  textAlign: 'center',
  fontFamily: 'inherit',
};

const overlayTitleStyle = {
  fontSize: 22,
  fontWeight: 600,
  letterSpacing: '0.01em',
  marginBottom: 6,
};

const overlayHintStyle = {
  fontSize: 13,
  opacity: 0.75,
};

const toastStyle = {
  position: 'fixed',
  bottom: 24,
  right: 24,
  zIndex: 9100,
  padding: '10px 14px',
  borderRadius: 10,
  fontSize: 13,
  fontFamily: 'inherit',
  boxShadow: '0 8px 24px rgba(0,0,0,0.25)',
  maxWidth: 380,
};

const toastTone = {
  info: { background: '#1f1b16', color: '#f5efe7', border: '1px solid rgba(245,239,231,0.18)' },
  ok: { background: '#1c2a1d', color: '#e6f3df', border: '1px solid rgba(120,180,90,0.35)' },
  warn: { background: '#2c2519', color: '#f4e6c5', border: '1px solid rgba(220,170,60,0.35)' },
  err: { background: '#2c1816', color: '#f4d8d2', border: '1px solid rgba(194,69,42,0.55)' },
};
