import { randomBytes, randomUUID } from "node:crypto";
import { NextResponse } from "next/server";
import { getDbPool } from "@/db";
import { getSession } from "@/lib/auth";
import { resolveInspectionTenant } from "@/lib/authorization";

export const runtime = "nodejs";

async function findInspection(externalId: string, tenantId: string) {
  const db = getDbPool();
  const [rows] = await db.execute(
    "SELECT id, inspection_cycle FROM inspections WHERE tenant_id = ? AND external_id = ? LIMIT 1",
    [tenantId, externalId],
  );
  return { db, inspection: (rows as { id: string; inspection_cycle: number }[])[0] ?? null };
}

export async function GET(request: Request, { params }: { params: Promise<{ externalId: string }> }) {
  try {
    const { externalId } = await params;
    const session = await getSession();
    if (!session) return NextResponse.json({ error: "Faça login para consultar o link de vistoria." }, { status: 401 });
    const tenantId = await resolveInspectionTenant(session, new URL(request.url).searchParams.get("tenantId"));
    if (!tenantId) return NextResponse.json({ error: "Cliente da vistoria não encontrado ou inativo." }, { status: 404 });
    const { db, inspection } = await findInspection(externalId, tenantId);
    if (!inspection) return NextResponse.json({ error: "Vistoria não encontrada." }, { status: 404 });
    const [links] = await db.execute(
      `SELECT token, expires_at
       FROM inspection_access_links
       WHERE inspection_id = ? AND inspection_cycle = ? AND revoked_at IS NULL AND expires_at > NOW()
       ORDER BY created_at DESC LIMIT 1`,
      [inspection.id, Number(inspection.inspection_cycle || 1)],
    );
    const link = (links as { token: string; expires_at: string }[])[0];
    return NextResponse.json({ path: link ? `/vistoria/${link.token}` : null, expiresAt: link?.expires_at ?? null, cycle: inspection.inspection_cycle });
  } catch (error) {
    console.error("Erro ao consultar link de vistoria", error);
    return NextResponse.json({ error: "Não foi possível consultar o link de vistoria." }, { status: 500 });
  }
}

export async function POST(request: Request, { params }: { params: Promise<{ externalId: string }> }) {
  try {
    const { externalId } = await params;
    const session = await getSession();
    if (!session) return NextResponse.json({ error: "Faça login para gerar um link de vistoria." }, { status: 401 });
    const body = await request.json().catch(() => ({})) as { reinspection?: boolean; expiryMinutes?: number; tenantId?: string };
    const tenantId = await resolveInspectionTenant(session, body.tenantId);
    if (!tenantId) return NextResponse.json({ error: "Cliente da vistoria não encontrado ou inativo." }, { status: 404 });
    const { db, inspection } = await findInspection(externalId, tenantId);
    if (!inspection) return NextResponse.json({ error: "Vistoria não encontrada." }, { status: 404 });

    let cycle = Number(inspection.inspection_cycle || 1);
    if (body.reinspection) {
      cycle += 1;
      await db.execute("UPDATE inspection_access_links SET revoked_at = NOW() WHERE inspection_id = ? AND revoked_at IS NULL", [inspection.id]);
      await db.execute("UPDATE inspections SET inspection_cycle = ?, status = 'link_sent', risk_score = 0, rules_version = NULL, completed_at = NULL WHERE id = ?", [cycle, inspection.id]);
    }

    if (!body.reinspection) {
      const [activeRows] = await db.execute(
        `SELECT token, expires_at FROM inspection_access_links
         WHERE inspection_id = ? AND inspection_cycle = ? AND revoked_at IS NULL AND expires_at > NOW()
         ORDER BY created_at DESC LIMIT 1`,
        [inspection.id, cycle],
      );
      const active = (activeRows as { token: string; expires_at: string }[])[0];
      if (active) return NextResponse.json({ path: `/vistoria/${active.token}`, expiresAt: active.expires_at, cycle, reused: true, message: "Link ativo localizado e copiado novamente." });
    }

    const token = randomBytes(32).toString("base64url");
    const allowedExpiries = [15, 60, 360, 1440, 2520];
    const expiryMinutes = allowedExpiries.includes(Number(body.expiryMinutes)) ? Number(body.expiryMinutes) : 1440;
    const expiresAt = new Date(Date.now() + expiryMinutes * 60 * 1000);
    await db.execute(
      "INSERT INTO inspection_access_links (id, inspection_id, inspection_cycle, token, expires_at) VALUES (?, ?, ?, ?, ?)",
      [randomUUID(), inspection.id, cycle, token, expiresAt],
    );
    await db.execute("UPDATE inspections SET status = 'link_sent' WHERE id = ? AND status = 'received'", [inspection.id]);

    return NextResponse.json({ path: `/vistoria/${token}`, expiresAt, cycle, reused: false, message: body.reinspection ? "Novo link de retriagem criado. As fotos anteriores foram preservadas no histórico." : "Link de vistoria criado." });
  } catch (error: unknown) {
    console.error("Erro ao gerar link de vistoria", error);
    const code = typeof error === "object" && error && "code" in error ? String(error.code) : "";
    if (code === "ER_NO_SUCH_TABLE") return NextResponse.json({ error: "A tabela de links ainda não foi criada.", hint: "Execute a migration 001_inspection_access_links.sql no MySQL." }, { status: 503 });
    return NextResponse.json({ error: "Não foi possível gerar o link de vistoria." }, { status: 500 });
  }
}
