// Yurtdışı üniversite sayfaları için ülke kontürlerini üretir.
//
// Kaynak: Natural Earth 10m admin_0_countries (kamu malı). GeoJSON bir kez
// indirilip tmp'ye önbelleklenir; çıktı src/lib/harita-ulkeler-verisi.ts
// dosyasına yazılır ve repo'ya commit'lenir (build ağa çıkmaz).
//
// Projeksiyon: ülke başına eşdikdörtgen (plate carrée) + cos(ortaEnlem)
// düzeltmesi; Türkiye haritasının kırpılmış oranıyla aynı 1050×447 kutuya
// sığdırılır. Nokta seyreltme ~1px eşikli olduğundan çıktı küçük kalır.
//
// Çalıştırma: pnpm tsx scripts/ulke-harita-uret.ts

import fs from "node:fs";
import os from "node:os";
import path from "node:path";

const GENISLIK = 1050;
const YUKSEKLIK = 447;
const KENAR_PAYI = 26;
const SEYRELTME_PX = 1.1;
const MIN_HALKA_PX = 3; // bbox'u bundan küçük halkalar (adacıklar) atlanır

const KAYNAK_URL =
  "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_10m_admin_0_countries.geojson";

type UlkeTanim = {
  kod: string;
  ad: string;
  /** Vurgulanan (mavi) NE ADMIN adları */
  vurgulu: string[];
  /** Soluk çizilen bağlam parçaları (ör. Kıbrıs'ın güneyi) */
  baglam?: string[];
};

const ULKELER: UlkeTanim[] = [
  {
    kod: "kktc",
    ad: "KKTC",
    vurgulu: ["Northern Cyprus"],
    baglam: [
      "Cyprus",
      "Cyprus No Mans Area",
      "Dhekelia Sovereign Base Area",
      "Akrotiri Sovereign Base Area",
    ],
  },
  { kod: "azerbaycan", ad: "Azerbaycan", vurgulu: ["Azerbaijan"] },
  { kod: "kirgizistan", ad: "Kırgızistan", vurgulu: ["Kyrgyzstan"] },
  { kod: "kazakistan", ad: "Kazakistan", vurgulu: ["Kazakhstan"] },
  {
    kod: "bosna-hersek",
    ad: "Bosna-Hersek",
    vurgulu: ["Bosnia and Herzegovina"],
  },
  { kod: "makedonya", ad: "Kuzey Makedonya", vurgulu: ["North Macedonia"] },
  { kod: "arnavutluk", ad: "Arnavutluk", vurgulu: ["Albania"] },
];

type Halka = [number, number][]; // [lng, lat]

async function geojsonGetir(): Promise<{
  features: {
    properties: { ADMIN: string };
    geometry: { type: string; coordinates: unknown };
  }[];
}> {
  const cachePath = path.join(os.tmpdir(), "ne_10m_admin_0_countries.geojson");
  if (!fs.existsSync(cachePath)) {
    console.log("indiriliyor:", KAYNAK_URL);
    const res = await fetch(KAYNAK_URL);
    if (!res.ok) throw new Error(`indirme başarısız: ${res.status}`);
    fs.writeFileSync(cachePath, Buffer.from(await res.arrayBuffer()));
  }
  return JSON.parse(fs.readFileSync(cachePath, "utf8"));
}

function halkalar(geometry: { type: string; coordinates: unknown }): Halka[] {
  if (geometry.type === "Polygon") return geometry.coordinates as Halka[];
  if (geometry.type === "MultiPolygon")
    return (geometry.coordinates as Halka[][]).flat();
  throw new Error(`beklenmeyen geometri: ${geometry.type}`);
}

function pathUret(
  ringler: Halka[],
  proje: (lng: number, lat: number) => { x: number; y: number },
): string[] {
  const parcalar: string[] = [];
  for (const ring of ringler) {
    const pts = ring.map(([lng, lat]) => proje(lng, lat));
    const xs = pts.map((p) => p.x);
    const ys = pts.map((p) => p.y);
    if (
      Math.max(...xs) - Math.min(...xs) < MIN_HALKA_PX &&
      Math.max(...ys) - Math.min(...ys) < MIN_HALKA_PX
    )
      continue;

    let d = "";
    let sonX = NaN;
    let sonY = NaN;
    for (let i = 0; i < pts.length; i++) {
      const { x, y } = pts[i];
      if (i > 0 && Math.hypot(x - sonX, y - sonY) < SEYRELTME_PX) continue;
      d += `${d ? "L" : "M"}${x.toFixed(1)} ${y.toFixed(1)}`;
      sonX = x;
      sonY = y;
    }
    d += "Z";
    if (d.length > 10) parcalar.push(d);
  }
  return parcalar;
}

async function main() {
  const geojson = await geojsonGetir();
  const byAdmin = new Map(
    geojson.features.map((f) => [f.properties.ADMIN, f] as const),
  );

  const cikti: string[] = [];
  const kodlar = ULKELER.map((u) => `"${u.kod}"`).join(" | ");

  cikti.push(
    "// Bu dosya scripts/ulke-harita-uret.ts tarafından üretildi — elle düzenleme.",
    "// Kaynak: Natural Earth 10m admin_0_countries (kamu malı).",
    "",
    `export type UlkeKodu = ${kodlar};`,
    "",
    "export type UlkeHarita = {",
    "  ad: string;",
    "  /** lat/lng → viewBox koordinatı: x = ax*lng + bx, y = ay*lat + by */",
    "  proje: { ax: number; bx: number; ay: number; by: number };",
    "  /** Vurgulanan ülke kontürleri */",
    "  ulke: string[];",
    "  /** Soluk çizilen bağlam kontürleri (ör. Kıbrıs adasının güneyi) */",
    "  baglam: string[];",
    "};",
    "",
    `export const ULKE_HARITA_GENISLIK = ${GENISLIK};`,
    `export const ULKE_HARITA_YUKSEKLIK = ${YUKSEKLIK};`,
    "",
    "export const ULKE_HARITALARI: Record<UlkeKodu, UlkeHarita> = {",
  );

  for (const ulke of ULKELER) {
    const adlar = [...ulke.vurgulu, ...(ulke.baglam ?? [])];
    const geometriler = adlar.map((ad) => {
      const f = byAdmin.get(ad);
      if (!f) throw new Error(`Natural Earth'te bulunamadı: ${ad}`);
      return { ad, ringler: halkalar(f.geometry) };
    });

    // Sığdırma: tüm parçaların (bağlam dahil) bbox'una göre tek ölçek
    const tumNoktalar = geometriler.flatMap((g) => g.ringler.flat());
    const latler = tumNoktalar.map(([, lat]) => lat);
    const ortaLat = (Math.min(...latler) + Math.max(...latler)) / 2;
    const kx = Math.cos((ortaLat * Math.PI) / 180);
    const pxler = tumNoktalar.map(([lng]) => lng * kx);
    const pyler = tumNoktalar.map(([, lat]) => -lat);
    const minX = Math.min(...pxler);
    const maxX = Math.max(...pxler);
    const minY = Math.min(...pyler);
    const maxY = Math.max(...pyler);
    const s = Math.min(
      (GENISLIK - 2 * KENAR_PAYI) / (maxX - minX),
      (YUKSEKLIK - 2 * KENAR_PAYI) / (maxY - minY),
    );
    const ox = (GENISLIK - s * (maxX - minX)) / 2;
    const oy = (YUKSEKLIK - s * (maxY - minY)) / 2;
    const proje = (lng: number, lat: number) => ({
      x: s * (lng * kx - minX) + ox,
      y: s * (-lat - minY) + oy,
    });

    const vurguluPaths = geometriler
      .filter((g) => ulke.vurgulu.includes(g.ad))
      .flatMap((g) => pathUret(g.ringler, proje));
    const baglamPaths = geometriler
      .filter((g) => !ulke.vurgulu.includes(g.ad))
      .flatMap((g) => pathUret(g.ringler, proje));

    const yaz = (n: number) => Number(n.toFixed(4));
    cikti.push(
      `  "${ulke.kod}": {`,
      `    ad: ${JSON.stringify(ulke.ad)},`,
      `    proje: { ax: ${yaz(s * kx)}, bx: ${yaz(ox - s * minX)}, ay: ${yaz(-s)}, by: ${yaz(oy - s * minY)} },`,
      `    ulke: ${JSON.stringify(vurguluPaths)},`,
      `    baglam: ${JSON.stringify(baglamPaths)},`,
      "  },",
    );
    console.log(
      `${ulke.kod}: ${vurguluPaths.length} vurgulu + ${baglamPaths.length} bağlam path, ` +
        `~${Math.round((vurguluPaths.join("").length + baglamPaths.join("").length) / 1024)}KB`,
    );
  }

  cikti.push("};", "");
  const hedef = path.join(
    process.cwd(),
    "src",
    "lib",
    "harita-ulkeler-verisi.ts",
  );
  fs.writeFileSync(hedef, cikti.join("\n"));
  console.log("yazıldı:", hedef);
}

main();
