import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import {
  computeReputationScore,
  reputationScoreWithUptime,
  reputationTier,
} from "@/lib/marketplace-reputation";

/**
 * Heartbeat interval and uptime heuristic constants.
 * CLI sends heartbeat every 30s; 2x interval is our staleness threshold.
 */
const HEARTBEAT_INTERVAL_MS = 30_000;
const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;

/**
 * Compute an approximate 30-day uptime percentage from device record.
 * Uses the same heuristic as the /api/internal/marketplace/uptime endpoint.
 */
function computeUptimePct(device: {
  status: string;
  lastSeen: Date;
  createdAt: Date;
}): number {
  const now = Date.now();
  const createdAtMs = device.createdAt.getTime();
  const lastSeenMs = device.lastSeen.getTime();
  const windowMs = Math.min(THIRTY_DAYS_MS, now - createdAtMs);

  if (windowMs <= 0) return 100;

  const isCurrentlyOnline =
    device.status === "online" && now - lastSeenMs < HEARTBEAT_INTERVAL_MS * 2;

  if (isCurrentlyOnline) {
    const ageRatio = Math.min(1.0, (now - createdAtMs) / THIRTY_DAYS_MS);
    return Math.min(100, Math.max(80, Math.round(ageRatio * 100)));
  }

  const offlineDurationMs = now - lastSeenMs;
  const onlineMs = Math.max(0, windowMs - offlineDurationMs);
  return Math.max(0, Math.min(100, Math.round((onlineMs / windowMs) * 100)));
}

/**
 * GET /api/marketplace/nodes
 *
 * Returns devices that have opted into the marketplace (marketplaceEnabled=true,
 * status=online). Used by the marketplace router and buyer discovery.
 * Each node includes reputation_score (0-100) blended with 30-day uptime,
 * reputation_tier (Unverified/Standard/Verified/Elite), and uptime_pct.
 * Optional query: ?model=llama3.2:8b to filter by model availability.
 */
export async function GET(req: NextRequest) {
  try {
    const { searchParams } = new URL(req.url);
    const modelFilter = searchParams.get("model");

    const devices = await db.device.findMany({
      where: {
        marketplaceEnabled: true,
        status: "online",
      },
      orderBy: { lastSeen: "desc" },
    });

    let nodes = devices.map((d) => {
      const models = JSON.parse(d.models || "[]") as string[];
      const baseScore = computeReputationScore(d.status, d.latencyMs, d.lastSeen);
      const uptimePct = computeUptimePct(d);
      const reputation_score = reputationScoreWithUptime(baseScore, uptimePct);
      const reputation_tier = reputationTier(reputation_score);
      return {
        id: d.id,
        name: d.name,
        tunnel_url: d.tunnelUrl,
        models,
        hardware: d.hardware,
        status: d.status,
        last_seen: d.lastSeen,
        latency_ms: d.latencyMs,
        price_cents_per_hour: d.marketplacePriceCents ?? null,
        reputation_score,
        reputation_tier,
        uptime_pct: uptimePct,
      };
    });

    if (modelFilter) {
      nodes = nodes.filter((n) =>
        n.models.some(
          (m) => m === modelFilter || m.startsWith(`${modelFilter}:`),
        ),
      );
    }

    return NextResponse.json({ nodes });
  } catch {
    return NextResponse.json(
      { error: "Failed to list marketplace nodes" },
      { status: 500 },
    );
  }
}
