/**
 * POST /api/eterra/sync-all-counties
 *
 * Starts a background sync for ALL counties in the database (entire Romania).
 * Iterates counties sequentially, running county-sync logic for each.
 * Returns immediately with jobId — progress via /api/eterra/progress.
 *
 * Body: {} (no params needed)
 */

import { prisma } from "@/core/storage/prisma";
import {
  setProgress,
  clearProgress,
  type SyncProgress,
} from "@/modules/parcel-sync/services/progress-store";
import { syncLayer } from "@/modules/parcel-sync/services/sync-service";
import { enrichFeatures } from "@/modules/parcel-sync/services/enrich-service";
import { EterraClient } from "@/modules/parcel-sync/services/eterra-client";
import { checkEterraHealthNow } from "@/modules/parcel-sync/services/eterra-health";
import { createAppNotification } from "@/core/notifications/app-notifications";
import { getSessionCredentials } from "@/modules/parcel-sync/services/session-store";
import { firePmtilesRebuild } from "@/modules/parcel-sync/services/pmtiles-webhook";

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

/* Concurrency guard — blocks both this and single county sync */
const g = globalThis as {
  __countySyncRunning?: string;
  __allCountiesSyncRunning?: boolean;
};

export async function POST() {
  const session = getSessionCredentials();
  const username = String(session?.username || process.env.ETERRA_USERNAME || "").trim();
  const password = String(session?.password || process.env.ETERRA_PASSWORD || "").trim();
  if (!username || !password) {
    return Response.json(
      { error: "Credentiale lipsa — conecteaza-te la eTerra mai intai." },
      { status: 401 },
    );
  }

  if (g.__allCountiesSyncRunning) {
    return Response.json(
      { error: "Sync All Romania deja in curs" },
      { status: 409 },
    );
  }

  if (g.__countySyncRunning) {
    return Response.json(
      { error: `Sync judet deja in curs: ${g.__countySyncRunning}` },
      { status: 409 },
    );
  }

  const jobId = crypto.randomUUID();
  g.__allCountiesSyncRunning = true;

  setProgress({
    jobId,
    downloaded: 0,
    total: 100,
    status: "running",
    phase: "Pregatire sync Romania...",
  });

  void runAllCountiesSync(jobId, username, password);

  return Response.json(
    { jobId, message: "Sync All Romania pornit" },
    { status: 202 },
  );
}

async function runAllCountiesSync(
  jobId: string,
  username: string,
  password: string,
) {
  const push = (p: Partial<SyncProgress>) =>
    setProgress({
      jobId,
      downloaded: 0,
      total: 100,
      status: "running",
      ...p,
    } as SyncProgress);

  try {
    // Health check
    const health = await checkEterraHealthNow();
    if (!health.available) {
      setProgress({
        jobId,
        downloaded: 0,
        total: 100,
        status: "error",
        phase: "eTerra indisponibil",
        message: health.message ?? "maintenance",
      });
      g.__allCountiesSyncRunning = false;
      setTimeout(() => clearProgress(jobId), 3_600_000);
      return;
    }

    // Get all distinct counties, ordered alphabetically
    const countyRows = await prisma.gisUat.groupBy({
      by: ["county"],
      where: { county: { not: null } },
      _count: true,
      orderBy: { county: "asc" },
    });

    const counties = countyRows
      .map((r) => r.county)
      .filter((c): c is string => c != null);

    if (counties.length === 0) {
      setProgress({
        jobId,
        downloaded: 100,
        total: 100,
        status: "done",
        phase: "Niciun judet gasit in DB",
      });
      g.__allCountiesSyncRunning = false;
      setTimeout(() => clearProgress(jobId), 3_600_000);
      return;
    }

    push({ phase: `0/${counties.length} judete — pornire...` });

    const countyResults: Array<{
      county: string;
      uatCount: number;
      errors: number;
      duration: number;
    }> = [];
    let totalErrors = 0;
    let totalUats = 0;

    for (let ci = 0; ci < counties.length; ci++) {
      const county = counties[ci]!;
      g.__countySyncRunning = county;

      // Get UATs for this county
      const uats = await prisma.$queryRawUnsafe<
        Array<{
          siruta: string;
          name: string | null;
          total: number;
          enriched: number;
        }>
      >(
        `SELECT u.siruta, u.name,
           COALESCE(f.total, 0)::int as total,
           COALESCE(f.enriched, 0)::int as enriched
         FROM "GisUat" u
         LEFT JOIN (
           SELECT siruta, COUNT(*)::int as total,
             COUNT(*) FILTER (WHERE "enrichedAt" IS NOT NULL)::int as enriched
           FROM "GisFeature"
           WHERE "layerId" IN ('TERENURI_ACTIVE','CLADIRI_ACTIVE') AND "objectId" > 0
           GROUP BY siruta
         ) f ON u.siruta = f.siruta
         WHERE u.county = $1
         ORDER BY COALESCE(f.total, 0) DESC`,
        county,
      );

      if (uats.length === 0) {
        countyResults.push({ county, uatCount: 0, errors: 0, duration: 0 });
        continue;
      }

      const countyStart = Date.now();
      let countyErrors = 0;

      for (let i = 0; i < uats.length; i++) {
        const uat = uats[i]!;
        const uatName = uat.name ?? uat.siruta;
        const ratio = uat.total > 0 ? uat.enriched / uat.total : 0;
        const isMagic = ratio > 0.3;
        const mode = isMagic ? "magic" : "base";

        // Progress: county level + UAT level — update before starting UAT
        const countyPct = ci / counties.length;
        const uatPct = i / uats.length;
        const overallPct = Math.round((countyPct + uatPct / counties.length) * 100);

        push({
          downloaded: overallPct,
          total: 100,
          phase: `[${ci + 1}/${counties.length}] ${county} — [${i + 1}/${uats.length}] ${uatName} (${mode})`,
          note: countyResults.length > 0
            ? `Ultimul judet: ${countyResults[countyResults.length - 1]!.county} (${countyResults[countyResults.length - 1]!.uatCount} UAT, ${countyResults[countyResults.length - 1]!.errors} err)`
            : undefined,
        });

        try {
          await syncLayer(username, password, uat.siruta, "TERENURI_ACTIVE", { uatName, jobId, isSubStep: true });
          await syncLayer(username, password, uat.siruta, "CLADIRI_ACTIVE", { uatName, jobId, isSubStep: true });

          // LIMITE_INTRAV_DYNAMIC — best effort
          try {
            await syncLayer(username, password, uat.siruta, "LIMITE_INTRAV_DYNAMIC", { uatName, jobId, isSubStep: true });
          } catch { /* skip */ }

          // Enrichment for magic mode
          if (isMagic) {
            try {
              const client = await EterraClient.create(username, password, { timeoutMs: 120_000 });
              await enrichFeatures(client, uat.siruta);
            } catch {
              // Enrichment failure is non-fatal
            }
          }
        } catch (err) {
          countyErrors++;
          const msg = err instanceof Error ? err.message : "Unknown";
          console.error(`[sync-all] ${county}/${uatName}: ${msg}`);
        }

        // Update progress AFTER UAT completion
        const completedUatPct = (i + 1) / uats.length;
        const completedOverallPct = Math.round((countyPct + completedUatPct / counties.length) * 100);
        push({
          downloaded: completedOverallPct,
          total: 100,
          phase: `[${ci + 1}/${counties.length}] ${county} — [${i + 1}/${uats.length}] ${uatName} finalizat`,
        });
      }

      const dur = Math.round((Date.now() - countyStart) / 1000);
      countyResults.push({ county, uatCount: uats.length, errors: countyErrors, duration: dur });
      totalErrors += countyErrors;
      totalUats += uats.length;

      console.log(
        `[sync-all] ${ci + 1}/${counties.length} ${county}: ${uats.length} UAT, ${countyErrors} err, ${dur}s`,
      );
    }

    const totalDur = countyResults.reduce((s, r) => s + r.duration, 0);
    const summary = `${counties.length} judete, ${totalUats} UAT-uri, ${totalErrors} erori, ${formatDuration(totalDur)}`;

    setProgress({
      jobId,
      downloaded: 100,
      total: 100,
      status: totalErrors > 0 && totalErrors === totalUats ? "error" : "done",
      phase: "Sync Romania finalizat",
      message: summary,
    });

    await createAppNotification({
      type: totalErrors > 0 ? "sync-error" : "sync-complete",
      title: totalErrors > 0
        ? `Sync Romania: ${totalErrors} erori din ${totalUats} UAT-uri`
        : `Sync Romania: ${totalUats} UAT-uri in ${counties.length} judete`,
      message: summary,
      metadata: { jobId, counties: counties.length, totalUats, totalErrors, totalDuration: totalDur },
    });

    console.log(`[sync-all] Done: ${summary}`);

    // Trigger PMTiles rebuild after full Romania sync
    await firePmtilesRebuild("all-counties-sync-complete", {
      counties: counties.length,
      totalUats,
      totalErrors,
    });

    setTimeout(() => clearProgress(jobId), 12 * 3_600_000);
  } catch (err) {
    const msg = err instanceof Error ? err.message : "Unknown";
    setProgress({
      jobId,
      downloaded: 0,
      total: 100,
      status: "error",
      phase: "Eroare",
      message: msg,
    });
    await createAppNotification({
      type: "sync-error",
      title: "Sync Romania: eroare generala",
      message: msg,
      metadata: { jobId },
    });
    setTimeout(() => clearProgress(jobId), 3_600_000);
  } finally {
    g.__allCountiesSyncRunning = false;
    g.__countySyncRunning = undefined;
  }
}

function formatDuration(seconds: number): string {
  if (seconds < 60) return `${seconds}s`;
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m${String(seconds % 60).padStart(2, "0")}s`;
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  return `${h}h${String(m).padStart(2, "0")}m`;
}
