/**
 * County & geometry refresh — populates GisUat.county + geometry
 * from eTerra LIMITE_UAT layer.
 *
 * Called with an already-authenticated EterraClient (fire-and-forget
 * after login), so there's no session expiry risk.
 *
 * Strategy:
 * 1. Query LIMITE_UAT for all features WITH geometry →
 *    get ADMIN_UNIT_ID, WORKSPACE_ID, AREA_VALUE, LAST_UPDATED_DTM + rings
 * 2. Map WORKSPACE_ID → county name via verified mapping
 * 3. Batch-update GisUat: county, workspacePk, geometry, areaValue, lastUpdatedDtm
 * 4. On subsequent runs: skip UATs where lastUpdatedDtm hasn't changed
 */

import { Prisma } from "@prisma/client";
import { prisma } from "@/core/storage/prisma";
import type { EterraClient } from "@/modules/parcel-sync/services/eterra-client";
import { findLayerById } from "@/modules/parcel-sync/services/eterra-layers";

/**
 * eTerra WORKSPACE_ID → Romanian county name.
 *
 * Verified by cross-referencing LIMITE_UAT sample UATs + DB confirmations.
 */
const WORKSPACE_TO_COUNTY: Record<number, string> = {
  10: "Alba",
  29: "Arad",
  38: "Argeș",
  47: "Bacău",
  56: "Bihor",
  65: "Bistrița-Năsăud",
  74: "Botoșani",
  83: "Brașov",
  92: "Brăila",
  109: "Buzău",
  118: "Caraș-Severin",
  127: "Cluj",
  136: "Constanța",
  145: "Covasna",
  154: "Dâmbovița",
  163: "Dolj",
  172: "Galați",
  181: "Gorj",
  190: "Harghita",
  207: "Hunedoara",
  216: "Ialomița",
  225: "Iași",
  234: "Ilfov",
  243: "Maramureș",
  252: "Mehedinți",
  261: "Mureș",
  270: "Neamț",
  289: "Olt",
  298: "Prahova",
  305: "Satu Mare",
  314: "Sălaj",
  323: "Sibiu",
  332: "Suceava",
  341: "Teleorman",
  350: "Timiș",
  369: "Tulcea",
  378: "Vaslui",
  387: "Vâlcea",
  396: "Vrancea",
  403: "București",
  519: "Călărași",
  528: "Giurgiu",
};

export async function refreshCountyData(client: EterraClient): Promise<void> {
  const total = await prisma.gisUat.count();
  if (total === 0) return;

  // Check how many are missing county OR geometry
  const [withCounty, withGeometry] = await Promise.all([
    prisma.gisUat.count({ where: { county: { not: null } } }),
    prisma.gisUat.count({
      where: { geometry: { not: Prisma.AnyNull } },
    }),
  ]);

  const needsCounty = withCounty < total * 0.5;
  const needsGeometry = withGeometry < total * 0.5;

  if (!needsCounty && !needsGeometry) {
    console.log(
      `[county-refresh] ${withCounty}/${total} counties, ${withGeometry}/${total} geometries — skipping.`,
    );
    return;
  }

  console.log(
    `[county-refresh] Starting: ${withCounty}/${total} counties, ${withGeometry}/${total} geometries.`,
  );

  // 1. Query LIMITE_UAT — with geometry if needed, without if only county
  const limiteUat = findLayerById("LIMITE_UAT");
  if (!limiteUat) {
    console.error("[county-refresh] LIMITE_UAT layer not configured.");
    return;
  }

  const features = await client.fetchAllLayerByWhere(limiteUat, "1=1", {
    outFields: "ADMIN_UNIT_ID,WORKSPACE_ID,AREA_VALUE,LAST_UPDATED_DTM",
    returnGeometry: needsGeometry,
    pageSize: 1000,
  });

  console.log(
    `[county-refresh] LIMITE_UAT: ${features.length} features` +
      `${needsGeometry ? " (with geometry)" : ""}.`,
  );
  if (features.length === 0) return;

  // 2. Log unknown workspaces
  const seenWs = new Set<number>();
  for (const f of features) {
    const ws = Number(f.attributes?.WORKSPACE_ID ?? 0);
    if (ws > 0 && !(ws in WORKSPACE_TO_COUNTY) && !seenWs.has(ws)) {
      seenWs.add(ws);
      const siruta = String(f.attributes?.ADMIN_UNIT_ID ?? "").replace(/\.0$/, "");
      console.warn(
        `[county-refresh] Unknown workspace ${ws} (SIRUTA ${siruta}). Add to mapping.`,
      );
    }
  }

  // 3. Upsert each UAT with county, workspacePk, geometry, area, lastUpdatedDtm
  let updated = 0;
  const BATCH = 50;

  for (let i = 0; i < features.length; i += BATCH) {
    const batch = features.slice(i, i + BATCH);
    const ops = [];

    for (const f of batch) {
      const siruta = String(f.attributes?.ADMIN_UNIT_ID ?? "")
        .trim()
        .replace(/\.0$/, "");
      const ws = Number(f.attributes?.WORKSPACE_ID ?? 0);
      if (!siruta || ws <= 0) continue;

      const county = WORKSPACE_TO_COUNTY[ws];
      const areaValue = Number(f.attributes?.AREA_VALUE ?? 0) || null;
      const lastUpdatedDtm = f.attributes?.LAST_UPDATED_DTM != null
        ? String(f.attributes.LAST_UPDATED_DTM)
        : null;

      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const geom = (f as any).geometry ?? null;

      const data: Prisma.GisUatUpdateInput = {
        workspacePk: ws,
        ...(county ? { county } : {}),
        ...(areaValue ? { areaValue } : {}),
        ...(lastUpdatedDtm ? { lastUpdatedDtm } : {}),
        ...(geom ? { geometry: geom as Prisma.InputJsonValue } : {}),
      };

      ops.push(
        prisma.gisUat.updateMany({
          where: { siruta },
          data,
        }),
      );
    }

    if (ops.length > 0) {
      const results = await prisma.$transaction(ops);
      for (const r of results) updated += r.count;
    }
  }

  console.log(`[county-refresh] Done: ${updated}/${total} updated.`);
}
