/* autoqa.jsx - shared auto training-data generation: dialog + run hook (Knowledge base + Training Data Studio) */

function useAutoQa({ modelId, settings, authUser, versionId }) {
  const [autoqa, setAutoqa] = React.useState(null);
  const abortRef = React.useRef(null);
  const isRealUser = authUser && !authUser.isDemo;

  const baseState = () => ({
    selectedFiles: [],
    questionsPerChunk: 3,
    phase: "confirm",
    position: 0,
    examples: [],
    warnings: 0,
    summary: null,
    error: null,
    modelId: modelId || null,
  });
  const openForFile = (file) => {
    setAutoqa({
      ...baseState(),
      selectedFiles: [{
        fileId: file.fileId || file.id || null,
        name: file.name || file.filename || null,
        chunks: Number(file.chunks ?? file.chunkCount ?? 0) || 0,
      }],
    });
  };
  const openPicker = () => setAutoqa(baseState());
  const toggleFile = (file) => setAutoqa(prev => prev ? {
    ...prev,
    selectedFiles: (() => {
      const fileId = file.fileId || file.id;
      if (prev.selectedFiles.some(f => f.fileId === fileId)) {
        return prev.selectedFiles.filter(f => f.fileId !== fileId);
      }
      return [...prev.selectedFiles, {
        fileId,
        name: file.filename || file.name,
        chunks: Number(file.chunkCount ?? file.chunks ?? 0) || 0,
      }];
    })(),
  } : prev);
  const setQuestionsPerChunk = (n) => setAutoqa(prev => prev ? { ...prev, questionsPerChunk: n } : prev);
  const stop = () => { abortRef.current?.abort(); };
  const close = () => {
    stop();
    abortRef.current = null;
    setAutoqa(null);
  };

  const downloadJsonl = () => {
    if (!autoqa?.examples?.length) return;
    const jsonl = autoqa.examples.map(ex => JSON.stringify({ instruction: ex.question, input: "", output: ex.answer })).join("\n");
    const base = String(autoqa.selectedFiles?.[0]?.name || "document").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9-_]+/g, "-").slice(0, 60) || "document";
    const url = URL.createObjectURL(new Blob([jsonl], { type: "application/x-ndjson" }));
    const a = document.createElement("a");
    a.href = url;
    a.download = `autoqa-${base}.jsonl`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const start = async () => {
    if (!autoqa || !isRealUser) return;
    const runModelId = autoqa.modelId || modelId;
    const fileIds = (autoqa.selectedFiles || []).map(f => f.fileId).filter(Boolean);
    if (!runModelId || !fileIds.length) return;
    const controller = new AbortController();
    abortRef.current = controller;
    setAutoqa(prev => prev ? { ...prev, phase: "running", position: 0, examples: [], warnings: 0, summary: null, error: null } : prev);
    try {
      await window.ModelOSIntegrations.generateTrainingData({
        modelId: runModelId,
        fileIds,
        llmProvider: settings.llmProvider,
        llmModel: settings.llmModel,
        llmApiKey: settings.llmApiKey,
        questionsPerChunk: autoqa.questionsPerChunk,
        persist: true,
        versionId: versionId || null,
      }, {
        signal: controller.signal,
        onEvent: (event, data) => {
          if (event === "start") setAutoqa(prev => prev ? { ...prev, totalChunks: data.totalChunks } : prev);
          else if (event === "examples") setAutoqa(prev => prev ? {
            ...prev,
            examples: [...prev.examples, ...data.examples.map(ex => ({ question: ex.question, answer: ex.answer, quality: ex.quality, chunkIndex: data.chunkIndex }))],
          } : prev);
          else if (event === "progress") setAutoqa(prev => prev ? { ...prev, position: data.position, warnings: data.failedChunks } : prev);
          else if (event === "done") setAutoqa(prev => prev ? { ...prev, phase: "done", summary: data } : prev);
          else if (event === "error") setAutoqa(prev => prev ? { ...prev, phase: "error", error: data.message } : prev);
        },
      }, authUser);
      setAutoqa(prev => prev && prev.phase === "running"
        ? { ...prev, phase: "done", summary: { completedChunks: prev.position, totalExamples: prev.examples.length, totalChunks: prev.totalChunks } }
        : prev);
    } catch (err) {
      if (err?.name === "AbortError") {
        setAutoqa(prev => prev ? { ...prev, phase: "done", summary: { ...(prev.summary || {}), aborted: true, totalExamples: prev.examples.length } } : prev);
      } else {
        setAutoqa(prev => prev ? { ...prev, phase: "error", error: err.message || "Generation failed." } : prev);
      }
    } finally {
      abortRef.current = null;
    }
  };

  return { autoqa, openForFile, openPicker, toggleFile, setQuestionsPerChunk, start, stop, close, downloadJsonl };
}

function AutoQaDialog({ state, hasKey, providerLabel, files, filesLoading, contextLabel, onClose, onStart, onStop, onDownload, onOpenStudio, onQuestionsPerChunkChange, onPickFile }) {
  if (!state) return null;
  const pct = state.totalChunks ? Math.min(100, Math.round((state.position / state.totalChunks) * 100)) : 0;
  const preview = (state.examples || []).slice(-40).reverse();
  const selected = state.selectedFiles || [];
  const needsPick = selected.length === 0;
  const selectedChunks = selected.reduce((a, f) => a + (f.chunks || 0), 0);
  return (
    <div className="scrim" role="presentation">
      <div className="modal" role="dialog" aria-modal="true" aria-labelledby="autoqa-title" style={{ maxWidth: 640 }}>
        <div className="card-hd between" style={{ gap: 16 }}>
          <div className="row" style={{ gap: 12, minWidth: 0 }}>
            <div style={{ width: 38, height: 38, borderRadius: "var(--r-sm)", background: "var(--primary-soft)", color: "var(--ink)", display: "flex", alignItems: "center", justifyContent: "center", flex: "none" }}>{I("spark", { style: { width: 19, height: 19 } })}</div>
            <div style={{ minWidth: 0 }}>
              <div id="autoqa-title" className="h3">Generate training data</div>
              <div className="caption" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                {needsPick ? "Pick indexed document(s)" : `${selected.map(f => f.name).join(", ")} - ${selectedChunks} chunks`}
              </div>
            </div>
          </div>
          <button className="icon-btn" onClick={onClose} style={{ width: 32, height: 32 }}>{I("x", { style: { width: 15, height: 15 } })}</button>
        </div>

        {state.phase === "confirm" && (
          <div className="card-pad stack" style={{ gap: 14 }}>
            {onPickFile && (
              <label>
                <span className="field-label">Documents</span>
                {filesLoading
                  ? <div className="caption" style={{ padding: "10px 0" }}><span className="spin" style={{ display: "inline-flex", marginRight: 6 }}>{I("refresh", { style: { width: 13, height: 13 } })}</span>Loading indexed documents...</div>
                  : (files || []).length === 0
                    ? <div className="caption" style={{ padding: "10px 0" }}>No indexed documents found for this bot. Upload and index a document in the Knowledge base first.</div>
                    : <div style={{ maxHeight: 190, overflowY: "auto", border: "1px solid var(--border)", borderRadius: "var(--r-sm)", padding: 4 }}>
                        {(files || []).map(f => {
                          const checked = selected.some(s => s.fileId === f.fileId);
                          return (
                            <label key={f.fileId} className="row" style={{ gap: 9, padding: "7px 8px", cursor: "pointer", borderRadius: 6, background: checked ? "var(--surface-2)" : "transparent" }}>
                              <input type="checkbox" checked={checked} onChange={() => onPickFile(f)} style={{ flex: "none" }} />
                              <span style={{ fontSize: 13, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{f.filename || f.name}</span>
                              <span className="caption" style={{ marginLeft: "auto", flex: "none" }}>{f.chunkCount ?? f.chunks} chunks</span>
                            </label>
                          );
                        })}
                      </div>}
              </label>
            )}
            <div className="stack" style={{ gap: 6 }}>
              {[
                `Mines questions from every indexed chunk of the selected document(s)`,
                `Writes each answer with RAG retrieval over your knowledge base - the same grounding the chatbot and evaluation use`,
                `Appends every pair to the Training Data Studio for review before fine-tuning`,
                `Skips questions that already exist and regenerates until each chunk meets the requested count`,
                `Runs with your ${providerLabel} key`,
              ].map((line, i) => (
                <div key={i} className="row" style={{ gap: 8, alignItems: "flex-start" }}>
                  <span style={{ width: 5, height: 5, borderRadius: 9, background: "var(--ink-3)", marginTop: 7, flex: "none" }} />
                  <span className="caption" style={{ lineHeight: 1.5 }}>{line}</span>
                </div>
              ))}
            </div>
            {contextLabel && <div className="caption" style={{ opacity: .7 }}>{contextLabel}</div>}
            <label>
              <span className="field-label">Questions per chunk</span>
              <select className="input" value={state.questionsPerChunk} onChange={(e) => onQuestionsPerChunkChange(Number(e.target.value))}>
                {Array.from({ length: 15 }, (_, i) => i + 1).map(n => <option key={n} value={n}>{n}</option>)}
              </select>
            </label>
            <div className="row between" style={{ gap: 10 }}>
              <span className="caption">{selectedChunks ? `${selectedChunks + selectedChunks * state.questionsPerChunk} LLM calls - ~${selectedChunks * state.questionsPerChunk} examples` : ""}</span>
              {hasKey
                ? <span className="badge badge-good">{I("checkCircle", { style: { width: 12, height: 12 } })} {providerLabel} key ready</span>
                : <span className="badge badge-bad">{I("alert", { style: { width: 12, height: 12 } })} Add your API key first</span>}
            </div>
          </div>
        )}

        {state.phase === "running" && (
          <div className="card-pad stack" style={{ gap: 12 }}>
            <div style={{ height: 6, borderRadius: 9, background: "var(--surface-3)", overflow: "hidden" }}>
              <div style={{ height: "100%", width: `${pct}%`, background: "var(--primary)", transition: "width .3s" }} />
            </div>
            <div className="row between" style={{ gap: 10 }}>
              <span className="caption">Chunk {Math.min(state.position, state.totalChunks)} of {state.totalChunks} - {state.examples.length} examples{state.warnings ? ` - ${state.warnings} skipped` : ""}</span>
              <span className="spin" style={{ display: "inline-flex", color: "var(--primary)" }}>{I("refresh", { style: { width: 14, height: 14 } })}</span>
            </div>
            {preview.length > 0 && (
              <div style={{ maxHeight: 280, overflowY: "auto", borderTop: "1px solid var(--border)" }}>
                {preview.map((ex, i) => (
                  <div key={i} style={{ padding: "10px 2px", borderBottom: "1px solid var(--border)" }}>
                    <div style={{ fontSize: 13, fontWeight: 600 }}>Q: {ex.question}</div>
                    <div className="caption" style={{ marginTop: 3, whiteSpace: "pre-wrap", lineHeight: 1.5 }}>A: {ex.answer}</div>
                    <div className="caption" style={{ marginTop: 3, opacity: .65 }}>chunk {ex.chunkIndex}{typeof ex.quality === "number" && ex.quality > 0 ? ` - AI score ${ex.quality}` : ""}</div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        {state.phase === "done" && (
          <div className="card-pad stack" style={{ gap: 12 }}>
            <div className={cx("badge", state.warnings ? "badge-info" : "badge-good")} style={{ alignSelf: "flex-start" }}>
              {I("checkCircle", { style: { width: 13, height: 13 } })}
              {state.summary?.aborted
                ? `Stopped early - ${state.examples.length} examples already saved`
                : `${state.examples.length} examples saved to the Training Data Studio${state.warnings ? ` (${state.warnings} chunks skipped)` : ""}`}
            </div>
            {preview.length > 0 && (
              <div style={{ maxHeight: 280, overflowY: "auto", borderTop: "1px solid var(--border)" }}>
                {preview.map((ex, i) => (
                  <div key={i} style={{ padding: "10px 2px", borderBottom: "1px solid var(--border)" }}>
                    <div style={{ fontSize: 13, fontWeight: 600 }}>Q: {ex.question}</div>
                    <div className="caption" style={{ marginTop: 3, whiteSpace: "pre-wrap", lineHeight: 1.5 }}>A: {ex.answer}</div>
                    <div className="caption" style={{ marginTop: 3, opacity: .65 }}>chunk {ex.chunkIndex}{typeof ex.quality === "number" && ex.quality > 0 ? ` - AI score ${ex.quality}` : ""}</div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        {state.phase === "error" && (
          <div className="card-pad stack" style={{ gap: 12 }}>
            <div className="badge badge-bad" style={{ alignSelf: "flex-start" }}>{I("alert", { style: { width: 13, height: 13 } })} Generation failed</div>
            <div className="caption" style={{ lineHeight: 1.5 }}>{state.error}</div>
            {state.examples.length > 0 && <div className="caption">{state.examples.length} examples generated before the failure are already saved.</div>}
          </div>
        )}

        <div className="row" style={{ justifyContent: "flex-end", gap: 10, padding: "14px 18px", borderTop: "1px solid var(--border)", background: "var(--surface-2)" }}>
          {state.phase === "confirm" && (
            <>
              <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
              <button className="btn btn-primary" disabled={!hasKey || needsPick || !selectedChunks} onClick={onStart}>{I("spark", { style: { width: 14, height: 14 } })} Generate</button>
            </>
          )}
          {state.phase === "running" && (
            <button className="btn btn-secondary" onClick={onStop}>{I("x", { style: { width: 13, height: 13 } })} Stop</button>
          )}
          {state.phase === "done" && (
            <>
              <button className="btn btn-secondary" onClick={onClose}>Close</button>
              <button className="btn btn-secondary" disabled={!state.examples.length} onClick={onDownload}>Download .jsonl</button>
              <button className="btn btn-primary" onClick={onOpenStudio}>{I("layers", { style: { width: 14, height: 14 } })} Open Training Data Studio</button>
            </>
          )}
          {state.phase === "error" && (
            <button className="btn btn-primary" onClick={onClose}>Close</button>
          )}
        </div>
      </div>
    </div>
  );
}

window.AutoQaDialog = AutoQaDialog;
window.useAutoQa = useAutoQa;
