import { Hono } from "hono";
import { createMiddleware } from "hono/factory";
import { logger as honoLogger } from "hono/logger";
import type { Logger } from "pino";
import type { JiraClientImpl } from "@/jira/client.js";
import type { CursorCloudClient } from "@/agent/cursor-cloud-client.js";
import type { FixPipeline } from "@/pipeline/fix-pipeline.js";
import type { RepoRegistry } from "@/repo/registry.js";
import type { RepoSelector } from "@/repo/selector.js";
import type { IJobQueue } from "@/types/index.js";
import type { DatadogLogsClient } from "@/datadog/client.js";
import type { SlackNotifier } from "@/slack/client.js";
import type { JiraPoller } from "@/poller/jira-poller.js";
import type { JiraTicketReviewPoller } from "@/poller/jira-ticket-review-poller.js";
import type { PrCommentPoller } from "@/poller/pr-comment-poller.js";
import type { PrMentionPoller } from "@/poller/pr-mention-poller.js";
import type { SlackMentionPoller } from "@/poller/slack-mention-poller.js";
import type { DailyReportScheduler } from "@/scheduler/daily-report.js";
import { createHealthRoutes } from "./routes/health.js";
import { createWebhookRoutes } from "./routes/webhook.js";
import { createDebugRoutes } from "./routes/debug.js";

interface AppDeps {
  queue: IJobQueue;
  jiraClient: JiraClientImpl;
  cursorCloudClient: CursorCloudClient;
  pipeline: FixPipeline;
  repoRegistry: RepoRegistry;
  repoSelector: RepoSelector;
  getGitHubToken: () => Promise<string>;
  jiraDomain: string;
  workdirPath: string;
  githubBotUser: string;
  logger: Logger;
  datadogLogsClient: DatadogLogsClient | null;
  slackNotifier: SlackNotifier | undefined;
  /** Bot token for debug Slack API calls (e.g. usergroups list). */
  slackBotToken: string | undefined;
  /** Effective channel for daily digest: `SLACK_DAILY_REPORT_CHANNEL_ID` or default `SLACK_CHANNEL_ID`. */
  slackDailyReportChannelId: string | undefined;
  squadScope: string[];
  botEmail: string;
  /**
   * Live poller / scheduler instances exposed for manual on-demand triggering
   * via the debug API. They stay constructed even when their interval is
   * gated off (e.g. dev mode forces all of them off).
   */
  jiraPoller: JiraPoller;
  ticketReviewPoller: JiraTicketReviewPoller;
  prCommentPoller: PrCommentPoller;
  prMentionPoller: PrMentionPoller;
  slackMentionPoller: SlackMentionPoller | undefined;
  dailyReportScheduler: DailyReportScheduler | undefined;
  /** Returns false until boot prewarm completes; gates /health to 503. */
  isReady?: () => boolean;
}

export function createApp(deps: AppDeps): Hono {
  const app = new Hono();

  app.use(
    "*",
    createMiddleware(async (c, next) => {
      if (c.req.path.endsWith("/health")) return next();
      const fn = honoLogger();
      return fn(c, next);
    }),
  );

  app.onError((err, c) => {
    deps.logger.error({ error: err.message, stack: err.stack }, "Unhandled error");
    return c.json({ error: "Internal server error" }, 500);
  });

  app.route("/hu-agent", createHealthRoutes(deps.isReady));
  app.route("/hu-agent", createWebhookRoutes(deps));
  app.route("/hu-agent", createDebugRoutes(deps));

  return app;
}
