import { Hono } from "hono";
import { NotificationRoutes } from "@/routes/notification/notification.route";
import { MembershipRoutes } from "@/routes/membership/membership.route";
import { MembersRoutes } from "@/routes/members/members.route";
import { PromptsAndAgentsRoutes } from "@/routes/chatbot/chatbot.route";
import { BookingsRoutes } from "@/routes/bookings/bookings.route";
import { PromoCodesRoutes } from "@/routes/promo-codes/promo-codes.route";
import { PromoCodeCampaignsRoutes } from "@/routes/promo-code-campaigns/promo-code-campaigns.route";
import { HotDealsRoutes } from "@/routes/hot-deals/hot-deals.route";
import { ConsoleSettingsRoutes } from "@/routes/console-settings/console-settings.route";
import { ExportRequestsRoutes } from "@/routes/export-requests/export-requests.route";
import { PromoAccessRolesRoutes } from "@/routes/promo-access-roles/promo-access-roles.route";
import { EDMRoutes } from "@/routes/edm/edm.route";
import { EDMInternalRoutes } from "@/routes/edm/edm-internal.route";
import { ResortRoutes } from "@/routes/resorts/resorts.route";
import { AvailabilityRoutes } from "@/routes/availability/availability.route";
import { MemberOfferRoutes } from "@/routes/member-offers/member-offers.route";
import { TravelRulesRoutes } from "@/routes/travel-rules/travel-rules.route";
import { DashboardRoutes } from "@/routes/dashboard/dashboard.route";
import { DashboardPublicRoutes } from "@/routes/dashboard/dashboard-public.route";
import { WorkflowRoutes } from "@/routes/workflows/workflows.route";
import { ViewpointRoutes } from "@/routes/viewpoint/viewpoint.route";
import { AccountDeletionRoutes } from "@/routes/account-deletion/account-deletion.route";
import { EventAnalyticsRoutes } from "@/routes/event-analytics/event-analytics.route";
import { UpdotProxyRoutes } from "./updot-proxy";
import { AdminRoutes } from "./v1/routes.admin";
import { PointsTransferRoutes } from "@/routes/points-transfer/points-transfer.route";
import { activityLogMiddleware } from "@/middlewares/activity-log";
import {
  listPublicHotDealsHandler,
  listPublicHotDealsListHandler,
  getPublicHotDealsDetailHandler,
  listPublicHotDealsRegionsHandler,
  listPublicTravelRulesHandler,
} from "@/controllers/admin/hot-deals/hot-deals.controller";


import { execSync } from "child_process";
import { readFileSync } from "fs";

export const AppRoutes = new Hono();

const pkg = JSON.parse(readFileSync(new URL("../../../package.json", import.meta.url), "utf-8"));

let gitInfo = { branch: "unknown", commit: "unknown" };
try {
  gitInfo.branch = execSync("git rev-parse --abbrev-ref HEAD").toString().trim();
  gitInfo.commit = execSync("git rev-parse --short HEAD").toString().trim();
} catch (e) {
  // git not available or not a git repo
}

AppRoutes.get("/health", (c) =>
  c.json({
    status: "ok",
    version: pkg.version,
    timestamp: new Date().toISOString(),
    git: gitInfo,
  })
);

AppRoutes.use("*", activityLogMiddleware);


AppRoutes.route("/v1/admin-console/notifications", NotificationRoutes);

AppRoutes.route("/v1/admin/memberships", MembershipRoutes);

// Native member APIs (member DB + Viewpoint). Anything not listed here still
// falls through to the Updot proxy below.
AppRoutes.route("/v1/admin-console/members", MembersRoutes);

AppRoutes.route("/v1/admin-console/chatbot", PromptsAndAgentsRoutes);

AppRoutes.route("/v1/admin-console/bookings", BookingsRoutes);

AppRoutes.route("/v1/admin-console/promo-codes", PromoCodesRoutes);

AppRoutes.route("/v1/admin-console/promo-code-campaigns", PromoCodeCampaignsRoutes);

AppRoutes.route("/v1/admin-console/hot-deals", HotDealsRoutes);
AppRoutes.route("/v1/admin-console/console-settings", ConsoleSettingsRoutes);
AppRoutes.route("/v1/admin-console/export-requests", ExportRequestsRoutes);
AppRoutes.route("/v1/admin-console/promo-access-roles", PromoAccessRolesRoutes);

AppRoutes.route("/v1/admin-console/edm", EDMRoutes);
// Service-to-service: the SMTP worker fetches template source to render itself.
// Deliberately outside /v1/admin-console — see the route file.
AppRoutes.route("/v1/internal/edm", EDMInternalRoutes);

AppRoutes.route("/v1/admin-console/resorts", ResortRoutes);

AppRoutes.route("/v1/admin-console/points-transfer", PointsTransferRoutes);

AppRoutes.route("/v1/availability", AvailabilityRoutes);

AppRoutes.route("/v1/admin-console/member-offers", MemberOfferRoutes);
AppRoutes.route("/v1/admin-console/travel-rules", TravelRulesRoutes);
AppRoutes.route("/v1/admin-console/dashboards", DashboardRoutes);
// Session-free public share-link viewer; the opaque token is the credential.
AppRoutes.route("/v1/public/dashboards", DashboardPublicRoutes);
AppRoutes.route("/v1/admin-console/workflows", WorkflowRoutes);
// Manually imported Viewpoint reports (bookings by source, member contacts).
AppRoutes.route("/v1/admin-console/viewpoint", ViewpointRoutes);
// Retiring a member account: Viewpoint status write, mirrored into the member DB.
// Super admin only, enforced in the handlers.
AppRoutes.route("/v1/admin-console/account-deletion", AccountDeletionRoutes);

// Booking events tracked in the `event-tracking` Firestore database.
AppRoutes.route("/v1/admin-console/event-analytics", EventAnalyticsRoutes);

import { withConsoleUserSession } from "@/middlewares/withConsoleUserSession";
import { GetKcgmSsoToken } from "@/controllers/admin/kcgm/kcgm-sso.controller";

AppRoutes.use("/v1/admin-console/kcgm/*", withConsoleUserSession());

// Short-lived hand-off token so a console user who already has the "kcgm"
// feature role can be signed into the separate KCGM Dashboard app without
// re-entering credentials there.
AppRoutes.get("/v1/admin-console/kcgm/sso-token", GetKcgmSsoToken);

AppRoutes.get("/v1/public/hot-deals", listPublicHotDealsHandler);
AppRoutes.get("/v1/public/hot-deals/list", listPublicHotDealsListHandler);
AppRoutes.get("/v1/public/hot-deals/detail/:id", getPublicHotDealsDetailHandler);
AppRoutes.get("/v1/public/hot-deals/regions", listPublicHotDealsRegionsHandler);
AppRoutes.get("/v1/public/travel-rules", listPublicTravelRulesHandler);

AppRoutes.route("/v1", UpdotProxyRoutes);

AppRoutes.route("/v2", AdminRoutes);

// ── KCGM API Proxy ──────────────────────────────────────────────────────────
// Forwards browser requests from the admin console iframe to the KCGM API
// running locally on port 4000. No separate domain required.
const KCGM_API_URL = process.env.KCGM_API_URL || "http://127.0.0.1:4000";

AppRoutes.all("/v1/admin-console/kcgm-proxy/*", async (c) => {
  const path = c.req.path.replace("/v1/admin-console/kcgm-proxy", "");
  const search = c.req.raw.url.includes("?") ? "?" + c.req.raw.url.split("?")[1] : "";
  const target = `${KCGM_API_URL}${path}${search}`;

  const headers = new Headers();
  c.req.raw.headers.forEach((value, key) => {
    if (!["host", "origin", "referer", "content-length", "transfer-encoding"].includes(key.toLowerCase())) {
      headers.set(key, value);
    }
  });

  let response;
  try {
    response = await fetch(target, {
      method: c.req.method,
      headers,
      body: ["GET", "HEAD"].includes(c.req.method) ? undefined : c.req.raw.body,
      // @ts-ignore Node.js fetch requires duplex: 'half' when streaming a body
      duplex: "half",
    });
  } catch (error: any) {
    console.error(`KCGM proxy fetch failed for ${target}:`, error.message, 'Cause:', error.cause);
    return c.json({ error: "The KCGM backend API is currently offline. " + error.message, cause: error.cause?.message || String(error.cause) }, 502);
  }

  const resHeaders = new Headers();
  response.headers.forEach((value, key) => {
    if (!["content-encoding", "transfer-encoding"].includes(key.toLowerCase())) {
      resHeaders.set(key, value);
    }
  });
  resHeaders.set("Access-Control-Allow-Origin", c.req.header("origin") || "*");
  resHeaders.set("Access-Control-Allow-Credentials", "true");

  return new Response(response.body, {
    status: response.status,
    headers: resHeaders,
  });
});
