-- Fase 3: roles definitivos, permisos por rol (matriz en codigo, no en DB) y asignaciones de
-- usuarios por emisor/establecimiento.
--
-- Posterior a 20260806090000_fase2_certificados_secuenciales, no la modifica.

-- ============================================================================
-- 1) RolUsuario: SUPERADMIN/CONTADOR -> SUPERADMIN/REPRESENTANTE_LEGAL/FINANCIERO/ASESOR_COMERCIAL
--    Postgres no soporta eliminar valores de un enum, asi que se recrea el tipo y se migran los
--    datos con un USING/CASE (CONTADOR -> FINANCIERO, el resto se conserva igual).
-- ============================================================================
ALTER TYPE "RolUsuario" RENAME TO "RolUsuario_old";
CREATE TYPE "RolUsuario" AS ENUM ('SUPERADMIN', 'REPRESENTANTE_LEGAL', 'FINANCIERO', 'ASESOR_COMERCIAL');

ALTER TABLE "usuarios" ALTER COLUMN "rol" TYPE "RolUsuario" USING (
  CASE "rol"::text
    WHEN 'CONTADOR' THEN 'FINANCIERO'
    ELSE "rol"::text
  END
)::"RolUsuario";

DROP TYPE "RolUsuario_old";

-- ============================================================================
-- 2) Invalidacion de sesiones: version incluida en cada JWT nuevo, comparada en cada request.
--    Arranca en 1 para todos los usuarios existentes; cualquier token emitido antes de esta fase
--    (que no trae este campo) queda invalidado por diseno (fail-closed: requireAuth exige que
--    coincida, y un token sin el campo nunca coincide con un entero real).
-- ============================================================================
ALTER TABLE "usuarios" ADD COLUMN "sessionVersion" INTEGER NOT NULL DEFAULT 1;

-- ============================================================================
-- 3) Asignaciones de usuario a emisor (+ establecimiento opcional)
-- ============================================================================
CREATE TABLE "asignaciones_usuario" (
    "id" TEXT NOT NULL,
    "usuarioId" TEXT NOT NULL,
    "emisorId" TEXT NOT NULL,
    "establecimientoId" TEXT,
    "activo" BOOLEAN NOT NULL DEFAULT true,
    "asignadoPorId" TEXT NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "asignaciones_usuario_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "asignaciones_usuario_usuarioId_emisorId_establecimientoId_key" ON "asignaciones_usuario"("usuarioId", "emisorId", "establecimientoId");
CREATE INDEX "asignaciones_usuario_usuarioId_idx" ON "asignaciones_usuario"("usuarioId");
CREATE INDEX "asignaciones_usuario_emisorId_idx" ON "asignaciones_usuario"("emisorId");

-- Indice unico parcial: el @@unique de arriba NO evita duplicados cuando establecimientoId es NULL
-- (alcance a "todo el emisor"), porque Postgres trata cada NULL como distinto en un unique index
-- normal. Este indice parcial cubre exactamente ese caso.
CREATE UNIQUE INDEX "asignaciones_usuario_usuario_emisor_sin_establecimiento_key"
  ON "asignaciones_usuario"("usuarioId", "emisorId")
  WHERE "establecimientoId" IS NULL;

ALTER TABLE "asignaciones_usuario" ADD CONSTRAINT "asignaciones_usuario_usuarioId_fkey" FOREIGN KEY ("usuarioId") REFERENCES "usuarios"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE "asignaciones_usuario" ADD CONSTRAINT "asignaciones_usuario_emisorId_fkey" FOREIGN KEY ("emisorId") REFERENCES "emisores"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE "asignaciones_usuario" ADD CONSTRAINT "asignaciones_usuario_establecimientoId_fkey" FOREIGN KEY ("establecimientoId") REFERENCES "establecimientos"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "asignaciones_usuario" ADD CONSTRAINT "asignaciones_usuario_asignadoPorId_fkey" FOREIGN KEY ("asignadoPorId") REFERENCES "usuarios"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- ============================================================================
-- 4) Asignacion inicial: cada usuario no-SUPERADMIN existente queda asignado (alcance = todo el
--    emisor, sin restringir a un establecimiento) al emisor mas antiguo (el migrado en la fase 1),
--    registrado por el SUPERADMIN activo mas antiguo. Los SUPERADMIN no necesitan asignacion
--    (alcance global implicito). Si no existe ningun emisor o ningun SUPERADMIN activo, no se
--    inventa una asignacion: el bloque no hace nada (base nueva / caso no determinable de forma segura).
-- ============================================================================
DO $$
DECLARE
  emisor_id TEXT;
  superadmin_id TEXT;
  fila RECORD;
BEGIN
  SELECT "id" INTO emisor_id FROM "emisores" ORDER BY "createdAt" ASC LIMIT 1;
  SELECT "id" INTO superadmin_id FROM "usuarios" WHERE "rol" = 'SUPERADMIN' AND "activo" = true ORDER BY "createdAt" ASC LIMIT 1;

  IF emisor_id IS NOT NULL AND superadmin_id IS NOT NULL THEN
    FOR fila IN SELECT "id" FROM "usuarios" WHERE "rol" != 'SUPERADMIN' LOOP
      INSERT INTO "asignaciones_usuario" ("id", "usuarioId", "emisorId", "establecimientoId", "activo", "asignadoPorId", "createdAt", "updatedAt")
      VALUES (gen_random_uuid()::text, fila."id", emisor_id, NULL, true, superadmin_id, now(), now())
      ON CONFLICT DO NOTHING;
    END LOOP;
  END IF;
END $$;
