import React, { useCallback, useEffect, useRef, useState } from 'react';

import {
  uploadBatch,
  getBatchStatus,
  getBatchPreview,
  pushToRag,
  listDocuments,
  deleteDocument,
  createTextEntry,
} from '../service/knowledge-base/knowledge-base.service';
import {
  TEXT_ENTRY_BODY_MAX_LENGTH,
  TEXT_ENTRY_TITLE_MAX_LENGTH,
} from '../service/knowledge-base/knowledge-base.routes';
import type {
  DocumentFile,
  BatchStatus,
  BatchPreviewFile,
} from '../service/knowledge-base/knowledge-base.interface';
import { useAppStateContext } from '../context/user.data.context';
import { WORDPRESS_STEP_KEYS } from '../service/setup-progress/setup-progress.constants';
import { setSetupProgressStep } from '../service/setup-progress/setup-progress.service';
import Button from '../components/widgets/Button';
import { Spinner } from '../components/ui/Spinner';
import ErrorWrapper from '../components/alert/ErrorWrapper';

const ALLOWED_TYPES = [
  'application/pdf',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'application/msword',
  'text/csv',
];
const ALLOWED_EXTENSIONS = ['.pdf', '.docx', '.doc', '.csv'];
const MAX_FILES = 5;
const MAX_SIZE = 20 * 1024 * 1024;

const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
};

const StatusBadge = ({ status }: { status: string }) => {
  switch (status.toLowerCase()) {
    case 'pushed':
      return (
        <span className="inline-flex items-center rounded-md bg-emerald-50 px-2 py-1 text-xs font-medium text-emerald-700 ring-1 ring-inset ring-emerald-600/20">
          In Knowledge Base
        </span>
      );
    case 'summarized':
    case 'ready':
      return (
        <span className="inline-flex items-center rounded-md bg-amber-50 px-2 py-1 text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-600/20">
          Ready to Push
        </span>
      );
    case 'processing':
      return (
        <span className="inline-flex items-center rounded-md bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10">
          Processing
        </span>
      );
    case 'failed':
      return (
        <span className="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-red-600/10">
          Failed
        </span>
      );
    default:
      return (
        <span className="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10">
          {status}
        </span>
      );
  }
};

const KnowledgeBase = (): JSX.Element => {
  const { token, clientId } = useAppStateContext();

  // Visiting Knowledge Base auto-completes the step - no documents needed.
  useEffect(() => {
    if (token) {
      setSetupProgressStep(WORDPRESS_STEP_KEYS.KNOWLEDGE_BASE).catch(() => {});
    }
  }, [token]);

  const fileInputRef = useRef<HTMLInputElement>(null);

  const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
  const [uploading, setUploading] = useState(false);
  const [uploadError, setUploadError] = useState<string | null>(null);

  const [batchId, setBatchId] = useState<string | null>(null);
  const [jobId, setJobId] = useState<string | null>(null);
  const [batchStatus, setBatchStatus] = useState<BatchStatus | null>(null);

  const [previewFiles, setPreviewFiles] = useState<BatchPreviewFile[]>([]);
  const [expandedPreviews, setExpandedPreviews] = useState<Set<number>>(
    new Set()
  );
  const [pushing, setPushing] = useState(false);
  const [pushJobId, setPushJobId] = useState<string | null>(null);
  // Set once a push completes; resets only when a new upload begins.
  // Keeps Review Summaries hidden after dismissal so a lingering
  // preview cache can't repopulate the section.
  const [pushedThisSession, setPushedThisSession] = useState(false);

  const [documents, setDocuments] = useState<DocumentFile[]>([]);
  const [loadingDocs, setLoadingDocs] = useState(true);

  const [deleteTarget, setDeleteTarget] = useState<string | null>(null);
  // Auto-imported docs get the ``Exclude`` framing so the merchant
  // understands deleting one also blocks future re-import.
  const deleteTargetIsAuto =
    deleteTarget !== null &&
    documents.find(d => d.file_name === deleteTarget)?.source === 'auto';
  const [deleting, setDeleting] = useState(false);

  const [isDragOver, setIsDragOver] = useState(false);

  const [textEntryTitle, setTextEntryTitle] = useState('');
  const [textEntryDescription, setTextEntryDescription] = useState('');
  const [textEntrySubmitting, setTextEntrySubmitting] = useState(false);
  const [textEntryError, setTextEntryError] = useState<string | null>(null);
  const [textEntrySuccess, setTextEntrySuccess] = useState<string | null>(null);

  const pollingRef = useRef<NodeJS.Timeout | null>(null);

  const fetchDocuments = useCallback(async () => {
    try {
      const result = await listDocuments();
      setDocuments(result.data?.documents || []);
    } catch (err: any) {
      console.error('Failed to load documents:', err);
    } finally {
      setLoadingDocs(false);
    }
  }, []);

  // The Reco copilot dispatches ``copilot:data-changed`` after it generates,
  // adds, or pushes a knowledge-base document, so re-fetch to reflect the new
  // doc / its pushed state without a manual reload.
  useEffect(() => {
    const onCopilotDataChanged = (): void => {
      void fetchDocuments();
    };
    window.addEventListener('copilot:data-changed', onCopilotDataChanged);
    return () =>
      window.removeEventListener('copilot:data-changed', onCopilotDataChanged);
  }, [fetchDocuments]);

  const fetchPreview = useCallback(async (bid: string) => {
    try {
      const result = await getBatchPreview(bid);
      setPreviewFiles(result.data?.files || []);
    } catch (err: any) {
      console.error('Failed to load preview:', err);
    }
  }, []);

  const clearPolling = useCallback(() => {
    if (pollingRef.current) {
      clearInterval(pollingRef.current);
      pollingRef.current = null;
    }
  }, []);

  useEffect(() => {
    if (clientId && token) {
      fetchDocuments();
    }
  }, [clientId, token, fetchDocuments]);

  useEffect(() => {
    if (!jobId || !clientId || !token) return;

    const pollStatus = async () => {
      try {
        const result = await getBatchStatus(jobId);
        const status = result.data;
        setBatchStatus(status);

        if (status.state === 'SUCCESS') {
          clearPolling();
          if (batchId) {
            fetchPreview(batchId);
          }
          fetchDocuments();
        } else if (status.state === 'FAILURE') {
          clearPolling();
          setUploadError(status.error || 'Processing failed');
        }
      } catch (err: any) {
        console.error('Poll error:', err);
      }
    };

    pollStatus();
    pollingRef.current = setInterval(pollStatus, 3000);

    return () => clearPolling();
  }, [
    jobId,
    batchId,
    clientId,
    token,
    clearPolling,
    fetchDocuments,
    fetchPreview,
  ]);

  useEffect(() => {
    if (!pushJobId || !clientId || !token) return;

    const pollPush = async () => {
      try {
        const result = await getBatchStatus(pushJobId);
        const status = result.data;
        setBatchStatus(status);

        if (status.state === 'SUCCESS' || status.state === 'FAILURE') {
          clearPolling();
          setPushing(false);
          setPreviewFiles([]);
          setBatchId(null);
          setJobId(null);
          if (status.state === 'SUCCESS') {
            setPushedThisSession(true);
          }
          fetchDocuments();

          if (status.state === 'FAILURE') {
            setPushJobId(null);
            setBatchStatus(null);
            return;
          }

          // Keep the green success card visible briefly so the merchant
          // sees confirmation before the card auto-dismisses.
          setTimeout(() => {
            setPushJobId(null);
            setBatchStatus(null);
          }, 3000);
        }
      } catch (err: any) {
        console.error('Push poll error:', err);
      }
    };

    pollPush();
    pollingRef.current = setInterval(pollPush, 3000);

    return () => clearPolling();
  }, [pushJobId, clientId, token, clearPolling, fetchDocuments]);

  const addFiles = useCallback((files: File[]) => {
    const valid = files.filter(
      f => ALLOWED_TYPES.includes(f.type) && f.size <= MAX_SIZE
    );
    setSelectedFiles(prev => {
      const combined = [...prev, ...valid];
      return combined.slice(0, MAX_FILES);
    });
    setUploadError(null);
  }, []);

  const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      addFiles(Array.from(e.target.files));
      e.target.value = '';
    }
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragOver(false);
    if (e.dataTransfer.files) {
      addFiles(Array.from(e.dataTransfer.files));
    }
  };

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragOver(true);
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragOver(false);
  };

  const removeFile = (index: number) => {
    setSelectedFiles(prev => prev.filter((_, i) => i !== index));
  };

  const handleUpload = async () => {
    if (!clientId || !token || selectedFiles.length === 0) return;

    setUploading(true);
    setUploadError(null);
    setBatchStatus(null);
    setPreviewFiles([]);
    setPushedThisSession(false);

    try {
      const formData = new FormData();
      selectedFiles.forEach(file => formData.append('files', file));
      formData.append('language', 'en');

      const result = await uploadBatch(formData);
      const data = result.data;

      setBatchId(data.batch_id);
      setJobId(data.job_id);
      setSelectedFiles([]);
    } catch (err: any) {
      setUploadError(err?.message || 'Upload failed');
    } finally {
      setUploading(false);
    }
  };

  const handlePushToRag = async () => {
    if (!clientId || !token || !batchId) return;

    setPushing(true);
    try {
      const result = await pushToRag(batchId);
      const newPushJobId = result.data?.job_id;
      if (newPushJobId) {
        setBatchStatus({
          batch_id: '',
          job_id: newPushJobId,
          state: 'PENDING',
          progress: 0,
          files_processed: 0,
          files_total: 0,
        } as BatchStatus);
      }
      setPushJobId(newPushJobId);
    } catch (err: any) {
      setUploadError(err?.message || 'Push failed');
      setPushing(false);
    }
  };

  const handleTextEntrySubmit = async () => {
    if (!clientId || !token) return;

    const trimmedTitle = textEntryTitle.trim();
    const trimmedDescription = textEntryDescription.trim();
    if (!trimmedTitle || !trimmedDescription) {
      setTextEntryError('Title and description are both required.');
      return;
    }
    if (trimmedDescription.length > TEXT_ENTRY_BODY_MAX_LENGTH) {
      setTextEntryError(
        `Description must be ${TEXT_ENTRY_BODY_MAX_LENGTH} characters or fewer.`
      );
      return;
    }

    setTextEntrySubmitting(true);
    setTextEntryError(null);
    setTextEntrySuccess(null);
    try {
      const result = await createTextEntry({
        title: trimmedTitle,
        description: trimmedDescription,
      });
      setTextEntrySuccess(
        `Added "${result.data?.title || trimmedTitle}" to the knowledge base.`
      );
      setTextEntryTitle('');
      setTextEntryDescription('');
      fetchDocuments();
    } catch (err: any) {
      setTextEntryError(
        err?.response?.data?.detail ||
          err?.message ||
          'Failed to save the text entry.'
      );
    } finally {
      setTextEntrySubmitting(false);
    }
  };

  const handleDelete = async () => {
    if (!clientId || !token || !deleteTarget) return;

    setDeleting(true);
    try {
      await deleteDocument(deleteTarget);
      setDeleteTarget(null);
      fetchDocuments();
    } catch (err: any) {
      console.error('Delete failed:', err);
    } finally {
      setDeleting(false);
    }
  };

  const togglePreview = (index: number) => {
    setExpandedPreviews(prev => {
      const next = new Set(prev);
      if (next.has(index)) {
        next.delete(index);
      } else {
        next.add(index);
      }
      return next;
    });
  };

  const isProcessing =
    batchStatus &&
    (batchStatus.state === 'PENDING' || batchStatus.state === 'PROGRESS');

  return (
    <div className="mx-auto w-full max-w-[1600px] space-y-6 bg-white p-6 md:p-10">
      <header className="mb-8">
        <h1 className="text-xl font-medium tracking-tight text-gray-900 md:text-2xl">
          Knowledge Base
        </h1>
        <p className="mt-2 text-sm text-gray-500">
          Upload store policies, FAQs, and guides. Give your AI agent the
          context it needs to answer customers accurately.
        </p>
      </header>

      <div className="space-y-8">
        <div className="flex flex-col space-y-6">
          {/* Knowledge Base Index — placed at the top so merchants see what
              the AI already knows about their shop before uploading more. */}
          <section className="overflow-hidden rounded-lg border border-gray-200 bg-white">
            <header className="border-b border-gray-100 bg-gray-50/50 px-5 py-4">
              <h2 className="text-sm font-medium text-gray-900">
                Knowledge Base Index
              </h2>
            </header>

            <div className="border-b border-blue-100 bg-blue-50 px-5 py-3 text-sm text-blue-900">
              Items with the{' '}
              <span className="font-semibold">Generated by system</span> badge
              were auto-imported from your site (crawled pages, brand profile,
              shop metadata) so you can see what the AI knows about your shop.
              Use <span className="font-semibold">Download</span> to grab any
              document, edit it locally, and re-upload it below. Your product
              catalog is also part of the AI&apos;s knowledge base but is not
              listed here.
            </div>

            {loadingDocs ? (
              <div className="flex h-32 items-center justify-center p-5">
                <Spinner className="h-5 w-5 text-gray-400" />
              </div>
            ) : documents.length === 0 ? (
              <div className="flex h-32 items-center justify-center p-5">
                <span className="text-sm text-gray-500">
                  No documents indexed yet.
                </span>
              </div>
            ) : (
              <div className="overflow-x-auto">
                <table className="w-full text-left text-sm text-gray-600">
                  <thead className="border-b border-gray-100 bg-white text-xs font-medium text-gray-500">
                    <tr>
                      <th className="px-5 py-3 font-medium">Name</th>
                      <th className="px-5 py-3 font-medium">Type</th>
                      <th className="px-5 py-3 font-medium">Size</th>
                      <th className="px-5 py-3 font-medium">Date</th>
                      <th className="px-5 py-3 font-medium">Status</th>
                      <th className="px-5 py-3 text-right font-medium">
                        Actions
                      </th>
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-gray-100 bg-white">
                    {documents.map(doc => (
                      <tr
                        key={doc.file_name}
                        className="transition-colors hover:bg-gray-50"
                      >
                        <td className="whitespace-nowrap px-5 py-3 text-gray-900">
                          <div className="flex flex-wrap items-center gap-2">
                            <span>{doc.file_name}</span>
                            {doc.source === 'auto' && (
                              <span className="inline-flex items-center rounded-full bg-blue-50 px-2 py-0.5 text-[10px] font-medium text-blue-700">
                                Generated by system
                              </span>
                            )}
                          </div>
                        </td>
                        <td className="whitespace-nowrap px-5 py-3">
                          <span className="inline-flex rounded-md bg-gray-100 px-2 py-1 text-[10px] font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10">
                            {doc.file_type.replace('.', '').toUpperCase()}
                          </span>
                        </td>
                        <td className="whitespace-nowrap px-5 py-3">
                          {formatFileSize(doc.file_size_bytes)}
                        </td>
                        <td className="whitespace-nowrap px-5 py-3">
                          {doc.processed_at
                            ? new Date(doc.processed_at).toLocaleDateString()
                            : '-'}
                        </td>
                        <td className="whitespace-nowrap px-5 py-3">
                          <StatusBadge status={doc.status} />
                        </td>
                        <td className="whitespace-nowrap px-5 py-3 text-right">
                          <div className="flex items-center justify-end gap-3">
                            {doc.download_url && (
                              <button
                                type="button"
                                className="text-sm font-medium text-gray-600 transition-colors hover:text-gray-900"
                                onClick={() =>
                                  window.open(doc.download_url!, '_blank')
                                }
                              >
                                Download
                              </button>
                            )}
                            <button
                              type="button"
                              className="text-sm font-medium text-red-600 transition-colors hover:text-red-800"
                              onClick={() => setDeleteTarget(doc.file_name)}
                            >
                              {doc.source === 'auto' ? 'Exclude' : 'Delete'}
                            </button>
                          </div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </section>

          <section className="overflow-hidden rounded-lg border border-gray-200 bg-white">
            <header className="border-b border-gray-100 bg-gray-50/50 px-5 py-4">
              <h2 className="text-sm font-medium text-gray-900">
                Upload Documents
              </h2>
            </header>
            <div className="p-5">
              <div
                className={`group relative flex cursor-pointer flex-col items-center justify-center rounded-lg border-2 border-dashed py-10 transition-colors ${
                  uploading || isProcessing
                    ? 'border-gray-200 bg-gray-50 cursor-not-allowed'
                    : isDragOver
                      ? 'border-gray-900 bg-gray-50'
                      : 'border-gray-300 bg-white hover:border-gray-400 hover:bg-gray-50/50'
                }`}
                onDrop={handleDrop}
                onDragOver={handleDragOver}
                onDragLeave={handleDragLeave}
                onClick={() => {
                  if (!uploading && !isProcessing)
                    fileInputRef.current?.click();
                }}
              >
                <input
                  ref={fileInputRef}
                  type="file"
                  className="hidden"
                  multiple
                  accept={ALLOWED_EXTENSIONS.join(',')}
                  onChange={handleFileInputChange}
                  disabled={uploading || !!isProcessing}
                />
                <div className="flex h-12 w-12 items-center justify-center rounded-full bg-gray-50 ring-1 ring-inset ring-gray-200 transition-colors group-hover:bg-white group-hover:ring-gray-300">
                  <svg
                    className="h-5 w-5 text-gray-500 transition-colors group-hover:text-gray-900"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    strokeWidth={2}
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
                    />
                  </svg>
                </div>
                <p className="mt-4 text-sm font-medium text-gray-900">
                  Drop files here or click to browse
                </p>
                <p className="mt-1 text-xs text-gray-500">
                  Accepts PDF, DOCX, DOC, CSV (max {MAX_SIZE / (1024 * 1024)} MB
                  each)
                </p>
              </div>

              {selectedFiles.length > 0 && (
                <div className="mt-6 space-y-4 rounded-md border border-gray-200 p-4">
                  <div className="flex items-center justify-between">
                    <h3 className="text-sm font-medium text-gray-900">
                      Selected Files{' '}
                      <span className="text-gray-500">
                        ({selectedFiles.length}/{MAX_FILES})
                      </span>
                    </h3>
                  </div>
                  <ul className="divide-y divide-gray-100">
                    {selectedFiles.map((file, i) => (
                      <li
                        key={i}
                        className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
                      >
                        <div className="flex items-center gap-3">
                          <svg
                            className="h-4 w-4 text-gray-400"
                            fill="none"
                            viewBox="0 0 24 24"
                            stroke="currentColor"
                            strokeWidth={2}
                          >
                            <path
                              strokeLinecap="round"
                              strokeLinejoin="round"
                              d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
                            />
                          </svg>
                          <span className="text-sm text-gray-900">
                            {file.name}
                          </span>
                          <span className="text-xs text-gray-500">
                            ({formatFileSize(file.size)})
                          </span>
                        </div>
                        <button
                          type="button"
                          className="text-sm font-medium text-red-600 transition-colors hover:text-red-700"
                          onClick={() => removeFile(i)}
                        >
                          Remove
                        </button>
                      </li>
                    ))}
                  </ul>
                  <div className="flex justify-end border-t border-gray-100 pt-4">
                    <Button
                      onClick={handleUpload}
                      disabled={uploading || selectedFiles.length === 0}
                      isLoading={uploading}
                      className="rounded-md bg-gray-900 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
                    >
                      Process Documents
                    </Button>
                  </div>
                </div>
              )}

              {uploadError && (
                <div className="mt-4">
                  <ErrorWrapper error={uploadError} />
                </div>
              )}
            </div>
          </section>

          <div className="flex items-center gap-3 text-xs font-medium uppercase tracking-wide text-gray-400">
            <span className="h-px flex-1 bg-gray-200" />
            <span>Or write text directly</span>
            <span className="h-px flex-1 bg-gray-200" />
          </div>

          <section className="overflow-hidden rounded-lg border border-gray-200 bg-white">
            <header className="border-b border-gray-100 bg-gray-50/50 px-5 py-4">
              <h2 className="text-sm font-medium text-gray-900">
                Add Text Entry
              </h2>
              <p className="mt-1 text-xs text-gray-500">
                Skip the document upload — paste a short note (FAQ, policy
                snippet, store hours) and we&apos;ll push it to the knowledge
                base immediately.
              </p>
            </header>
            <div className="space-y-4 p-5">
              <div>
                <label
                  htmlFor="kb-text-title"
                  className="block text-xs font-medium text-gray-700"
                >
                  Title
                </label>
                <input
                  id="kb-text-title"
                  type="text"
                  className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 text-sm text-gray-900 placeholder-gray-400 focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                  placeholder="E.g. Return policy"
                  maxLength={TEXT_ENTRY_TITLE_MAX_LENGTH}
                  value={textEntryTitle}
                  onChange={e => setTextEntryTitle(e.target.value)}
                  disabled={textEntrySubmitting}
                />
                <p className="mt-1 text-[11px] text-gray-400">
                  {textEntryTitle.length}/{TEXT_ENTRY_TITLE_MAX_LENGTH}
                </p>
              </div>
              <div>
                <label
                  htmlFor="kb-text-description"
                  className="block text-xs font-medium text-gray-700"
                >
                  Description
                </label>
                <textarea
                  id="kb-text-description"
                  rows={6}
                  className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 text-sm text-gray-900 placeholder-gray-400 focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                  placeholder="Write the answer in plain language — exact wording, numbers, and dates included."
                  maxLength={TEXT_ENTRY_BODY_MAX_LENGTH}
                  value={textEntryDescription}
                  onChange={e => setTextEntryDescription(e.target.value)}
                  disabled={textEntrySubmitting}
                />
                <p className="mt-1 text-[11px] text-gray-400">
                  {textEntryDescription.length}/{TEXT_ENTRY_BODY_MAX_LENGTH}
                </p>
              </div>

              {textEntryError && <ErrorWrapper error={textEntryError} />}
              {textEntrySuccess && (
                <div className="rounded-md border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-800">
                  {textEntrySuccess}
                </div>
              )}

              <div className="flex justify-end">
                <Button
                  onClick={handleTextEntrySubmit}
                  disabled={
                    textEntrySubmitting ||
                    !textEntryTitle.trim() ||
                    !textEntryDescription.trim()
                  }
                  isLoading={textEntrySubmitting}
                  className="rounded-md bg-gray-900 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
                >
                  Add to Knowledge Base
                </Button>
              </div>
            </div>
          </section>

          {batchStatus && (
            <section
              className={`overflow-hidden rounded-lg border bg-white ${
                batchStatus.state === 'SUCCESS'
                  ? 'border-emerald-300 ring-1 ring-emerald-200'
                  : batchStatus.state === 'FAILURE'
                    ? 'border-red-300 ring-1 ring-red-200'
                    : 'border-gray-200'
              }`}
            >
              <header className="border-b border-gray-100 bg-gray-50/50 px-5 py-4">
                <h2 className="text-sm font-medium text-gray-900">
                  {pushJobId
                    ? batchStatus.state === 'SUCCESS'
                      ? 'Pushed to Knowledge Base'
                      : batchStatus.state === 'FAILURE'
                        ? 'Push Failed'
                        : 'Pushing to Knowledge Base'
                    : 'Processing Status'}
                </h2>
              </header>
              <div className="p-5">
                <div className="mb-4 flex items-center justify-between">
                  <span className="text-sm text-gray-700">
                    {pushJobId
                      ? batchStatus.state === 'PENDING'
                        ? 'Waiting in queue...'
                        : batchStatus.state === 'PROGRESS'
                          ? `Pushing: ${batchStatus.current_file || '...'}`
                          : batchStatus.state === 'SUCCESS'
                            ? 'Your files are now available to the agent.'
                            : 'Push to knowledge base failed.'
                      : batchStatus.state === 'PENDING'
                        ? 'Waiting in queue...'
                        : batchStatus.state === 'PROGRESS'
                          ? `Processing: ${batchStatus.current_file || '...'}`
                          : batchStatus.state === 'SUCCESS'
                            ? 'Processing complete!'
                            : 'Processing failed'}
                  </span>
                  <span
                    className={`inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset ${
                      batchStatus.state === 'SUCCESS'
                        ? 'bg-emerald-50 text-emerald-700 ring-emerald-600/20'
                        : batchStatus.state === 'FAILURE'
                          ? 'bg-red-50 text-red-700 ring-red-600/10'
                          : 'bg-blue-50 text-blue-700 ring-blue-700/10'
                    }`}
                  >
                    {pushJobId && batchStatus.state === 'PROGRESS'
                      ? 'PUSHING'
                      : pushJobId && batchStatus.state === 'SUCCESS'
                        ? 'PUSHED'
                        : batchStatus.state}
                  </span>
                </div>

                <div className="h-1.5 w-full overflow-hidden rounded-full bg-gray-100">
                  <div
                    className={`h-full rounded-full transition-all duration-300 ${
                      batchStatus.state === 'FAILURE'
                        ? 'bg-red-500'
                        : 'bg-gray-900'
                    }`}
                    style={{ width: `${batchStatus.progress}%` }}
                  />
                </div>

                {batchStatus.files_total > 0 && (
                  <p className="mt-2 text-xs font-medium text-gray-500">
                    {batchStatus.files_processed} of {batchStatus.files_total}{' '}
                    files processed
                  </p>
                )}

                {batchStatus.results && batchStatus.results.length > 0 && (
                  <ul className="mt-6 divide-y divide-gray-100 rounded-md border border-gray-100 bg-gray-50/50">
                    {batchStatus.results.map((r, i) => (
                      <li
                        key={i}
                        className="flex items-center justify-between px-4 py-3"
                      >
                        <span className="text-sm text-gray-900">
                          {r.file_name}
                        </span>
                        {r.status === 'ready' ? (
                          <span className="inline-flex items-center rounded-md bg-emerald-50 px-2 py-1 text-xs font-medium text-emerald-700 ring-1 ring-inset ring-emerald-600/20">
                            Ready
                          </span>
                        ) : (
                          <span className="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-red-600/10">
                            Failed
                          </span>
                        )}
                      </li>
                    ))}
                  </ul>
                )}

                {batchStatus.state === 'SUCCESS' && !pushJobId && (
                  <div className="mt-4 rounded-md border border-amber-300 bg-amber-50 p-3 text-sm text-amber-900">
                    <p className="font-semibold">
                      Next step: push to Knowledge Base
                    </p>
                    <p className="mt-1">
                      Your files are processed but the agent still can&apos;t
                      see them until you scroll down to{' '}
                      <span className="font-semibold">Review AI Summaries</span>{' '}
                      and click{' '}
                      <span className="font-semibold">
                        &ldquo;Push to Knowledge Base&rdquo;
                      </span>
                      .
                    </p>
                  </div>
                )}
              </div>
            </section>
          )}

          {previewFiles.length > 0 &&
            !pushJobId &&
            !pushing &&
            !pushedThisSession && (
              <section className="overflow-hidden rounded-lg border-2 border-amber-300 bg-white ring-1 ring-amber-200">
                <header className="flex flex-col items-center gap-3 border-b border-amber-200 bg-amber-50/60 px-5 py-4">
                  <div className="text-center">
                    <h2 className="text-sm font-medium text-gray-900">
                      Review AI Summaries
                    </h2>
                    <p className="mt-0.5 text-xs text-gray-500">
                      Review generated summaries before pushing them live.
                    </p>
                  </div>
                  <Button
                    onClick={handlePushToRag}
                    disabled={pushing}
                    isLoading={pushing}
                    className="rounded-md bg-amber-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-amber-600 disabled:cursor-not-allowed disabled:opacity-50"
                  >
                    Push to Knowledge Base
                  </Button>
                </header>
                <div className="border-b border-amber-200 bg-amber-50/40 px-5 py-3 text-sm text-amber-900">
                  <p className="font-semibold">
                    Action required: files are not live yet
                  </p>
                  <p className="mt-1">
                    Processing finished, but your agent still can&apos;t see
                    these documents. Review the summaries below, then click{' '}
                    <span className="font-semibold">
                      &ldquo;Push to Knowledge Base&rdquo;
                    </span>{' '}
                    to make them available in conversations.
                  </p>
                </div>
                <div className="divide-y divide-gray-100">
                  {previewFiles.map((file, i) => (
                    <div key={i} className="p-5">
                      <div className="flex items-center justify-between">
                        <div className="space-y-1">
                          <p className="text-sm font-medium text-gray-900">
                            {file.name}
                          </p>
                          <p className="text-xs text-gray-500">
                            Original: {formatFileSize(file.original_size)} |
                            Summary: {file.summary_length.toLocaleString()}{' '}
                            chars
                          </p>
                        </div>
                        <button
                          type="button"
                          className="text-sm font-medium text-gray-600 underline underline-offset-4 transition-colors hover:text-gray-900"
                          onClick={() => togglePreview(i)}
                        >
                          {expandedPreviews.has(i)
                            ? 'Hide Summary'
                            : 'View Summary'}
                        </button>
                      </div>

                      {expandedPreviews.has(i) && (
                        <div className="mt-4 max-h-[400px] overflow-y-auto rounded-md bg-gray-50 p-4 ring-1 ring-inset ring-gray-200">
                          <pre className="whitespace-pre-wrap font-sans text-[13px] leading-relaxed text-gray-700">
                            {file.summary}
                          </pre>
                        </div>
                      )}
                    </div>
                  ))}
                </div>
              </section>
            )}
        </div>

        <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
          <section className="rounded-lg border border-gray-200 bg-white p-6">
            <h3 className="text-sm font-medium text-gray-900">How It Works</h3>
            <div className="mt-4 space-y-4 text-sm text-gray-600">
              <p>
                Upload store policies, FAQs, or guides. Our AI reads,
                understands, and summarizes each file so your agent can
                reference it during customer interactions.
              </p>
              <ol className="space-y-3">
                <li className="flex gap-3">
                  <span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-gray-100 text-xs font-medium text-gray-900">
                    1
                  </span>
                  <span>
                    <strong>Upload:</strong> Drop files (up to {MAX_FILES} per
                    batch, max {MAX_SIZE / (1024 * 1024)}MB each).
                  </span>
                </li>
                <li className="flex gap-3">
                  <span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-gray-100 text-xs font-medium text-gray-900">
                    2
                  </span>
                  <span>
                    <strong>Processing:</strong> PDFs are scanned via OCR and
                    summarized by AI. DOCX, CSV, and TXT files are processed
                    directly.
                  </span>
                </li>
                <li className="flex gap-3">
                  <span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-gray-100 text-xs font-medium text-gray-900">
                    3
                  </span>
                  <span>
                    <strong>Review:</strong> Preview generated summaries before
                    publishing.
                  </span>
                </li>
                <li className="flex gap-3">
                  <span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-gray-100 text-xs font-medium text-gray-900">
                    4
                  </span>
                  <span>
                    <strong>Push to AI:</strong> Sync approved documents to the
                    knowledge base instantly.
                  </span>
                </li>
              </ol>
            </div>
          </section>

          <section className="rounded-lg border border-gray-200 bg-gray-50 p-6">
            <h3 className="text-sm font-medium text-gray-900">
              Recommended Format
            </h3>
            <p className="mt-2 text-sm text-gray-600">
              For best results, structure documents in a clear Q&A format. The
              more concise the content, the better the AI will answer questions.
            </p>
            <div className="mt-4 overflow-hidden rounded-md border border-gray-200 bg-white">
              <pre className="p-4 font-mono text-[11px] leading-relaxed text-gray-800 overflow-x-auto">
                {`Q: What is your return policy?
A: We accept returns within 30 days of purchase. Items must be unused and in original packaging. Refunds are processed within 5-7 business days.

Q: Do you offer free shipping?
A: Free shipping on all orders over $50. Standard shipping (3-5 days) is $4.99. Express shipping (1-2 days) is $9.99.`}
              </pre>
            </div>
          </section>
        </div>
      </div>

      {deleteTarget && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div
            className="fixed inset-0 bg-gray-900/40 backdrop-blur-sm transition-opacity"
            onClick={() => !deleting && setDeleteTarget(null)}
          />
          <div className="relative z-10 w-full max-w-md overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-gray-200 p-6">
            <div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
              <svg
                className="h-6 w-6 text-red-600"
                fill="none"
                viewBox="0 0 24 24"
                strokeWidth="1.5"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
                />
              </svg>
            </div>
            <h3 className="text-center text-lg font-medium text-gray-900">
              {deleteTargetIsAuto ? 'Exclude this page' : 'Delete Document'}
            </h3>
            <p className="mt-2 text-center text-sm text-gray-500">
              {deleteTargetIsAuto ? (
                <>
                  <strong className="text-gray-900">
                    {`"`}
                    {deleteTarget}
                    {`"`}
                  </strong>{' '}
                  was auto-imported from your site. Excluding it removes it from
                  the knowledge base now and tells the next sync to skip the
                  same page, so it won&apos;t keep coming back.
                </>
              ) : (
                <>
                  Are you sure you want to delete{' '}
                  <strong className="text-gray-900">
                    {`"`}
                    {deleteTarget}
                    {`"`}
                  </strong>
                  ? If it was already pushed, it will be removed on the next
                  rebuild.
                </>
              )}
            </p>
            <div className="mt-6 flex flex-col-reverse gap-3 sm:flex-row sm:justify-between">
              <Button
                variant="secondary"
                className="w-full justify-center rounded-md border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-900 hover:bg-gray-50 sm:w-auto"
                onClick={() => setDeleteTarget(null)}
                disabled={deleting}
              >
                Cancel
              </Button>
              <Button
                className="w-full justify-center rounded-md bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 sm:w-auto"
                onClick={handleDelete}
                disabled={deleting}
                isLoading={deleting}
              >
                {deleteTargetIsAuto ? 'Exclude' : 'Delete Document'}
              </Button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default KnowledgeBase;
