import { useState, useEffect, useCallback } from 'react';
import { Topbar } from '../../components/layout/Topbar';
import { Upload, Search, Download, Trash2, RefreshCw, AlertTriangle } from 'lucide-react';
import { UploadModal } from './UploadModal';
import { useLanguage } from '../../contexts/LanguageContext';

const TOKEN_KEY = 'auth_token';
function authHeader(): Record<string, string> {
  const t = localStorage.getItem(TOKEN_KEY);
  return t ? { Authorization: `Bearer ${t}` } : {};
}

interface Doc {
  id: string;
  name: string;
  status: 'ok' | 'warn' | 'risk' | 'info';
  uploadedAt: string;
  chunks: number;
  type: string;
  sizeBytes: number;
  summary?: string;
  version?: string;
  hasFile: boolean;
}

const STATUS_FILTERS = ['All', 'Ready', 'Processing', 'Failed', 'Pending'];
const STATUS_LABEL: Record<string, string> = { ok: 'Ready', warn: 'Processing', risk: 'Failed', info: 'Pending' };
const STATUS_MAP: Record<string, string> = { All: 'All', Ready: 'ok', Processing: 'warn', Failed: 'risk', Pending: 'info' };

function backendStatus(s: string): Doc['status'] {
  if (s === 'indexed') return 'ok';
  if (s === 'failed') return 'risk';
  if (s === 'parsed') return 'warn';
  return 'info';
}

function formatSize(bytes: number): string {
  if (!bytes) return '—';
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
}

// ── Confirm dialog ─────────────────────────────────────────────────────────
function ConfirmDialog({ message, onConfirm, onCancel }: {
  message: string;
  onConfirm: () => void;
  onCancel: () => void;
}) {
  const { t } = useLanguage();
  return (
    <div className="modal-overlay" onClick={onCancel}>
      <div
        style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 14, padding: '28px 32px', maxWidth: 400, width: '100%', boxShadow: '0 12px 40px rgba(0,0,0,.2)' }}
        onClick={e => e.stopPropagation()}
      >
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
          <AlertTriangle size={18} color="var(--danger)" />
          <span style={{ fontWeight: 600, fontSize: 15 }}>{t.docs.confirmDeleteTitle}</span>
        </div>
        <p style={{ fontSize: 13, color: 'var(--muted)', lineHeight: 1.6, marginBottom: 20 }}>{message}</p>
        <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
          <button className="btn sm" onClick={onCancel}>{t.docs.cancelBtn}</button>
          <button className="btn sm" style={{ background: 'var(--danger)', color: '#fff', borderColor: 'var(--danger)' }} onClick={onConfirm}>
            {t.docs.deleteBtn}
          </button>
        </div>
      </div>
    </div>
  );
}

export function DocsPage() {
  const { t } = useLanguage();
  const [search, setSearch] = useState('');
  const [statusF, setStatusF] = useState('All');
  const [typeF, setTypeF] = useState('All types');
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [docs, setDocs] = useState<Doc[]>([]);
  const [loading, setLoading] = useState(true);
  const [showUpload, setShowUpload] = useState(false);
  const [refreshKey, setRefreshKey] = useState(0);
  const [retrying, setRetrying] = useState<Set<string>>(new Set());
  const [deleting, setDeleting] = useState<Set<string>>(new Set());
  const [confirmDelete, setConfirmDelete] = useState<{ ids: string[]; names: string[] } | null>(null);

  // Dynamic type options derived from actual docs
  const typeOpts = ['All types', ...Array.from(new Set(docs.map(d => d.type).filter(t => t && t !== '—')))];

  const fetchDocs = useCallback(() => {
    setLoading(true);
    fetch('/api/v1/documents/management-list', { headers: authHeader() })
      .then(r => r.json())
      .then(d => {
        if (!Array.isArray(d?.documents)) { setLoading(false); return; }
        setDocs(d.documents.map((item: Record<string, unknown>) => ({
          id: item.doc_id as string,
          name: item.doc_name as string,
          status: backendStatus(item.status as string),
          uploadedAt: ((item.updated_at as string) ?? '').slice(0, 10),
          chunks: (item.chunk_count as number) ?? 0,
          type: (item.regulation_type as string) || '—',
          sizeBytes: (item.size_bytes as number) ?? 0,
          summary: item.summary as string | undefined,
          version: item.version as string | undefined,
          hasFile: item.has_file !== false,
        })));
        setLoading(false);
      })
      .catch(() => setLoading(false));
  }, []);

  useEffect(() => { fetchDocs(); }, [fetchDocs, refreshKey]);

  // ── Filtering ────────────────────────────────────────────────────────────
  const filtered = docs.filter(d => {
    const matchSearch = !search || d.name.toLowerCase().includes(search.toLowerCase());
    const matchStatus = statusF === 'All' || d.status === STATUS_MAP[statusF];
    const matchType = typeF === 'All types' || d.type === typeF;
    return matchSearch && matchStatus && matchType;
  });

  // ── Selection helpers ────────────────────────────────────────────────────
  function toggleAll() {
    if (selected.size === filtered.length) setSelected(new Set());
    else setSelected(new Set(filtered.map(d => d.id)));
  }
  function toggleOne(id: string) {
    const s = new Set(selected);
    s.has(id) ? s.delete(id) : s.add(id);
    setSelected(s);
  }

  // ── Download ─────────────────────────────────────────────────────────────
  async function downloadDoc(id: string, name: string) {
    try {
      const resp = await fetch(`/api/v1/documents/download/${id}`, { headers: authHeader() });
      if (!resp.ok) throw new Error(`下载失败: ${resp.status}`);
      const blob = await resp.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = name;
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      console.error('Download failed', err);
      alert(String(err));
    }
  }

  // ── Retry (re-process failed doc) ────────────────────────────────────────
  async function retryDoc(id: string) {
    setRetrying(r => new Set([...r, id]));
    try {
      await fetch(`/api/v1/documents/${id}/retry`, { method: 'POST', headers: authHeader() });
      setTimeout(() => {
        setRetrying(r => { const s = new Set(r); s.delete(id); return s; });
        setRefreshKey(k => k + 1);
      }, 1500);
    } catch {
      setRetrying(r => { const s = new Set(r); s.delete(id); return s; });
    }
  }

  // ── Delete (single or batch) ─────────────────────────────────────────────
  function askDelete(ids: string[]) {
    const names = ids.map(id => docs.find(d => d.id === id)?.name ?? id);
    setConfirmDelete({ ids, names });
  }

  async function confirmDeleteDocs() {
    if (!confirmDelete) return;
    const { ids } = confirmDelete;
    setConfirmDelete(null);
    setDeleting(new Set(ids));

    await Promise.allSettled(
      ids.map(id => fetch(`/api/v1/documents/${id}`, { method: 'DELETE', headers: authHeader() }))
    );

    setDeleting(new Set());
    setSelected(s => { const n = new Set(s); ids.forEach(id => n.delete(id)); return n; });
    setRefreshKey(k => k + 1);
  }

  return (
    <div className="docs-page">
      <Topbar
        title={t.docs.topbarTitle}
        actions={
          <>
            <div className="search-box">
              <Search size={13} />
              <input
                placeholder={t.docs.searchPlaceholder}
                value={search}
                onChange={e => setSearch(e.target.value)}
              />
            </div>
            <button className="btn sm" onClick={() => setRefreshKey(k => k + 1)}>
              <RefreshCw size={13} />{t.docs.refreshBtn}
            </button>
            <button className="btn sm primary" onClick={() => setShowUpload(true)}>
              <Upload size={13} />{t.docs.uploadBtn}
            </button>
          </>
        }
      />

      <div className="page-content">
        <div className="docs-controls">
          <div className="chip-group">
            {STATUS_FILTERS.map(f => (
              <button
                key={f}
                className={`chip${statusF === f ? ' active' : ''}`}
                onClick={() => setStatusF(f)}
              >
                {f === 'All' ? t.docs.filterAll
                  : f === 'Ready' ? t.docs.filterReady
                  : f === 'Processing' ? t.docs.filterProcessing
                  : f === 'Failed' ? t.docs.filterFailed
                  : t.docs.filterPending}
              </button>
            ))}
          </div>
          <select className="select-input" value={typeF} onChange={e => setTypeF(e.target.value)}>
            {typeOpts.map(o => (
              <option key={o} value={o}>{o === 'All types' ? t.docs.filterAllTypes : o}</option>
            ))}
          </select>
        </div>

        {/* Batch action bar */}
        {selected.size > 0 && (
          <div className="batch-bar">
            <span>
              {selected.size}{' '}
              {t.docs.colName === 'Document name'
                ? `document${selected.size > 1 ? 's' : ''} selected`
                : '份文档已选择'}
            </span>
            <button
              className="btn sm"
              style={{ color: 'var(--danger)', borderColor: 'rgba(239,68,68,.4)' }}
              onClick={() => askDelete([...selected])}
            >
              <Trash2 size={12} />{t.docs.deleteSelected}
            </button>
          </div>
        )}

        {/* Table */}
        <div className="docs-table">
          <div className="table-header">
            <input
              type="checkbox"
              checked={selected.size === filtered.length && filtered.length > 0}
              onChange={toggleAll}
            />
            <span>{t.docs.colName}</span>
            <span>{t.docs.colStatus}</span>
            <span>{t.docs.colUploaded}</span>
            <span>{t.docs.colChunks}</span>
            <span>{t.docs.colSize}</span>
            <span>{t.docs.colType}</span>
            <span>{t.docs.colActions}</span>
          </div>

          {loading ? (
            <div style={{ padding: '32px 16px', color: 'var(--muted)', fontSize: 13, textAlign: 'center' }}>
              {t.docs.loading}
            </div>
          ) : filtered.length === 0 ? (
            <div style={{ padding: '40px 16px', color: 'var(--muted)', fontSize: 13, textAlign: 'center' }}>
              {docs.length === 0 ? t.docs.emptyNoDocuments : t.docs.emptyNoMatch}
            </div>
          ) : (
            filtered.map(d => {
              const isDeleting = deleting.has(d.id);
              const isRetrying = retrying.has(d.id);
              return (
                <div
                  key={d.id}
                  className={`table-row${selected.has(d.id) ? ' row-selected' : ''}${isDeleting ? ' row-deleting' : ''}`}
                >
                  <input
                    type="checkbox"
                    checked={selected.has(d.id)}
                    onChange={() => toggleOne(d.id)}
                    disabled={isDeleting}
                  />
                  <span className="doc-name-cell" title={d.summary || d.name}>
                    {d.name}
                    {d.version && <span style={{ fontSize: 10, color: 'var(--muted)', marginLeft: 6 }}>v{d.version}</span>}
                  </span>
                  <span><span className={`status ${d.status}`}>{STATUS_LABEL[d.status]}</span></span>
                  <span className="cell-mono">{d.uploadedAt}</span>
                  <span className="cell-mono">{d.chunks || '—'}</span>
                  <span className="cell-mono">{formatSize(d.sizeBytes)}</span>
                  <span className="cell-muted">{d.type}</span>
                  <span className="row-actions">
                    {/* Download — disabled for Milvus-only docs that have no binary file */}
                    <button
                      className="text-link"
                      title={d.hasFile ? t.docs.titleDownload : '无原始文件'}
                      onClick={() => downloadDoc(d.id, d.name)}
                      disabled={!d.hasFile}
                      style={!d.hasFile ? { opacity: 0.3, cursor: 'not-allowed' } : undefined}
                    >
                      <Download size={12} />
                    </button>

                    {/* Retry for failed */}
                    {d.status === 'risk' && (
                      <button
                        className="text-link"
                        title={t.docs.titleRetry}
                        disabled={isRetrying}
                        onClick={() => retryDoc(d.id)}
                        style={{ color: 'var(--warn)' }}
                      >
                        <RefreshCw size={12} style={{ animation: isRetrying ? 'spin 1s linear infinite' : 'none' }} />
                      </button>
                    )}

                    {/* Delete */}
                    <button
                      className="text-link danger-link"
                      title={t.docs.titleDelete}
                      disabled={isDeleting}
                      onClick={() => askDelete([d.id])}
                    >
                      <Trash2 size={12} />
                    </button>
                  </span>
                </div>
              );
            })
          )}
        </div>

        {/* Footer count */}
        {!loading && (
          <div style={{ padding: '10px 0', fontSize: 12, color: 'var(--muted)' }}>
            {filtered.length} of {docs.length} document{docs.length !== 1 ? 's' : ''}
            {selected.size > 0 && ` · ${selected.size} selected`}
          </div>
        )}
      </div>

      {/* Confirm delete dialog */}
      {confirmDelete && (
        <ConfirmDialog
          message={
            confirmDelete.ids.length === 1
              ? `Delete "${confirmDelete.names[0]}"? This will remove the document, all its chunks, and embeddings from the vector store. This action cannot be undone.`
              : `Delete ${confirmDelete.ids.length} documents? This will remove them and all their chunks from the vector store. This action cannot be undone.`
          }
          onConfirm={confirmDeleteDocs}
          onCancel={() => setConfirmDelete(null)}
        />
      )}

      {showUpload && (
        <UploadModal
          onClose={() => setShowUpload(false)}
          onComplete={() => setRefreshKey(k => k + 1)}
        />
      )}
    </div>
  );
}
