/**
 * DocumentUploadPanel — Upload PDF do projektu + RAG re-ingest
 *
 * Flow:
 *  1. Drag & drop / wybór pliku
 *  2. POST /api/projects/{id}/documents → 202 Accepted
 *  3. Polling GET co 3s gdy status=processing
 *  4. Lista wgranych dokumentów z ikonami statusu
 */

import React, { useState, useEffect, useRef, useCallback } from 'react';
import { Upload, FileText, CheckCircle, XCircle, Loader2, RefreshCw, Trash2, AlertTriangle, Database, FileSearch } from 'lucide-react';
import toast from 'react-hot-toast';

interface ProjectDocument {
  doc_id: string;
  filename: string;
  file_size_bytes: number;
  status: 'uploaded' | 'processing' | 'indexed' | 'error';
  parser_used: string | null;
  chunks_count: number | null;
  error_message: string | null;
  uploaded_at: string;
  indexed_at: string | null;
}

interface QuotaInfo {
  current: number;
  limit: number;
  plan: string;
  can_upload: boolean;
}

interface Props {
  projectId: string;
  token?: string;
}

const API = import.meta.env.VITE_API_URL || '';

// Kolor + ikona dla statusu indeksacji
function StatusBadge({ status }: { status: ProjectDocument['status'] }) {
  const map = {
    uploaded:   { label: 'Oczekuje',       color: '#f59e0b', bg: 'rgba(245,158,11,0.1)', Icon: Loader2 },
    processing: { label: 'Indeksowanie…',  color: '#3b82f6', bg: 'rgba(59,130,246,0.1)',  Icon: Loader2 },
    indexed:    { label: 'Gotowy',    color: '#10b981', bg: 'rgba(16,185,129,0.1)', Icon: CheckCircle },
    error:      { label: 'Błąd parsera',   color: '#ef4444', bg: 'rgba(239,68,68,0.1)',  Icon: XCircle },
  };
  const { label, color, bg, Icon } = map[status] ?? map.uploaded;
  const spinning = status === 'processing' || status === 'uploaded';

  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      padding: '2px 8px', borderRadius: 6, fontSize: '0.72rem',
      fontWeight: 700, background: bg, color,
    }}>
      <Icon size={11} style={spinning ? { animation: 'spin 1s linear infinite' } : {}} />
      {label}
    </span>
  );
}

function fmtBytes(b: number) {
  if (b < 1024) return `${b} B`;
  if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;
  return `${(b / (1024 * 1024)).toFixed(1)} MB`;
}

export default function DocumentUploadPanel({ projectId, token }: Props) {
  const [docs, setDocs] = useState<ProjectDocument[]>([]);
  const [quota, setQuota] = useState<QuotaInfo | null>(null);
  const [dragging, setDragging] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [loadingList, setLoadingList] = useState(true);
  const [docType, setDocType] = useState<'knowledge_base' | 'external_grant'>('knowledge_base');
  const fileInputRef = useRef<HTMLInputElement>(null);
  const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const tokenParam = token ? `?token=${token}` : '';

  /* ── Fetch listy dokumentów ────────────────────────────────────────────── */
  const fetchDocs = useCallback(async () => {
    try {
      const res = await fetch(`${API}/api/projects/${projectId}/documents${tokenParam}`);
      if (!res.ok) return;
      const data = await res.json();
      setDocs(data.documents || []);
      if (data.quota) setQuota(data.quota);
    } catch {
      // sieć
    } finally {
      setLoadingList(false);
    }
  }, [projectId, tokenParam]);

  /* ── Polling co 3s gdy jest document w trakcie przetwarzania ──────────── */
  useEffect(() => {
    fetchDocs();
  }, [fetchDocs]);

  useEffect(() => {
    const hasPending = docs.some(d => d.status === 'processing' || d.status === 'uploaded');
    if (hasPending && !pollingRef.current) {
      pollingRef.current = setInterval(fetchDocs, 3000);
    } else if (!hasPending && pollingRef.current) {
      clearInterval(pollingRef.current);
      pollingRef.current = null;
    }
    return () => {
      if (pollingRef.current) clearInterval(pollingRef.current);
    };
  }, [docs, fetchDocs]);

  /* ── Upload ────────────────────────────────────────────────────────────── */
  const uploadFile = async (file: File) => {
    if (!file.name.toLowerCase().endsWith('.pdf')) {
      toast.error('Obsługiwane są wyłącznie pliki PDF.');
      return;
    }
    if (file.size > 20 * 1024 * 1024) {
      toast.error('Plik przekracza limit 20 MB.');
      return;
    }
    // Sprawdź kwotę po stronie klienta przed wysłaniem
    if (quota && !quota.can_upload) {
      toast.error(
        quota.plan === 'free'
          ? `Osiągnięto limit ${quota.limit} plików na planie Free. Przejdź na plan Pro.`
          : `Osiągnięto limit ${quota.limit} plików dla tego projektu.`,
        { duration: 5000 }
      );
      return;
    }

    setUploading(true);
    const form = new FormData();
    form.append('file', file);

    const urlParams = new URLSearchParams();
    if (token) urlParams.append('token', token);
    urlParams.append('doc_type', docType);

    try {
      const res = await fetch(
        `${API}/api/projects/${projectId}/documents?${urlParams.toString()}`,
        { method: 'POST', body: form }
      );
      const data = await res.json();
      if (res.status === 429) {
        // Limit planu
        const msg = typeof data.detail === 'object'
          ? data.detail.message
          : data.detail;
        toast.error(msg || 'Przekroczono limit plików dla tego planu.', { duration: 6000 });
        // Odśwież kwotę
        await fetchDocs();
      } else if (!res.ok) {
        toast.error(data.detail || 'Błąd uploadu.');
      } else {
        toast.success(`📄 "${file.name}" wgrany. Przetwarzanie w toku…`);
        await fetchDocs();
      }
    } catch {
      toast.error('Błąd połączenia z serwerem.');
    } finally {
      setUploading(false);
    }
  };

  const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) uploadFile(file);
    e.target.value = '';
  };

  const onDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setDragging(false);
    const file = e.dataTransfer.files?.[0];
    if (file) uploadFile(file);
  };

  /* ── Re-ingest ─────────────────────────────────────────────────────────── */
  const reingest = async (docId: string) => {
    try {
      const res = await fetch(
        `${API}/api/projects/${projectId}/documents/${docId}/reingest${tokenParam}`,
        { method: 'POST' }
      );
      if (res.ok) {
        toast.success('Ponowna indeksacja uruchomiona.');
        fetchDocs();
      }
    } catch {
      toast.error('Błąd ponownej indeksacji.');
    }
  };

  /* ── Delete ────────────────────────────────────────────────────────────── */
  const deleteDoc = async (docId: string, filename: string) => {
    if (!window.confirm(`Usunąć "${filename}" z projektu?`)) return;
    try {
      const res = await fetch(
        `${API}/api/projects/${projectId}/documents/${docId}${tokenParam}`,
        { method: 'DELETE' }
      );
      if (res.ok) {
        toast.success('Dokument usunięty.');
        setDocs(d => d.filter(x => x.doc_id !== docId));
      }
    } catch {
      toast.error('Błąd usuwania.');
    }
  };

  /* ── Render ────────────────────────────────────────────────────────────── */
  return (
    <div style={{ maxWidth: 820, margin: '2rem auto', padding: '0 1rem', display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>

      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
        <div style={{ width: 44, height: 44, borderRadius: 12, background: 'rgba(139,92,246,0.12)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Database size={20} color="#a78bfa" />
        </div>
        <div>
          <h2 style={{ margin: 0, fontSize: '1.25rem', fontWeight: 800, color: 'var(--text-primary)' }}>
            Dokumenty i Audyt Zewnętrzny
          </h2>
          <p style={{ margin: '0.2rem 0 0', color: 'var(--text-muted)', fontSize: '0.83rem' }}>
            Wgraj regulaminy do bazy RAG, lub gotowy wniosek z biura doradczego do weryfikacji.
          </p>
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
          {/* Licznik kwoty */}
          {quota && (
            <div style={{
              padding: '0.3rem 0.75rem',
              borderRadius: 8,
              background: quota.can_upload ? 'rgba(16,185,129,0.08)' : 'rgba(239,68,68,0.1)',
              border: `1px solid ${quota.can_upload ? 'rgba(16,185,129,0.2)' : 'rgba(239,68,68,0.2)'}`,
              fontSize: '0.75rem',
              fontWeight: 700,
              color: quota.can_upload ? '#34d399' : '#f87171',
              whiteSpace: 'nowrap',
            }}>
              {quota.current}/{quota.limit} PDF · {quota.plan.toUpperCase()}
            </div>
          )}
          <button
            onClick={fetchDocs}
            style={{ background: 'transparent', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 8, padding: '0.4rem 0.75rem', color: 'var(--text-muted)', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 6, fontSize: '0.8rem' }}
          >
            <RefreshCw size={13} /> Odśwież
          </button>
        </div>
      </div>

      {/* Drop Zone */}
      {quota && !quota.can_upload ? (
        <div style={{
          border: '2px dashed rgba(239,68,68,0.25)',
          borderRadius: 16,
          padding: '2.5rem 2rem',
          textAlign: 'center',
          background: 'rgba(239,68,68,0.03)',
        }}>
          <XCircle size={36} color="#f87171" style={{ marginBottom: 12, opacity: 0.6 }} />
          <p style={{ margin: 0, fontWeight: 700, color: '#f87171', fontSize: '0.95rem' }}>
            Limit pliku osiągnięty ({quota.current}/{quota.limit} · {quota.plan.toUpperCase()})
          </p>
          <p style={{ margin: '0.5rem 0 0', color: 'var(--text-muted)', fontSize: '0.8rem' }}>
            Usuń stary dokument lub{' '}
            <a href="/cennik" style={{ color: '#a78bfa', textDecoration: 'underline' }}>przejdź na plan Pro</a>
            {' '}aby dodać więcej plików.
          </p>
        </div>
      ) : (
      <div
        onDragOver={e => { e.preventDefault(); setDragging(true); }}
        onDragLeave={() => setDragging(false)}
        onDrop={onDrop}
        onClick={() => !uploading && fileInputRef.current?.click()}
        style={{
          border: `2px dashed ${dragging ? '#a78bfa' : 'rgba(255,255,255,0.1)'}`,
          borderRadius: 16,
          padding: '2.5rem 2rem',
          textAlign: 'center',
          cursor: uploading ? 'not-allowed' : 'pointer',
          background: dragging ? 'rgba(139,92,246,0.04)' : 'rgba(255,255,255,0.01)',
          transition: 'all 0.2s',
          position: 'relative',
        }}
      >
        {uploading ? (
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
            <Loader2 size={36} color="#a78bfa" style={{ animation: 'spin 1s linear infinite' }} />
            <span style={{ color: 'var(--text-muted)', fontSize: '0.9rem' }}>Wysyłanie pliku…</span>
          </div>
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10 }}>
            <div style={{ width: 52, height: 52, borderRadius: 12, background: 'rgba(139,92,246,0.1)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Upload size={24} color="#a78bfa" />
            </div>
            <div>
              <p style={{ margin: 0, fontWeight: 700, color: 'var(--text-primary)', fontSize: '0.95rem' }}>
                Przeciągnij plik PDF lub kliknij aby wybrać
              </p>
              <p style={{ margin: '0.3rem 0 0', color: 'var(--text-muted)', fontSize: '0.78rem' }}>
                Maksymalnie 20 MB · PDF
              </p>
            </div>
          </div>
        )}
        <input
          ref={fileInputRef}
          type="file"
          accept=".pdf,application/pdf"
          style={{ display: 'none' }}
          onChange={onFileChange}
        />
      </div>
      )}

      {/* Typ dokumentu */}
      <div style={{ display: 'flex', gap: '1rem', marginBottom: '0.5rem' }}>
        <button
          onClick={() => setDocType('knowledge_base')}
          style={{
            flex: 1, padding: '1rem', borderRadius: 12, border: `2px solid ${docType === 'knowledge_base' ? 'var(--accent-blue)' : 'rgba(255,255,255,0.05)'}`,
            background: docType === 'knowledge_base' ? 'rgba(59,130,246,0.05)' : 'rgba(255,255,255,0.02)', cursor: 'pointer', textAlign: 'left', transition: '0.2s'
          }}
        >
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
            <Database size={16} color={docType === 'knowledge_base' ? 'var(--accent-blue)' : 'var(--text-secondary)'} />
            <strong style={{ color: docType === 'knowledge_base' ? 'var(--accent-blue)' : 'var(--text-primary)' }}>Baza Wiedzy (RAG)</strong>
          </div>
          <div style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>Regulaminy, FAQs, Instrukcje wypełniania.</div>
        </button>
        <button
          onClick={() => setDocType('external_grant')}
          style={{
            flex: 1, padding: '1rem', borderRadius: 12, border: `2px solid ${docType === 'external_grant' ? '#a78bfa' : 'rgba(255,255,255,0.05)'}`,
            background: docType === 'external_grant' ? 'rgba(139,92,246,0.05)' : 'rgba(255,255,255,0.02)', cursor: 'pointer', textAlign: 'left', transition: '0.2s'
          }}
        >
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
            <FileSearch size={16} color={docType === 'external_grant' ? '#a78bfa' : 'var(--text-secondary)'} />
            <strong style={{ color: docType === 'external_grant' ? '#a78bfa' : 'var(--text-primary)' }}>Gotowy wniosek (Reverse-Audit)</strong>
          </div>
          <div style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>Wniosek wypełniony poza platformą (do audytu).</div>
        </button>
      </div>

      {docType === 'knowledge_base' ? (
      <div style={{ background: 'rgba(59,130,246,0.06)', border: '1px solid rgba(59,130,246,0.15)', borderRadius: 10, padding: '0.75rem 1rem', fontSize: '0.8rem', color: '#93c5fd', display: 'flex', gap: 8, alignItems: 'flex-start' }}>
        <AlertTriangle size={14} style={{ flexShrink: 0, marginTop: 2 }} />
        <span>
          Po wgraniu plik jest automatycznie parsowany (LlamaParse → PyPDF) i dzielony na chunki §/Art./Rozdział.
          Generator AI będzie używał tych danych jako kontekst prawny dla Twojego programu dotacyjnego.
        </span>
      </div>
      ) : (
      <div style={{ background: 'rgba(139,92,246,0.06)', border: '1px solid rgba(139,92,246,0.15)', borderRadius: 10, padding: '0.75rem 1rem', fontSize: '0.8rem', color: '#c4b5fd', display: 'flex', gap: 8, alignItems: 'flex-start' }}>
        <FileSearch size={14} style={{ flexShrink: 0, marginTop: 2 }} />
        <span>
          Wgrywasz gotowy dokument do skontrolowania (Reverse-Audit). AI odczyta całą treść bez dzielenia na chunki i przygotuje wniosek do finalnej kontroli w module Audytu Wniosku.
        </span>
      </div>
      )}

      {/* Lista dokumentów */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
        {loadingList && (
          <div style={{ textAlign: 'center', padding: '2rem', color: 'var(--text-muted)' }}>
            <Loader2 size={24} style={{ animation: 'spin 1s linear infinite' }} />
          </div>
        )}

        {!loadingList && docs.length === 0 && (
          <div style={{ textAlign: 'center', padding: '2rem', color: 'var(--text-muted)', fontSize: '0.88rem' }}>
            <FileText size={36} style={{ opacity: 0.2, marginBottom: 8 }} />
            <br />Brak wgranych dokumentów. Wgraj regulamin dotacyjny aby poprawić kontekst AI.
          </div>
        )}

        {docs.map((doc: any) => (
          <div key={doc.doc_id} style={{
            background: 'rgba(255,255,255,0.025)',
            border: `1px solid ${doc.status === 'error' ? 'rgba(239,68,68,0.2)' : 'rgba(255,255,255,0.06)'}`,
            borderRadius: 12,
            padding: '1rem 1.25rem',
            display: 'flex',
            alignItems: 'center',
            gap: '1rem',
          }}>
            {/* Ikona */}
            <div style={{ width: 38, height: 38, borderRadius: 8, background: 'rgba(255,255,255,0.04)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
              <FileText size={18} color={doc.status === 'indexed' ? '#10b981' : '#94a3b8'} />
            </div>

            {/* Info */}
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 600, color: 'var(--text-primary)', fontSize: '0.88rem', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                {doc.filename}
              </div>
              <div style={{ display: 'flex', gap: '0.6rem', flexWrap: 'wrap', marginTop: 4, alignItems: 'center' }}>
                <StatusBadge status={doc.status} />
                {doc.file_size_bytes && (
                  <span style={{ fontSize: '0.72rem', color: 'var(--text-muted)' }}>{fmtBytes(doc.file_size_bytes)}</span>
                )}
                <span style={{ fontSize: '0.72rem', color: (doc as any).doc_type === 'external_grant' ? '#a78bfa' : '#3b82f6', fontWeight: 600, padding: '2px 6px', borderRadius: '4px', background: 'rgba(255,255,255,0.05)' }}>
                  {(doc as any).doc_type === 'external_grant' ? 'Reverse-Audit' : 'Baza RAG'}
                </span>
                {doc.chunks_count && doc.status === 'indexed' && (
                  <span style={{ fontSize: '0.72rem', color: '#6366f1' }}>
                    {doc.chunks_count} chunk{doc.chunks_count !== 1 ? 'ów' : ''}
                  </span>
                )}
                {doc.parser_used && doc.status === 'indexed' && (
                  <span style={{ fontSize: '0.72rem', color: 'var(--text-muted)' }}>via {doc.parser_used}</span>
                )}
                {doc.uploaded_at && (
                  <span style={{ fontSize: '0.72rem', color: 'var(--text-muted)' }}>
                    {new Date(doc.uploaded_at).toLocaleDateString('pl-PL')}
                  </span>
                )}
              </div>
              {doc.error_message && (
                <div style={{ fontSize: '0.75rem', color: '#fca5a5', marginTop: 4 }}>
                  {doc.error_message.slice(0, 120)}
                </div>
              )}
            </div>

            {/* Akcje */}
            <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
              {(doc.status === 'error' || doc.status === 'indexed') && (
                <button
                  onClick={() => reingest(doc.doc_id)}
                  title="Ponowna indeksacja"
                  style={{ background: 'rgba(99,102,241,0.1)', border: '1px solid rgba(99,102,241,0.2)', borderRadius: 7, padding: '0.4rem 0.6rem', cursor: 'pointer', color: '#818cf8' }}
                >
                  <RefreshCw size={13} />
                </button>
              )}
              <button
                onClick={() => deleteDoc(doc.doc_id, doc.filename)}
                title="Usuń dokument"
                style={{ background: 'rgba(239,68,68,0.08)', border: '1px solid rgba(239,68,68,0.15)', borderRadius: 7, padding: '0.4rem 0.6rem', cursor: 'pointer', color: '#f87171' }}
              >
                <Trash2 size={13} />
              </button>
            </div>
          </div>
        ))}
      </div>

      <style>{`
        @keyframes spin { to { transform: rotate(360deg); } }
      `}</style>
    </div>
  );
}
