import { useState } from "react";
import { api, getErrorMessage } from "../api";
import type { CorpusStats } from "../types";
import StatusMessage from "./StatusMessage";
import Select from "./Select";

interface Props {
  onStatsUpdate: (stats: CorpusStats) => void;
}

const MODELS = [
  { value: "all-MiniLM-L6-v2", label: "all-MiniLM-L6-v2 (fast, 384-dim)" },
  { value: "all-mpnet-base-v2", label: "all-mpnet-base-v2 (best quality, 768-dim)" },
  { value: "BAAI/bge-large-en-v1.5", label: "BAAI/bge-large-en-v1.5 (high accuracy, 1024-dim)" },
];

export default function EngineSetup({ onStatsUpdate }: Props) {
  const [model, setModel] = useState("all-MiniLM-L6-v2");
  const [chunkSize, setChunkSize] = useState(512);
  const [chunkOverlap, setChunkOverlap] = useState(128);
  const [batchSize, setBatchSize] = useState(64);

  const [docId, setDocId] = useState("");
  const [docText, setDocText] = useState("");

  const [showAdvanced, setShowAdvanced] = useState(false);
  const [status, setStatus] = useState<{ type: "ok" | "err" | "loading"; msg: string } | null>(null);
  const [initialized, setInitialized] = useState(false);
  const [docsAdded, setDocsAdded] = useState<string[]>([]);

  async function handleInit() {
    setStatus({ type: "loading", msg: "Loading model..." });
    try {
      const res = await api.init({
        model_name: model,
        chunk_size: chunkSize,
        chunk_overlap: chunkOverlap,
        batch_size: batchSize,
      });
      setInitialized(true);
      setDocsAdded([]);
      setStatus({ type: "ok", msg: `Model "${res.model}" loaded in ${res.load_time_seconds}s` });
    } catch (e: unknown) {
      setStatus({ type: "err", msg: getErrorMessage(e) });
    }
  }

  async function handleAddDoc() {
    if (!docId.trim() || !docText.trim()) return;
    setStatus({ type: "loading", msg: `Adding document "${docId}"...` });
    try {
      const res = await api.addDocument({ doc_id: docId, text: docText });
      setDocsAdded((prev) => [...prev, res.doc_id]);
      setStatus({ type: "ok", msg: `Added "${res.doc_id}": ${res.num_chunks} chunks` });
      setDocId("");
      setDocText("");
    } catch (e: unknown) {
      setStatus({ type: "err", msg: getErrorMessage(e) });
    }
  }

  async function handleBuildIndex() {
    setStatus({ type: "loading", msg: "Building FAISS index..." });
    try {
      const res = await api.buildIndex();
      setStatus({
        type: "ok",
        msg: `Index built: ${res.total_chunks} vectors (dim=${res.embedding_dim}) in ${res.build_time_seconds}s`,
      });
      const stats = await api.getStats();
      onStatsUpdate(stats);
    } catch (e: unknown) {
      setStatus({ type: "err", msg: getErrorMessage(e) });
    }
  }

  return (
    <div>
      {/* Step 1: Initialize engine */}
      <div className="panel">
        <h2>1. Initialize Engine</h2>
        <div className="form-row">
          <div className="form-group">
            <label>Model</label>
            <Select options={MODELS} value={model} onChange={setModel} />
          </div>
        </div>

        <button className="advanced-toggle" onClick={() => setShowAdvanced(!showAdvanced)}>
          {showAdvanced ? "\u25be" : "\u25b8"} Advanced Settings
        </button>

        {showAdvanced && (
          <div className="advanced-section">
            <div className="form-row">
              <div className="form-group form-group-md">
                <label>Chunk Size</label>
                <input type="number" value={chunkSize} onChange={(e) => setChunkSize(+e.target.value)} />
              </div>
              <div className="form-group form-group-md">
                <label>Overlap</label>
                <input type="number" value={chunkOverlap} onChange={(e) => setChunkOverlap(+e.target.value)} />
              </div>
              <div className="form-group form-group-md">
                <label>Batch Size</label>
                <input type="number" value={batchSize} onChange={(e) => setBatchSize(+e.target.value)} />
              </div>
            </div>
          </div>
        )}

        <button className="btn btn-primary" onClick={handleInit} style={{ marginTop: 8 }}>
          Initialize
        </button>
      </div>

      {/* Step 2: Add documents */}
      <div className="panel">
        <h2>2. Add Documents</h2>
        {docsAdded.length > 0 && (
          <div style={{ marginBottom: 12 }}>
            {docsAdded.map((id) => (
              <span key={id} className="tag">{id}</span>
            ))}
          </div>
        )}
        <div className="form-row">
          <div className="form-group form-group-lg">
            <label>Document ID</label>
            <input
              value={docId}
              onChange={(e) => setDocId(e.target.value)}
              placeholder="e.g. chapter_1"
              disabled={!initialized}
            />
          </div>
        </div>
        <div className="form-group mb-2">
          <label>Document Text</label>
          <textarea
            value={docText}
            onChange={(e) => setDocText(e.target.value)}
            placeholder="Paste your document text here..."
            rows={8}
            disabled={!initialized}
          />
        </div>
        <button className="btn btn-primary" onClick={handleAddDoc} disabled={!initialized || !docId || !docText}>
          Add Document
        </button>
      </div>

      {/* Step 3: Build index */}
      <div className="panel">
        <h2>3. Build Index</h2>
        <p className="panel-desc">
          Embeds all chunks and builds a FAISS index for fast similarity search.
          This must be done after adding all documents.
        </p>
        <button
          className="btn btn-primary"
          onClick={handleBuildIndex}
          disabled={!initialized || docsAdded.length === 0}
        >
          Build Index
        </button>
      </div>

      {status && <StatusMessage type={status.type} message={status.msg} />}
    </div>
  );
}
