/**
 * POST /api/geoportal/optimize-views
 *
 * Replaces on-the-fly ST_Simplify views with materialized columns.
 * This eliminates CPU-heavy geometry simplification on every Martin tile request.
 *
 * What it does:
 * 1. Adds geom_z0/z5/z8 columns to GisUat table (pre-simplified geometry)
 * 2. Backfills them from the original geom column
 * 3. Creates spatial indexes on each
 * 4. Replaces views to use pre-computed columns instead of on-the-fly simplification
 *
 * Safe to re-run (idempotent). Original geom column is NEVER modified.
 */
import { NextResponse } from "next/server";
import { prisma } from "@/core/storage/prisma";

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

const STEPS = [
  // 0. Drop existing views that reference geom (they block ALTER TABLE)
  { name: "Drop gis_uats_z0 view", sql: `DROP VIEW IF EXISTS gis_uats_z0 CASCADE` },
  { name: "Drop gis_uats_z5 view", sql: `DROP VIEW IF EXISTS gis_uats_z5 CASCADE` },
  { name: "Drop gis_uats_z8 view", sql: `DROP VIEW IF EXISTS gis_uats_z8 CASCADE` },
  { name: "Drop gis_uats_z12 view", sql: `DROP VIEW IF EXISTS gis_uats_z12 CASCADE` },
  { name: "Drop gis_uats view", sql: `DROP VIEW IF EXISTS gis_uats CASCADE` },

  // 1. Add pre-simplified geometry columns (plain geometry, no typed constraint)
  {
    name: "Add geom_z0 column (2000m)",
    sql: `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='GisUat' AND column_name='geom_z0') THEN ALTER TABLE "GisUat" ADD COLUMN geom_z0 geometry; END IF; END $$`,
  },
  {
    name: "Add geom_z5 column (500m)",
    sql: `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='GisUat' AND column_name='geom_z5') THEN ALTER TABLE "GisUat" ADD COLUMN geom_z5 geometry; END IF; END $$`,
  },
  {
    name: "Add geom_z8 column (50m)",
    sql: `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='GisUat' AND column_name='geom_z8') THEN ALTER TABLE "GisUat" ADD COLUMN geom_z8 geometry; END IF; END $$`,
  },

  // 2. Backfill with pre-computed simplified geometries
  {
    name: "Backfill geom_z0 (2000m simplification)",
    sql: `UPDATE "GisUat" SET geom_z0 = ST_SimplifyPreserveTopology(geom, 2000) WHERE geom IS NOT NULL AND geom_z0 IS NULL`,
  },
  {
    name: "Backfill geom_z5 (500m simplification)",
    sql: `UPDATE "GisUat" SET geom_z5 = ST_SimplifyPreserveTopology(geom, 500) WHERE geom IS NOT NULL AND geom_z5 IS NULL`,
  },
  {
    name: "Backfill geom_z8 (50m simplification)",
    sql: `UPDATE "GisUat" SET geom_z8 = ST_SimplifyPreserveTopology(geom, 50) WHERE geom IS NOT NULL AND geom_z8 IS NULL`,
  },

  // 3. Spatial indexes
  {
    name: "Index geom_z0",
    sql: `CREATE INDEX IF NOT EXISTS gis_uat_geom_z0_idx ON "GisUat" USING GIST (geom_z0)`,
  },
  {
    name: "Index geom_z5",
    sql: `CREATE INDEX IF NOT EXISTS gis_uat_geom_z5_idx ON "GisUat" USING GIST (geom_z5)`,
  },
  {
    name: "Index geom_z8",
    sql: `CREATE INDEX IF NOT EXISTS gis_uat_geom_z8_idx ON "GisUat" USING GIST (geom_z8)`,
  },

  // 4. Replace views to use pre-computed columns (zero CPU on read)
  {
    name: "Replace gis_uats_z0 view",
    sql: `CREATE OR REPLACE VIEW gis_uats_z0 AS SELECT siruta, name, geom_z0 AS geom FROM "GisUat" WHERE geom_z0 IS NOT NULL`,
  },
  {
    name: "Replace gis_uats_z5 view",
    sql: `CREATE OR REPLACE VIEW gis_uats_z5 AS SELECT siruta, name, geom_z5 AS geom FROM "GisUat" WHERE geom_z5 IS NOT NULL`,
  },
  {
    name: "Replace gis_uats_z8 view",
    sql: `CREATE OR REPLACE VIEW gis_uats_z8 AS SELECT siruta, name, county, geom_z8 AS geom FROM "GisUat" WHERE geom_z8 IS NOT NULL`,
  },
  {
    name: "Replace gis_uats_z12 view (original geom)",
    sql: `CREATE OR REPLACE VIEW gis_uats_z12 AS SELECT siruta, name, county, geom FROM "GisUat" WHERE geom IS NOT NULL`,
  },

  // 5. Restore legacy gis_uats view for QGIS compatibility
  {
    name: "Restore gis_uats view",
    sql: `CREATE OR REPLACE VIEW gis_uats AS SELECT siruta, name, county, geom_z8 AS geom FROM "GisUat" WHERE geom_z8 IS NOT NULL`,
  },

  // 6. Slim down gis_terenuri/cladiri views (drop huge attributes/enrichment JSON columns)
  {
    name: "Optimize gis_features view (slim columns)",
    sql: `CREATE OR REPLACE VIEW gis_features AS SELECT id, "layerId" AS layer_id, siruta, "objectId" AS object_id, "cadastralRef" AS cadastral_ref, "areaValue" AS area_value, "isActive" AS is_active, geom FROM "GisFeature" WHERE geom IS NOT NULL`,
  },
  {
    name: "Optimize gis_terenuri view",
    sql: `CREATE OR REPLACE VIEW gis_terenuri AS SELECT * FROM gis_features WHERE layer_id LIKE 'TERENURI%' OR layer_id LIKE 'CADGEN_LAND%'`,
  },
  {
    name: "Optimize gis_cladiri view",
    sql: `CREATE OR REPLACE VIEW gis_cladiri AS SELECT * FROM gis_features WHERE layer_id LIKE 'CLADIRI%' OR layer_id LIKE 'CADGEN_BUILDING%'`,
  },
  {
    name: "Optimize gis_administrativ view",
    sql: `CREATE OR REPLACE VIEW gis_administrativ AS SELECT * FROM gis_features WHERE layer_id LIKE 'LIMITE%' OR layer_id LIKE 'SPECIAL_AREAS%'`,
  },

  // 7. Update trigger to also compute simplified geoms on INSERT/UPDATE
  {
    name: "Update trigger to pre-compute simplified geoms",
    sql: `CREATE OR REPLACE FUNCTION gis_uat_sync_geom() RETURNS TRIGGER AS $$ BEGIN IF NEW.geometry IS NOT NULL THEN BEGIN NEW.geom := gis_uat_esri_to_geom(NEW.geometry::jsonb); IF NEW.geom IS NOT NULL THEN NEW.geom_z0 := ST_SimplifyPreserveTopology(NEW.geom, 2000); NEW.geom_z5 := ST_SimplifyPreserveTopology(NEW.geom, 500); NEW.geom_z8 := ST_SimplifyPreserveTopology(NEW.geom, 50); END IF; EXCEPTION WHEN OTHERS THEN NEW.geom := NULL; NEW.geom_z0 := NULL; NEW.geom_z5 := NULL; NEW.geom_z8 := NULL; END; ELSE NEW.geom := NULL; NEW.geom_z0 := NULL; NEW.geom_z5 := NULL; NEW.geom_z8 := NULL; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql`,
  },
];

export async function POST() {
  const results: string[] = [];
  try {
    for (const step of STEPS) {
      await prisma.$executeRawUnsafe(step.sql);
      results.push(`${step.name} OK`);
    }
    return NextResponse.json({ status: "ok", results });
  } catch (error) {
    const msg = error instanceof Error ? error.message : "Eroare";
    return NextResponse.json({ status: "error", results, error: msg }, { status: 500 });
  }
}

/** GET — check optimization status */
export async function GET() {
  try {
    const cols = await prisma.$queryRaw`
      SELECT column_name FROM information_schema.columns
      WHERE table_name = 'GisUat' AND column_name LIKE 'geom_z%'
    ` as Array<{ column_name: string }>;

    const optimized = cols.length >= 3;
    return NextResponse.json({ optimized, columns: cols.map((c) => c.column_name) });
  } catch {
    return NextResponse.json({ optimized: false, columns: [] });
  }
}
