/**
 * GET  /api/geoportal/monitor — tile infrastructure status
 * POST /api/geoportal/monitor — trigger actions (rebuild, warm-cache)
 */
import { NextRequest, NextResponse } from "next/server";
import { firePmtilesRebuild } from "@/modules/parcel-sync/services/pmtiles-webhook";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

const TILE_CACHE_INTERNAL = "http://tile-cache:80";
const MARTIN_INTERNAL = "http://martin:3000";
const PMTILES_URL = process.env.NEXT_PUBLIC_PMTILES_URL || "";
// Server-side fetch needs absolute URL — resolve relative paths through tile-cache
const PMTILES_FETCH_URL = PMTILES_URL.startsWith("/")
  ? `${TILE_CACHE_INTERNAL}${PMTILES_URL.replace(/^\/tiles/, "")}`
  : PMTILES_URL;
const N8N_WEBHOOK_URL = process.env.N8N_WEBHOOK_URL || "";

type NginxStatus = {
  activeConnections: number;
  accepts: number;
  handled: number;
  requests: number;
  reading: number;
  writing: number;
  waiting: number;
};

function parseNginxStatus(text: string): NginxStatus {
  const lines = text.trim().split("\n");
  const active = parseInt(lines[0]?.match(/\d+/)?.[0] ?? "0", 10);
  const counts = lines[2]?.trim().split(/\s+/).map(Number) ?? [0, 0, 0];
  const rw = lines[3]?.match(/\d+/g)?.map(Number) ?? [0, 0, 0];
  return {
    activeConnections: active,
    accepts: counts[0] ?? 0,
    handled: counts[1] ?? 0,
    requests: counts[2] ?? 0,
    reading: rw[0] ?? 0,
    writing: rw[1] ?? 0,
    waiting: rw[2] ?? 0,
  };
}

async function fetchWithTimeout(url: string, timeoutMs = 5000): Promise<Response> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(url, { signal: controller.signal, cache: "no-store" });
  } finally {
    clearTimeout(timer);
  }
}

// Sample tile coordinates for cache testing (Romania, z8)
const SAMPLE_TILES = [
  { z: 8, x: 143, y: 91, source: "gis_uats_z8" },
  { z: 17, x: 73640, y: 47720, source: "gis_terenuri" },
];

export async function GET() {
  const result: Record<string, unknown> = {
    timestamp: new Date().toISOString(),
  };

  // 1. Nginx status
  try {
    const res = await fetchWithTimeout(`${TILE_CACHE_INTERNAL}/status`);
    if (res.ok) {
      result.nginx = parseNginxStatus(await res.text());
    } else {
      result.nginx = { error: `HTTP ${res.status}` };
    }
  } catch {
    result.nginx = { error: "tile-cache unreachable" };
  }

  // 2. Martin catalog
  try {
    const res = await fetchWithTimeout(`${MARTIN_INTERNAL}/catalog`);
    if (res.ok) {
      const catalog = await res.json() as { tiles?: Record<string, unknown> };
      const sources = Object.keys(catalog.tiles ?? {});
      result.martin = { status: "ok", sources, sourceCount: sources.length };
    } else {
      result.martin = { error: `HTTP ${res.status}` };
    }
  } catch {
    result.martin = { error: "martin unreachable" };
  }

  // 3. PMTiles info
  if (PMTILES_URL) {
    try {
      const res = await fetchWithTimeout(PMTILES_FETCH_URL, 3000);
      result.pmtiles = {
        url: PMTILES_URL,
        status: res.ok ? "ok" : `HTTP ${res.status}`,
        size: res.headers.get("content-length")
          ? `${(parseInt(res.headers.get("content-length") ?? "0", 10) / 1024 / 1024).toFixed(1)} MB`
          : "unknown",
        lastModified: res.headers.get("last-modified") ?? "unknown",
      };
    } catch {
      result.pmtiles = { url: PMTILES_URL, error: "unreachable" };
    }
  } else {
    result.pmtiles = { status: "not configured" };
  }

  // 4. Cache test — request sample tiles and check X-Cache-Status
  const cacheTests: Record<string, string>[] = [];
  for (const tile of SAMPLE_TILES) {
    try {
      const url = `${TILE_CACHE_INTERNAL}/${tile.source}/${tile.z}/${tile.x}/${tile.y}`;
      const res = await fetchWithTimeout(url, 10000);
      cacheTests.push({
        tile: `${tile.source}/${tile.z}/${tile.x}/${tile.y}`,
        status: `${res.status}`,
        cache: res.headers.get("x-cache-status") ?? "unknown",
      });
    } catch {
      cacheTests.push({
        tile: `${tile.source}/${tile.z}/${tile.x}/${tile.y}`,
        status: "error",
        cache: "unreachable",
      });
    }
  }
  result.cacheTests = cacheTests;

  // 5. Config summary
  result.config = {
    martinUrl: process.env.NEXT_PUBLIC_MARTIN_URL ?? "(not set)",
    pmtilesUrl: PMTILES_URL || "(not set)",
    n8nWebhook: N8N_WEBHOOK_URL ? "configured" : "not set",
  };

  return NextResponse.json(result);
}

async function getPmtilesInfo(): Promise<{ size: string; lastModified: string } | null> {
  if (!PMTILES_URL) return null;
  try {
    const res = await fetchWithTimeout(PMTILES_FETCH_URL, 3000);
    return {
      size: res.headers.get("content-length")
        ? `${(parseInt(res.headers.get("content-length") ?? "0", 10) / 1024 / 1024).toFixed(1)} MB`
        : "unknown",
      lastModified: res.headers.get("last-modified") ?? "unknown",
    };
  } catch {
    return null;
  }
}

export async function POST(request: NextRequest) {
  const body = await request.json() as { action?: string };
  const action = body.action;

  if (action === "rebuild") {
    // Get current PMTiles state before rebuild
    const before = await getPmtilesInfo();
    const result = await firePmtilesRebuild("manual-rebuild");
    if (!result.ok) {
      return NextResponse.json(
        { error: "Webhook PMTiles indisponibil — verifica N8N_WEBHOOK_URL si serviciul pmtiles-webhook" },
        { status: 500 },
      );
    }
    return NextResponse.json({
      ok: true,
      action: "rebuild",
      alreadyRunning: result.alreadyRunning ?? false,
      previousPmtiles: before,
      message: result.alreadyRunning
        ? "Rebuild PMTiles deja in curs. Urmareste PMTiles last-modified."
        : "Rebuild PMTiles pornit. Dureaza ~8 min. Urmareste PMTiles last-modified.",
    });
  }

  if (action === "check-rebuild") {
    // Check if PMTiles was updated since a given timestamp
    const previousLastModified = (body as { previousLastModified?: string }).previousLastModified;
    const current = await getPmtilesInfo();
    const changed = !!current && !!previousLastModified && current.lastModified !== previousLastModified;
    return NextResponse.json({
      ok: true,
      action: "check-rebuild",
      current,
      changed,
      message: changed
        ? `Rebuild finalizat! PMTiles actualizat: ${current?.size}, ${current?.lastModified}`
        : "Rebuild in curs...",
    });
  }

  if (action === "warm-cache") {
    const sources = ["gis_terenuri", "gis_cladiri"];
    let total = 0;
    let hits = 0;
    let misses = 0;
    let errors = 0;
    const promises: Promise<void>[] = [];
    for (const source of sources) {
      for (let x = 9200; x <= 9210; x++) {
        for (let y = 5960; y <= 5970; y++) {
          total++;
          promises.push(
            fetchWithTimeout(`${TILE_CACHE_INTERNAL}/${source}/14/${x}/${y}`, 30000)
              .then((res) => {
                const cache = res.headers.get("x-cache-status") ?? "";
                if (cache === "HIT") hits++;
                else misses++;
              })
              .catch(() => { errors++; }),
          );
        }
      }
    }
    await Promise.all(promises);
    return NextResponse.json({
      ok: true,
      action: "warm-cache",
      total,
      hits,
      misses,
      errors,
      message: `${total} tile-uri procesate: ${hits} HIT, ${misses} MISS (nou incarcate), ${errors} erori`,
    });
  }

  return NextResponse.json({ error: "Unknown action" }, { status: 400 });
}
