import { Router } from "express";
import type { AppServices } from "../serverContext";
import { ApiError, created, ok } from "../utils/http";

const PREFIX = "/api/accounting-agent/v1";

export function buildAccountingAgentRouter(services: AppServices): Router {
  const router = Router();
  const runtime = services.runtimeAdapter;

  router.post(`${PREFIX}/runs/start`, (req, res, next) => {
    try {
      const body = (req.body ?? {}) as Record<string, unknown>;
      const run = runtime.startRun({
        sessionId: body.sessionId ? String(body.sessionId) : undefined,
        initiator: body.initiator ? String(body.initiator) : "operator",
        source: body.source ? String(body.source) : "gui",
        metadata: (body.metadata ?? {}) as Record<string, unknown>,
        idempotencyKey: body.idempotencyKey ? String(body.idempotencyKey) : undefined
      });
      created(res, {
        ok: true,
        sessionId: run.sessionId,
        runId: run.runId,
        status: run.status,
        run
      });
    } catch (error) {
      next(error);
    }
  });

  router.post(`${PREFIX}/runs/finish`, (req, res, next) => {
    try {
      const body = (req.body ?? {}) as Record<string, unknown>;
      const status = String(body.status ?? "DONE") as "DONE" | "ERROR" | "CANCELLED";
      if (!["DONE", "ERROR", "CANCELLED"].includes(status)) {
        throw new ApiError("INVALID_STATUS", `Invalid finish status: ${status}`, 400);
      }
      const run = runtime.finishRun({
        runId: String(body.runId ?? ""),
        status,
        source: body.source ? String(body.source) : "gui",
        reason: body.reason ? String(body.reason) : undefined,
        metadata: (body.metadata ?? {}) as Record<string, unknown>,
        idempotencyKey: body.idempotencyKey ? String(body.idempotencyKey) : undefined
      });
      ok(res, {
        ok: true,
        run
      });
    } catch (error) {
      next(error);
    }
  });

  router.get(`${PREFIX}/runs`, (_req, res) => {
    ok(res, {
      ok: true,
      items: runtime.listRuns()
    });
  });

  router.get(`${PREFIX}/runs/:runId`, (req, res, next) => {
    try {
      const run = runtime.getRun(String(req.params.runId));
      if (!run) {
        throw new ApiError("RUN_NOT_FOUND", `Run not found: ${req.params.runId}`, 404);
      }
      ok(res, {
        ok: true,
        run
      });
    } catch (error) {
      next(error);
    }
  });

  router.post(`${PREFIX}/tasks/enqueue`, (req, res, next) => {
    try {
      const body = (req.body ?? {}) as Record<string, unknown>;
      const task = runtime.enqueueTask({
        runId: String(body.runId ?? ""),
        payload: (body.payload ?? {}) as Record<string, unknown>,
        source: body.source ? String(body.source) : "gui",
        idempotencyKey: body.idempotencyKey ? String(body.idempotencyKey) : undefined
      });
      created(res, {
        ok: true,
        task
      });
    } catch (error) {
      next(error);
    }
  });

  router.post(`${PREFIX}/tasks/claim`, (_req, res) => {
    const task = runtime.claimTask();
    ok(res, {
      ok: true,
      task
    });
  });

  router.post(`${PREFIX}/tasks/:taskId/complete`, (req, res, next) => {
    try {
      const body = (req.body ?? {}) as Record<string, unknown>;
      const task = runtime.completeTask({
        taskId: String(req.params.taskId),
        result: (body.result ?? {}) as Record<string, unknown>,
        source: body.source ? String(body.source) : "worker",
        idempotencyKey: body.idempotencyKey ? String(body.idempotencyKey) : undefined
      });
      ok(res, {
        ok: true,
        task
      });
    } catch (error) {
      next(error);
    }
  });

  router.post(`${PREFIX}/tasks/:taskId/error`, (req, res, next) => {
    try {
      const body = (req.body ?? {}) as Record<string, unknown>;
      const task = runtime.failTask({
        taskId: String(req.params.taskId),
        error: {
          code: String(body.code ?? "TASK_ERROR"),
          message: String(body.message ?? "Task failed"),
          details: body.details
        },
        source: body.source ? String(body.source) : "worker",
        idempotencyKey: body.idempotencyKey ? String(body.idempotencyKey) : undefined
      });
      ok(res, {
        ok: true,
        task
      });
    } catch (error) {
      next(error);
    }
  });

  router.get(`${PREFIX}/results`, (_req, res) => {
    ok(res, {
      ok: true,
      items: runtime.getResults()
    });
  });

  router.get(`${PREFIX}/trace/run/:runId`, (req, res) => {
    ok(res, {
      ok: true,
      items: runtime.getRunTrace(String(req.params.runId))
    });
  });

  router.get(`${PREFIX}/health`, (_req, res) => {
    ok(res, runtime.health());
  });

  return router;
}
