import { Router, Request, Response } from "express";
import { requireAuth } from "../middleware/auth";
import {
  supervisorConfig,
  getSupervisorHealth,
  getRagStatus,
  recommendTask,
  dispatchChat,
  buildBridgeDeepLink,
  ingestRagTexts,
  ingestProjectDocs,
} from "../services/supervisorAiService";
import {
  collectOperationalSnapshot,
  learnAndRecommend,
  recordFeedback,
  evolveProposal,
  buildInsightsDocument,
  generateProposals,
} from "../services/aiLearningService";

const router = Router();

router.get("/status", requireAuth, async (_req: Request, res: Response) => {
  const cfg = supervisorConfig();
  const [health, rag] = await Promise.all([getSupervisorHealth(), getRagStatus()]);
  res.json({
    success: true,
    config: { hasToken: cfg.hasToken, projectId: cfg.projectId, bridgeUrl: cfg.bridgeUrl },
    supervisor: {
      online: health.ok,
      status: health.data?.status || (health.ok ? "ok" : "offline"),
    },
    rag: rag.ok ? rag.data : { error: "rag_unavailable" },
  });
});

router.get("/snapshot", requireAuth, async (_req: Request, res: Response) => {
  const snapshot = await collectOperationalSnapshot();
  res.json({ success: true, snapshot });
});

router.post("/learn", requireAuth, async (_req: Request, res: Response) => {
  const result = await learnAndRecommend();
  res.json({ success: true, ...result });
});

router.post("/evolve", requireAuth, async (req: Request, res: Response) => {
  const proposalId = String(req.body?.proposalId || "").trim();
  if (!proposalId) {
    return res.status(400).json({ success: false, error: "proposalId requerido" });
  }
  try {
    const evolved = await evolveProposal(proposalId);
    res.json({ success: true, ...evolved });
  } catch (e) {
    res.status(404).json({ success: false, error: (e as Error).message });
  }
});

router.post("/feedback", requireAuth, async (req: Request, res: Response) => {
  const proposalId = String(req.body?.proposalId || "").trim();
  const rating = Number(req.body?.rating);
  if (!proposalId || (rating !== 1 && rating !== -1)) {
    return res.status(400).json({ success: false, error: "proposalId y rating (1|-1) requeridos" });
  }
  const note = req.body?.note ? String(req.body.note) : undefined;
  const entries = await recordFeedback(proposalId, rating as 1 | -1, note);
  res.json({ success: true, count: entries.length });
});

router.post("/ingest-insights", requireAuth, async (_req: Request, res: Response) => {
  const snapshot = await collectOperationalSnapshot();
  const proposals = await generateProposals(snapshot);
  const doc = await buildInsightsDocument(snapshot, proposals);
  const ingested = await ingestRagTexts([
    { text: doc, id: `captajaus-ops-${Date.now()}`, type: "operational_insight" },
  ]);
  if (!ingested.ok) {
    return res.status(502).json({ success: false, error: "rag_ingest_failed" });
  }
  res.json({ success: true, chars: doc.length, rag: ingested.data });
});

router.post("/ingest-project", requireAuth, async (_req: Request, res: Response) => {
  const result = await ingestProjectDocs();
  if (!result.ok) {
    return res.status(502).json({ success: false, error: "ingest_project_failed" });
  }
  res.json({ success: true, result: result.data });
});

router.post("/recommend", requireAuth, async (req: Request, res: Response) => {
  const task = String(req.body?.task || "").trim();
  if (!task) {
    return res.status(400).json({ success: false, error: "task requerido" });
  }
  const agent = req.body?.agent ? String(req.body.agent) : undefined;
  const rec = await recommendTask(task, agent);
  if (!rec.ok || !rec.data) {
    return res.status(rec.status === 401 ? 503 : 502).json({
      success: false,
      error: "supervisor_no_disponible",
      bridgeUrl: supervisorConfig().bridgeUrl,
    });
  }
  const data = rec.data as Record<string, unknown>;
  const primary = data.primary_match as Record<string, unknown> | undefined;
  const advancedPrompt = [
    "MODO REVISIÓN — no aplicar cambios sin confirmación del operador.",
    primary ? `Agente: ${primary.agent} · ${primary.title}` : "",
    "",
    task,
  ]
    .filter(Boolean)
    .join("\n");
  res.json({
    success: true,
    recommendation: data,
    primary,
    advancedPrompt,
    bridgeUrl: buildBridgeDeepLink(advancedPrompt),
  });
});

router.post("/dispatch", requireAuth, async (req: Request, res: Response) => {
  const message = String(req.body?.message || "").trim();
  const agent = String(req.body?.agent || "ops");
  if (!message) {
    return res.status(400).json({ success: false, error: "message requerido" });
  }
  const result = await dispatchChat(message, agent);
  if (!result.ok) {
    return res.status(502).json({
      success: false,
      error: "dispatch_failed",
      bridgeUrl: buildBridgeDeepLink(message),
    });
  }
  res.json({ success: true, result: result.data });
});

export default router;
