/**
 * Debug endpoint for registry sequence counters.
 *
 * GET  — Show all sequence counters + actual max from entries + sample numbers
 * POST — Reset all counters to match actual entries (fixes stale counters)
 *
 * Auth: NextAuth session only.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/core/storage/prisma";
import { getAuthSession } from "@/core/auth";

async function requireAdmin(): Promise<NextResponse | null> {
  const session = await getAuthSession();
  if (!session) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  const u = session.user as { role?: string } | undefined;
  if (u?.role !== "admin") {
    return NextResponse.json({ error: "Admin access required" }, { status: 403 });
  }
  return null;
}

export async function GET() {
  const denied = await requireAdmin();
  if (denied) return denied;

  // Get all sequence counters
  const counters = await prisma.$queryRaw<
    Array<{ company: string; year: number; type: string; lastSeq: number }>
  >`SELECT company, year, type, "lastSeq" FROM "RegistrySequence" ORDER BY company, year, type`;

  // Sample: show raw value snippet + extracted number (for debugging regex issues)
  const samples = await prisma.$queryRawUnsafe<
    Array<{ key: string; num: string | null; snippet: string }>
  >(`
    SELECT key,
           SUBSTRING(value::text FROM '"number": "([^"]+)"') AS num,
           SUBSTRING(value::text FROM 1 FOR 200) AS snippet
    FROM "KeyValueStore"
    WHERE namespace = 'registratura'
      AND key LIKE 'entry:%'
    ORDER BY key
    LIMIT 5
  `);

  // Get actual max sequences from entries — current format: B-2026-00001
  // Use [0-9] instead of \d for PostgreSQL POSIX regex compatibility
  const actuals = await prisma.$queryRawUnsafe<
    Array<{ prefix: string; maxSeq: number; count: number }>
  >(`
    SELECT
      SUBSTRING(value::text FROM '"number": "([A-Z]-[0-9]{4})-') AS prefix,
      MAX(CAST(SUBSTRING(value::text FROM '"number": "[A-Z]-[0-9]{4}-([0-9]{5})"') AS INTEGER)) AS "maxSeq",
      COUNT(*)::int AS count
    FROM "KeyValueStore"
    WHERE namespace = 'registratura'
      AND key LIKE 'entry:%'
      AND value::text ~ '"number": "[A-Z]-[0-9]{4}-[0-9]{5}"'
    GROUP BY prefix
    ORDER BY prefix
  `);

  // Also check for old-format entries (BTG-2026-OUT-00001)
  const oldFormatActuals = await prisma.$queryRawUnsafe<
    Array<{ prefix: string; maxSeq: number; count: number }>
  >(`
    SELECT
      SUBSTRING(value::text FROM '"number": "([A-Z]{3}-[0-9]{4})-') AS prefix,
      MAX(CAST(SUBSTRING(value::text FROM '"number": "[A-Z]{3}-[0-9]{4}-(?:IN|OUT|INT)-([0-9]{5})"') AS INTEGER)) AS "maxSeq",
      COUNT(*)::int AS count
    FROM "KeyValueStore"
    WHERE namespace = 'registratura'
      AND key LIKE 'entry:%'
      AND value::text ~ '"number": "[A-Z]{3}-[0-9]{4}-(IN|OUT|INT)-[0-9]{5}"'
    GROUP BY prefix
    ORDER BY prefix
  `);

  return NextResponse.json({
    counters,
    samples,
    currentFormatEntries: actuals,
    oldFormatEntries: oldFormatActuals,
    note: "POST to this endpoint to reset all counters to match actual entries",
  });
}

export async function POST() {
  const denied = await requireAdmin();
  if (denied) return denied;

  // Delete ALL old counters
  const deleted = await prisma.$executeRaw`DELETE FROM "RegistrySequence"`;

  // Re-create counters from current format entries (B-2026-00001)
  const insertedNew = await prisma.$executeRawUnsafe(`
    INSERT INTO "RegistrySequence" (id, company, year, type, "lastSeq", "createdAt", "updatedAt")
    SELECT
      gen_random_uuid()::text,
      SUBSTRING(value::text FROM '"number": "([A-Z])-') AS company,
      CAST(SUBSTRING(value::text FROM '"number": "[A-Z]-([0-9]{4})-') AS INTEGER) AS year,
      'SEQ' AS type,
      MAX(CAST(SUBSTRING(value::text FROM '"number": "[A-Z]-[0-9]{4}-([0-9]{5})"') AS INTEGER)) AS "lastSeq",
      NOW(),
      NOW()
    FROM "KeyValueStore"
    WHERE namespace = 'registratura'
      AND key LIKE 'entry:%'
      AND value::text ~ '"number": "[A-Z]-[0-9]{4}-[0-9]{5}"'
    GROUP BY company, year, type
  `);

  // Also handle old-format entries (BTG→B, USW→U, SDT→S, GRP→G)
  const insertedOld = await prisma.$executeRawUnsafe(`
    INSERT INTO "RegistrySequence" (id, company, year, type, "lastSeq", "createdAt", "updatedAt")
    SELECT
      gen_random_uuid()::text,
      CASE SUBSTRING(value::text FROM '"number": "([A-Z]{3})-')
        WHEN 'BTG' THEN 'B'
        WHEN 'USW' THEN 'U'
        WHEN 'SDT' THEN 'S'
        WHEN 'GRP' THEN 'G'
        ELSE SUBSTRING(value::text FROM '"number": "([A-Z]{3})-')
      END AS company,
      CAST(SUBSTRING(value::text FROM '"number": "[A-Z]{3}-([0-9]{4})-') AS INTEGER) AS year,
      'SEQ' AS type,
      MAX(CAST(SUBSTRING(value::text FROM '"number": "[A-Z]{3}-[0-9]{4}-(?:IN|OUT|INT)-([0-9]{5})"') AS INTEGER)) AS "lastSeq",
      NOW(),
      NOW()
    FROM "KeyValueStore"
    WHERE namespace = 'registratura'
      AND key LIKE 'entry:%'
      AND value::text ~ '"number": "[A-Z]{3}-[0-9]{4}-(IN|OUT|INT)-[0-9]{5}"'
    GROUP BY company, year, type
    ON CONFLICT (company, year, type)
    DO UPDATE SET "lastSeq" = GREATEST("RegistrySequence"."lastSeq", EXCLUDED."lastSeq"),
                  "updatedAt" = NOW()
  `);

  return NextResponse.json({
    success: true,
    deletedCounters: deleted,
    recreatedFromNewFormat: insertedNew,
    recreatedFromOldFormat: insertedOld,
    message: "All counters reset from actual entries (both old and new format).",
  });
}

/**
 * PATCH — Migrate old-format entries (BTG/SDT/USW/GRP) to new format (B/S/U/G).
 * Rewrites the "number" field inside the JSONB value for matching entries.
 */
export async function PATCH() {
  const denied = await requireAdmin();
  if (denied) return denied;

  // Map old 3-letter prefixes to new single-letter
  const migrations: Array<{ old: string; new: string }> = [
    { old: "BTG", new: "B" },
    { old: "SDT", new: "S" },
    { old: "USW", new: "U" },
    { old: "GRP", new: "G" },
  ];

  const results: Array<{ prefix: string; updated: number }> = [];

  for (const m of migrations) {
    // Find entries with old-format numbers: BTG-2026-IN-00001, SDT-2026-OUT-00002, etc.
    const entries = await prisma.$queryRawUnsafe<
      Array<{ key: string; num: string }>
    >(`
      SELECT key,
             SUBSTRING(value::text FROM '"number": "([^"]+)"') AS num
      FROM "KeyValueStore"
      WHERE namespace = 'registratura'
        AND key LIKE 'entry:%'
        AND value::text ~ '"number": "${m.old}-[0-9]{4}-(IN|OUT|INT)-[0-9]{5}"'
    `);

    let updated = 0;
    for (const entry of entries) {
      if (!entry.num) continue;

      // Parse: SDT-2026-OUT-00001 → S-2026-00001
      const match = entry.num.match(
        new RegExp(`^${m.old}-(\\d{4})-(?:IN|OUT|INT)-(\\d{5})$`)
      );
      if (!match) continue;

      const newNumber = `${m.new}-${match[1]}-${match[2]}`;

      // Update the JSONB value — replace the number field
      await prisma.$executeRawUnsafe(`
        UPDATE "KeyValueStore"
        SET value = jsonb_set(value, '{number}', $1::jsonb)
        WHERE namespace = 'registratura'
          AND key = $2
      `, JSON.stringify(newNumber), entry.key);

      updated++;
    }

    results.push({ prefix: m.old, updated });
  }

  return NextResponse.json({
    success: true,
    migrations: results,
    message: "Old-format entries migrated to new format. Run POST to reset counters.",
  });
}
