import {
  Body,
  Controller,
  Get,
  Param,
  ParseIntPipe,
  Patch,
  Post,
  Request,
  UseGuards,
} from "@nestjs/common";
import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger";
import { JwtAuthGuard } from "../auth/guards/jwt-auth.guard";
import { OmitDeviationDto } from "./dto/omit-deviation.dto";
import { ProvisionarAccesoDto } from "./dto/provisionar-acceso.dto";
import { RegisterTenantDto } from "./dto/register-tenant.dto";
import { TestConnectionDto } from "./dto/test-connection.dto";
import { UpdateTogglesOperativosDto } from "./dto/update-toggles-operativos.dto";
import { PlatformAdminGuard } from "./guards/platform-admin.guard";
import { TenantsAdminService } from "./tenants-admin.service";

// Superficie de PLATAFORMA — nunca de un tenant en particular. Por eso el
// guard es PlatformAdminGuard (mira rolPlataforma), no PermissionGuard (que
// mira el rol local dentro de un tenant, y aca no hay ningun tenant
// "actual": esta pantalla opera sobre CUALQUIER tenant por id explicito).
@ApiTags("admin-tenants")
@ApiBearerAuth()
@UseGuards(JwtAuthGuard, PlatformAdminGuard)
@Controller("admin/tenants")
export class TenantsAdminController {
  constructor(private readonly tenantsAdminService: TenantsAdminService) {}

  @Get()
  @ApiOperation({ summary: "Listar tenants con su estado de acceso/schema/migraciones" })
  async list() {
    return this.tenantsAdminService.listTenantsResumen();
  }

  @Post("probar-conexion")
  @ApiOperation({ summary: "Probar una conexion SIN guardar nada (paso Preparar)" })
  async testConnection(@Body() dto: TestConnectionDto) {
    return this.tenantsAdminService.testConnection(dto);
  }

  @Post()
  @ApiOperation({ summary: "Registrar un tenant nuevo (conexion existente, nunca crea base/usuario MySQL)" })
  async register(@Body() dto: RegisterTenantDto) {
    return this.tenantsAdminService.registerTenant(dto);
  }

  @Get(":id")
  @ApiOperation({ summary: "Estado detallado: acceso, migraciones pendientes, desviaciones de columna" })
  async getEstado(@Param("id", ParseIntPipe) id: number) {
    return this.tenantsAdminService.getEstadoDetallado(id);
  }

  @Get(":id/resumen-operativo")
  @ApiOperation({
    summary:
      "Checklist operativo: tiendas creadas, tiendas con facturacion POS activa, y productos propios",
  })
  async getResumenOperativo(@Param("id", ParseIntPipe) id: number) {
    return this.tenantsAdminService.getResumenOperativo(id);
  }

  @Patch(":id/toggles-operativos")
  @ApiOperation({
    summary:
      "Configurar si el tenant necesita tiendas/productos propios/facturacion POS -- " +
      "apagar el toggle correspondiente deja de exigirlo para poder 'Activar'",
  })
  async updateTogglesOperativos(
    @Param("id", ParseIntPipe) id: number,
    @Body() dto: UpdateTogglesOperativosDto,
  ) {
    return this.tenantsAdminService.updateTogglesOperativos(id, dto);
  }

  @Post(":id/omitir-desviacion")
  @ApiOperation({ summary: "Aceptar explicitamente una desviacion de columna 'grave' (con nota)" })
  async omitDeviation(
    @Param("id", ParseIntPipe) id: number,
    @Body() dto: OmitDeviationDto,
    @Request() req: any,
  ) {
    return this.tenantsAdminService.omitDeviation(id, dto, req.user.identidadId);
  }

  @Post(":id/aprovisionar-acceso")
  @ApiOperation({ summary: "Crear el primer usuario local + identidad + membresia de un tenant" })
  async aprovisionarAcceso(
    @Param("id", ParseIntPipe) id: number,
    @Body() dto: ProvisionarAccesoDto,
    @Request() req: any,
  ) {
    return this.tenantsAdminService.provisionarPrimerAcceso(id, dto, req.user.identidadId);
  }

  @Post(":id/activar")
  @ApiOperation({ summary: "Activar un tenant: exige acceso ok, 0 migraciones pendientes y 0 desviaciones graves" })
  async activar(@Param("id", ParseIntPipe) id: number) {
    return this.tenantsAdminService.activarTenant(id);
  }

  @Post(":id/reconciliar")
  @ApiOperation({ summary: "Aplicar el esquema pendiente de un tenant (nunca toca datos existentes)" })
  async reconciliar(@Param("id", ParseIntPipe) id: number, @Request() req: any) {
    return this.tenantsAdminService.reconciliar(id, req.user.identidadId);
  }

  @Post(":id/reconciliar-forzado")
  @ApiOperation({
    summary:
      "Re-correr el up() de TODAS las migraciones sin mirar la tabla migrations del tenant -- " +
      "para cuando esa tabla dice que todo esta aplicado pero el esquema real no lo refleja",
  })
  async reconciliarForzado(@Param("id", ParseIntPipe) id: number, @Request() req: any) {
    return this.tenantsAdminService.reconciliarForzado(id, req.user.identidadId);
  }

  @Get(":id/reconciliar-progreso")
  @ApiOperation({ summary: "Consultar cuantas migraciones ya se aplicaron mientras una reconciliacion esta corriendo" })
  async progresoReconciliacion(@Param("id", ParseIntPipe) id: number) {
    return this.tenantsAdminService.getProgresoReconciliacion(id);
  }
}
