import { createFileRoute } from "@tanstack/react-router";
import { createHmac, timingSafeEqual } from "crypto";

// MikroTik agent polls this endpoint to fetch the current allow-list
// (active MAC-bound subscriptions with speed limits and expiry).
//
// Auth: HMAC-SHA256 signature of `${router_id}:${timestamp}` using the router's
// `agent_secret`. Headers: X-Router-Id, X-Timestamp (unix seconds), X-Signature.

function verifyHmac(secret: string, message: string, signatureHex: string): boolean {
  const expected = createHmac("sha256", secret).update(message).digest("hex");
  const a = Buffer.from(signatureHex);
  const b = Buffer.from(expected);
  if (a.length !== b.length) return false;
  return timingSafeEqual(a, b);
}

export const Route = createFileRoute("/api/public/agent/sessions")({
  server: {
    handlers: {
      GET: async ({ request }) => {
        const routerId = request.headers.get("x-router-id");
        const ts = request.headers.get("x-timestamp");
        const sig = request.headers.get("x-signature");

        if (!routerId || !ts || !sig) {
          return new Response("Missing auth headers", { status: 401 });
        }
        const tsNum = Number(ts);
        if (!Number.isFinite(tsNum) || Math.abs(Date.now() / 1000 - tsNum) > 300) {
          return new Response("Timestamp out of range", { status: 401 });
        }

        const { supabaseAdmin } = await import("@/integrations/supabase/client.server");

        const { data: router } = await supabaseAdmin
          .from("routers")
          .select("id, agent_secret")
          .eq("id", routerId)
          .maybeSingle();

        if (!router?.agent_secret) return new Response("Unknown router", { status: 401 });
        if (!verifyHmac(router.agent_secret, `${routerId}:${ts}`, sig)) {
          return new Response("Invalid signature", { status: 401 });
        }

        await supabaseAdmin
          .from("routers")
          .update({ is_online: true, last_seen_at: new Date().toISOString() })
          .eq("id", routerId);

        const nowIso = new Date().toISOString();

        // Expire lapsed subscriptions
        await supabaseAdmin
          .from("subscriptions")
          .update({ status: "expired" })
          .eq("status", "active")
          .lt("expires_at", nowIso);

        const { data: subs } = await supabaseAdmin
          .from("subscriptions")
          .select(
            "id, mac_address, expires_at, plan:plan_id(download_kbps,upload_kbps,device_limit)",
          )
          .eq("status", "active")
          .not("mac_address", "is", null)
          .gt("expires_at", nowIso);

        const sessions = (subs ?? []).map((s: any) => ({
          subscription_id: s.id,
          mac_address: s.mac_address,
          expires_at: s.expires_at,
          download_kbps: s.plan?.download_kbps ?? null,
          upload_kbps: s.plan?.upload_kbps ?? null,
          device_limit: s.plan?.device_limit ?? 1,
        }));

        return new Response(
          JSON.stringify({ ok: true, server_time: nowIso, sessions }),
          { status: 200, headers: { "content-type": "application/json" } },
        );
      },
    },
  },
});
