// Copyright: © 2026 TWWIM UG. All rights reserved. (www.twwim.com)

import { useRef, useState } from 'react';
import {
  FileText, Trash2, Plus, AlertCircle, Database, ShieldAlert,
  Upload, X, Download, Loader2, CheckCircle2, XCircle,
} from 'lucide-react';
import {
  useKnowledgeDocuments,
  useUploadKnowledgeDocument,
  useDeleteKnowledgeDocument,
} from '../hooks';
import { useTranslation } from '@/i18n/TranslationProvider';
import { tokenStorage } from '@/infrastructure/storage/LocalTokenStorage';
import type { KnowledgeDocument } from '@/infrastructure/http/api/knowledge';
import { knowledgeApi } from '@/infrastructure/http/api/knowledge';
import { apiClient } from '@/infrastructure/http/ApiClient';

const ALLOWED_EXTENSIONS = '.pdf,.docx,.txt';
const ALLOWED_MIME = [
  'application/pdf',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'text/plain',
];
const FILE_BYTES_MAX = 25 * 1024 * 1024;

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

function StatusPill({ status }: { status: KnowledgeDocument['status'] }) {
  const map: Record<KnowledgeDocument['status'], { color: string; icon: JSX.Element; label: string }> = {
    PENDING: { color: 'bg-gray-100 text-gray-700', icon: <Loader2 size={12} className="animate-spin" />, label: 'Pending' },
    PROCESSING: { color: 'bg-blue-100 text-blue-700', icon: <Loader2 size={12} className="animate-spin" />, label: 'Processing' },
    COMPLETED: { color: 'bg-emerald-100 text-emerald-800', icon: <CheckCircle2 size={12} />, label: 'Indexed' },
    FAILED: { color: 'bg-red-100 text-red-800', icon: <XCircle size={12} />, label: 'Failed' },
  };
  const cur = map[status] ?? map.PENDING;
  return (
    <span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium ${cur.color}`}>
      {cur.icon}
      {cur.label}
    </span>
  );
}

function UploadForm({ tenantId, onClose }: { tenantId: string; onClose: () => void }) {
  const { t } = useTranslation();
  const upload = useUploadKnowledgeDocument(tenantId);
  const [file, setFile] = useState<File | null>(null);
  const [localError, setLocalError] = useState<string | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const pick = (chosen: File | null) => {
    setLocalError(null);
    if (!chosen) {
      setFile(null);
      return;
    }
    if (!ALLOWED_MIME.includes(chosen.type)) {
      setLocalError(`Unsupported type: ${chosen.type || 'unknown'}. Allowed: PDF, DOCX, TXT.`);
      return;
    }
    if (chosen.size > FILE_BYTES_MAX) {
      setLocalError(`File too large (${formatBytes(chosen.size)}). Max ${formatBytes(FILE_BYTES_MAX)}.`);
      return;
    }
    setFile(chosen);
  };

  const submit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!file) return;
    upload.mutate(file, {
      onSuccess: () => onClose(),
    });
  };

  return (
    <div className="bg-white border border-gray-200 rounded-lg p-6 mb-6">
      <div className="flex items-center justify-between mb-4">
        <h3 className="text-lg font-semibold text-gray-900">{t('knowledge.uploadDocument') ?? 'Upload document'}</h3>
        <button onClick={onClose} className="p-1 text-gray-400 hover:text-gray-600">
          <X size={20} />
        </button>
      </div>

      <form onSubmit={submit} className="space-y-4">
        <input
          ref={inputRef}
          type="file"
          accept={ALLOWED_EXTENSIONS}
          onChange={(e) => pick(e.target.files?.[0] ?? null)}
          className="block w-full text-sm text-gray-600 file:mr-3 file:py-2 file:px-4 file:rounded file:border-0 file:text-sm file:font-medium file:bg-cyan-50 file:text-cyan-700 hover:file:bg-cyan-100"
        />

        {file && (
          <div className="flex items-center gap-2 px-3 py-2 bg-gray-50 border border-gray-200 rounded text-sm">
            <FileText size={16} className="text-gray-400" />
            <span className="flex-1 truncate">{file.name}</span>
            <span className="text-xs text-gray-500">{formatBytes(file.size)}</span>
          </div>
        )}

        {localError && (
          <div className="flex items-center gap-2 p-3 bg-red-50 border border-red-200 rounded text-sm text-red-700">
            <AlertCircle size={16} />
            {localError}
          </div>
        )}

        {upload.isError && !localError && (
          <div className="flex items-center gap-2 p-3 bg-red-50 border border-red-200 rounded text-sm text-red-700">
            <AlertCircle size={16} />
            {upload.error?.message ?? (t('knowledge.uploadError') ?? 'Upload failed')}
          </div>
        )}

        <div className="flex justify-end gap-3">
          <button
            type="button"
            onClick={onClose}
            className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50"
          >
            {t('common.cancel')}
          </button>
          <button
            type="submit"
            disabled={!file || upload.isPending}
            className="px-4 py-2 text-sm font-medium text-white bg-cyan-600 rounded-lg hover:bg-cyan-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
          >
            {upload.isPending ? (
              <Loader2 size={16} className="animate-spin" />
            ) : (
              <Upload size={16} />
            )}
            {upload.isPending ? (t('common.uploading') ?? 'Uploading…') : (t('knowledge.upload') ?? 'Upload')}
          </button>
        </div>
      </form>
    </div>
  );
}

function DocumentRow({ doc, tenantId }: { doc: KnowledgeDocument; tenantId: string }) {
  const { t } = useTranslation();
  const del = useDeleteKnowledgeDocument(tenantId);
  const [confirm, setConfirm] = useState(false);

  const download = async () => {
    // Hit the authenticated endpoint via ApiClient (carries the JWT), then
    // turn the blob into a temporary <a download> click.
    try {
      const resp = await (apiClient as any).get(
        knowledgeApi.getDocumentDownloadUrl(tenantId, doc.id),
        { responseType: 'blob' },
      );
      const blob = resp as Blob;
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = doc.filename;
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
    } catch (e) {
      // Surface a non-blocking error
      console.error('Download failed', e);
    }
  };

  return (
    <tr className="hover:bg-gray-50 transition-colors">
      <td className="px-4 py-3">
        <div className="flex items-start gap-2 min-w-0">
          <FileText size={16} className="text-gray-400 mt-0.5 shrink-0" />
          <div className="min-w-0">
            <div className="text-sm font-medium text-gray-900 truncate">{doc.filename}</div>
            <div className="text-xs text-gray-500">
              {doc.mimeType} · {formatBytes(doc.sizeBytes)}
              {doc.chunkCount > 0 && <span> · {doc.chunkCount} chunks</span>}
            </div>
            {doc.errorMessage && (
              <div className="text-xs text-red-600 truncate max-w-md mt-0.5">{doc.errorMessage}</div>
            )}
          </div>
        </div>
      </td>
      <td className="px-4 py-3"><StatusPill status={doc.status} /></td>
      <td className="px-4 py-3 text-xs text-gray-500">{new Date(doc.createdAt).toLocaleDateString()}</td>
      <td className="px-4 py-3 text-right">
        <div className="flex items-center justify-end gap-1">
          <button
            onClick={download}
            disabled={doc.status !== 'COMPLETED' && doc.status !== 'FAILED'}
            className="p-1.5 text-gray-400 hover:text-cyan-600 rounded hover:bg-cyan-50 transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
            title={t('common.download') ?? 'Download'}
          >
            <Download size={14} />
          </button>
          {confirm ? (
            <>
              <button onClick={() => setConfirm(false)} className="px-2 py-1 text-xs text-gray-600 hover:text-gray-800">
                {t('common.cancel')}
              </button>
              <button
                onClick={() => del.mutate(doc.id, { onSuccess: () => setConfirm(false) })}
                disabled={del.isPending}
                title={t('common.confirm') ?? 'Confirm'}
                aria-label={t('common.confirm') ?? 'Confirm'}
                className="px-2 py-1 text-xs text-white bg-red-600 rounded hover:bg-red-700 disabled:opacity-50"
              >
                {del.isPending ? '…' : t('common.confirm')}
              </button>
            </>
          ) : (
            <button
              onClick={() => setConfirm(true)}
              className="p-1.5 text-gray-400 hover:text-red-600 rounded hover:bg-red-50 transition-colors"
              title={t('common.delete')}
            >
              <Trash2 size={14} />
            </button>
          )}
        </div>
      </td>
    </tr>
  );
}

interface KnowledgeDocumentsTabProps {
  tenantId: string;
}

export function KnowledgeDocumentsTab({ tenantId }: KnowledgeDocumentsTabProps) {
  const { t } = useTranslation();
  const [isAdding, setIsAdding] = useState(false);
  const { data, isLoading, error } = useKnowledgeDocuments(tenantId);

  const capValue = tokenStorage.getCapability('knowledge_files_max');
  const maxFiles = capValue ? parseInt(capValue, 10) : 0;
  const featureEnabled = maxFiles > 0;
  const totalDocs = data?.total ?? 0;
  const atLimit = !featureEnabled || totalDocs >= maxFiles;

  if (isLoading) {
    return (
      <div className="animate-pulse space-y-4 p-6">
        <div className="h-10 bg-gray-200 rounded w-1/3" />
        <div className="h-64 bg-gray-200 rounded" />
      </div>
    );
  }

  if (error) {
    return (
      <div className="p-6">
        <div className="flex items-center gap-2 p-4 bg-red-50 border border-red-200 rounded-lg text-sm text-red-700">
          <AlertCircle size={16} />
          {t('knowledge.loadError')}: {error.message}
        </div>
      </div>
    );
  }

  const items = data?.items ?? [];

  return (
    <div>
      {!featureEnabled && (
        <div className="mx-6 mt-4 flex items-center gap-2 p-3 bg-gray-100 border border-gray-200 rounded-lg text-sm text-gray-600">
          <ShieldAlert size={16} className="shrink-0" />
          {t('knowledge.featureDisabled')}
        </div>
      )}
      {featureEnabled && totalDocs >= maxFiles && (
        <div className="mx-6 mt-4 flex items-center gap-2 p-3 bg-amber-50 border border-amber-200 rounded-lg text-sm text-amber-800">
          <ShieldAlert size={16} className="shrink-0" />
          {t('knowledge.limitReached') ?? `Document limit reached (${totalDocs}/${maxFiles}).`}
        </div>
      )}

      <div className="px-6 py-4 flex items-center gap-3">
        <div className="text-sm text-gray-500">
          {totalDocs} / {maxFiles} {totalDocs === 1 ? 'document' : 'documents'}
        </div>
        <button
          onClick={() => setIsAdding(true)}
          disabled={atLimit}
          className="ml-auto px-4 py-2 text-sm font-medium text-white bg-cyan-600 rounded-lg hover:bg-cyan-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
        >
          <Plus size={16} />
          {t('knowledge.uploadDocument') ?? 'Upload document'}
        </button>
      </div>

      {isAdding && !atLimit && (
        <div className="px-6">
          <UploadForm tenantId={tenantId} onClose={() => setIsAdding(false)} />
        </div>
      )}

      {items.length === 0 ? (
        <div className="px-6 py-12 text-center">
          <Database className="mx-auto h-12 w-12 text-gray-300 mb-3" />
          <p className="text-sm text-gray-500 mb-1">{t('knowledge.noDocuments') ?? 'No documents yet'}</p>
          <p className="text-xs text-gray-400">{t('knowledge.noDocumentsHint') ?? 'Upload a PDF, DOCX, or TXT file to get started.'}</p>
        </div>
      ) : (
        <div className="overflow-x-auto">
          <table className="w-full">
            <thead className="bg-gray-50 border-y border-gray-200">
              <tr>
                <th className="px-4 py-2.5 text-left text-xs font-medium text-gray-500 uppercase">{t('knowledge.title')}</th>
                <th className="px-4 py-2.5 text-left text-xs font-medium text-gray-500 uppercase">{t('knowledge.status')}</th>
                <th className="px-4 py-2.5 text-left text-xs font-medium text-gray-500 uppercase">{t('knowledge.created')}</th>
                <th className="px-4 py-2.5 text-right text-xs font-medium text-gray-500 uppercase">{t('common.actions')}</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-200">
              {items.map((doc: KnowledgeDocument) => (
                <DocumentRow key={doc.id} doc={doc} tenantId={tenantId} />
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}
