import crypto from "crypto";
import { Router, Request, Response } from "express";
import { getAgentStatus, io } from "../socket";
import { captureScreenshot, click, disconnectAgent, doubleClick, doubleClickCurrent, pressKey, typeText } from "../services/windowsAgentBridge";
import { runExistingPatientOpenDental, runExistingPatientOpenDentalRatioTest } from "../services/typeAgentRunner";
import { storage } from "../storage";

const router = Router();

// GET /api/type-agent/status
// Current Windows Agent (DentalAgent.exe) connection status, for the initial page load —
// live updates after that come over the "type-agent:status" socket.io event.
router.get("/status", (_req: Request, res: Response) => {
  res.json(getAgentStatus());
});

// POST /api/type-agent/disconnect
// Forcibly disconnects a connected agent by IP — the "x" on the Type Agent page.
router.post("/disconnect", (req: Request, res: Response) => {
  const { ip } = req.body ?? {};
  if (!ip) {
    res.status(400).json({ error: "ip is required" });
    return;
  }
  try {
    disconnectAgent(ip);
    res.json({ success: true });
  } catch (err) {
    res.status(404).json({ error: err instanceof Error ? err.message : "Agent not found" });
  }
});

// POST /api/type-agent/test-command
// Sends a single low-level command (screenshot/click/double_click/type/key) straight to a
// connected Windows Agent. Exists to verify the command bridge before the AI-driven step
// orchestration is wired in — not meant to be called from the Type Agent UI directly.
router.post("/test-command", async (req: Request, res: Response) => {
  const { type, x, y, text, key, ip } = req.body ?? {};
  try {
    let result;
    switch (type) {
      case "screenshot":
        result = await captureScreenshot(ip);
        break;
      case "click":
        result = await click(Number(x), Number(y), ip);
        break;
      case "double_click":
        result = await doubleClick(Number(x), Number(y), ip);
        break;
      case "double_click_current":
        result = await doubleClickCurrent(ip);
        break;
      case "type":
        result = await typeText(String(text ?? ""), ip);
        break;
      case "key":
        result = await pressKey(String(key ?? ""), ip);
        break;
      default:
        res.status(400).json({ error: "Unknown command type" });
        return;
    }
    res.json({ success: true, result });
  } catch (err) {
    res.status(500).json({ error: err instanceof Error ? err.message : "Command failed" });
  }
});

// POST /api/type-agent/run
// Kicks off a real step-by-step run against a connected Windows Agent. Only Open Dental /
// existing-patient is wired up so far — everything else the Type Agent page still shows as
// a preview only. Responds immediately with a runId; progress streams over the
// "type-agent:run:<runId>" socket.io event so the browser doesn't have to hold the request
// open for what can be a slow, multi-step, vision-driven sequence.
router.post("/run", async (req: Request, res: Response) => {
  const userId = req.user?.id;
  if (!userId) {
    res.status(401).json({ error: "Unauthorized" });
    return;
  }

  const { software, action, ip, patientId, ratioTest } = req.body ?? {};
  if (software !== "open-dental" || action !== "existing-patient") {
    res.status(400).json({ error: "This software/action combination isn't automated yet." });
    return;
  }
  if (!ip) {
    res.status(400).json({ error: "ip is required" });
    return;
  }

  const patient = await storage.getPatient(Number(patientId));
  if (!patient?.lastName || !patient?.firstName) {
    res.status(400).json({ error: "Patient not found or missing a first/last name" });
    return;
  }

  const runId = crypto.randomUUID();
  res.json({ runId });

  const runFn = ratioTest ? runExistingPatientOpenDentalRatioTest : runExistingPatientOpenDental;
  runFn(userId, runId, ip, patient.lastName, patient.firstName, (index, total, label, status, error) => {
    io?.emit(`type-agent:run:${runId}`, { index, total, label, status, error });
  }).catch((err) => {
    console.error("[type-agent/run] failed:", err);
  });
});

export default router;
