import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, UseGuards, ValidationPipe } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import { RequireModule } from 'src/auth/decorators/require-module.decorator';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { GetUser } from 'src/auth/get-user.decorator';
import { ModuleGuard } from 'src/auth/guards/module.guard';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import {
  CreateComponenteCostoDto,
  CreateConceptoCostoDto,
  CreateDespachoDto,
  CreateEmbarqueDto,
  CreateItemEmbarqueDto,
  CreateTasaIscDto,
  GenerarCxPDto,
  LiberarEmbarqueDto,
  UpdateComponenteCostoDto,
  UpdateConceptoCostoDto,
  UpdateDespachoDto,
  UpdateEmbarqueDto,
  UpdateEstadoEmbarqueDto,
  UpdateImportacionesConfigDto,
  UpdateItemEmbarqueDto,
  UpdateTasaIscDto,
} from './dto/importaciones.dto';
import { ImportacionesCxPService } from './services/importaciones-cxp.service';
import { ImportacionesIscService } from './services/importaciones-isc.service';
import { ImportacionesService } from './services/importaciones.service';

@ApiTags('Importaciones')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), ModuleGuard)
@RequireModule('IMPORTACIONES')
@Controller({ path: 'importaciones', version: '1' })
export class ImportacionesController {
  constructor(
    private readonly service: ImportacionesService,
    private readonly iscService: ImportacionesIscService,
    private readonly cxpService: ImportacionesCxPService,
  ) {}

  @Get('config')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_VER')
  @ApiOperation({ summary: 'Obtener configuración operativa de importaciones por empresa' })
  getConfig(@GetUser() user: LoginUserInfo) {
    return this.service.getConfig(user.empresa_id);
  }

  @Put('config')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_EDITAR')
  @ApiOperation({ summary: 'Actualizar configuración operativa de importaciones por empresa' })
  updateConfig(
    @Body(new ValidationPipe({ transform: true, skipMissingProperties: true })) dto: UpdateImportacionesConfigDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.updateConfig(user.empresa_id, dto, user.id);
  }

  @Get('productos/search')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_VER')
  @ApiOperation({ summary: 'Buscar productos internos para vincular ítems importados' })
  @ApiQuery({ name: 'q', required: true })
  @ApiQuery({ name: 'limit', required: false })
  searchProductos(@GetUser() user: LoginUserInfo, @Query('q') q?: string, @Query('limit') limit?: string) {
    return this.service.searchProductos(user.empresa_id, q, limit);
  }

  @Get('embarques')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_VER')
  @ApiOperation({ summary: 'Listar embarques de importación' })
  @ApiQuery({ name: 'page', required: false })
  @ApiQuery({ name: 'limit', required: false })
  @ApiQuery({ name: 'perfil', required: false })
  @ApiQuery({ name: 'estado', required: false })
  @ApiQuery({ name: 'proveedor_id', required: false })
  @ApiQuery({ name: 'search', required: false })
  findAll(
    @GetUser() user: LoginUserInfo,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
    @Query('perfil') perfil?: string,
    @Query('estado') estado?: string,
    @Query('proveedor_id') proveedor_id?: string,
    @Query('search') search?: string,
  ) {
    return this.service.findAll(user.empresa_id, { page, limit, perfil, estado, proveedor_id, search });
  }

  @Post('embarques')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_CREAR')
  @ApiOperation({ summary: 'Crear embarque de importación' })
  create(@Body(new ValidationPipe({ transform: true })) dto: CreateEmbarqueDto, @GetUser() user: LoginUserInfo) {
    return this.service.create(dto, user.empresa_id, user.id);
  }

  @Get('embarques/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_VER')
  @ApiOperation({ summary: 'Detalle de embarque de importación' })
  findOne(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.findOne(id, user.empresa_id);
  }

  @Patch('embarques/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_EDITAR')
  @ApiOperation({ summary: 'Actualizar cabecera de embarque' })
  update(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true, skipMissingProperties: true })) dto: UpdateEmbarqueDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.update(id, dto, user.empresa_id, user.id);
  }

  @Patch('embarques/:id/estado')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_EDITAR')
  @ApiOperation({ summary: 'Actualizar estado del embarque' })
  updateEstado(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true })) dto: UpdateEstadoEmbarqueDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.updateEstado(id, dto, user.empresa_id, user.id);
  }

  @Delete('embarques/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_ELIMINAR')
  @ApiOperation({ summary: 'Eliminar embarque (soft delete)' })
  remove(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.remove(id, user.empresa_id, user.id);
  }

  @Get('embarques/:id/bitacora')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_VER')
  @ApiOperation({ summary: 'Bitácora del expediente: eventos cronológicos del embarque' })
  getBitacora(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.getBitacora(id, user.empresa_id);
  }

  @Post('embarques/:id/items')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_EDITAR')
  @ApiOperation({ summary: 'Agregar ítem al embarque y recalcular costo' })
  addItem(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true })) dto: CreateItemEmbarqueDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.addItem(id, dto, user.empresa_id, user.id);
  }

  @Patch('embarques/:id/items/:itemId')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_EDITAR')
  @ApiOperation({ summary: 'Actualizar ítem del embarque y recalcular costo' })
  updateItem(
    @Param('id') id: string,
    @Param('itemId') itemId: string,
    @Body(new ValidationPipe({ transform: true, skipMissingProperties: true })) dto: UpdateItemEmbarqueDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.updateItem(id, itemId, dto, user.empresa_id, user.id);
  }

  @Delete('embarques/:id/items/:itemId')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_EDITAR')
  @ApiOperation({ summary: 'Eliminar ítem del embarque y recalcular costo' })
  removeItem(@Param('id') id: string, @Param('itemId') itemId: string, @GetUser() user: LoginUserInfo) {
    return this.service.removeItem(id, itemId, user.empresa_id, user.id);
  }

  @Get('conceptos')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_COS_COSTO_VER')
  @ApiOperation({ summary: 'Listar conceptos base de costo (sistema + empresa)' })
  @ApiQuery({ name: 'perfil', required: false, description: 'Filtra por perfil aplicable (AUTOS | CONSUMO_MASIVO)' })
  getConceptos(@GetUser() user: LoginUserInfo, @Query('perfil') perfil?: string) {
    return this.service.getConceptos(user.empresa_id, perfil);
  }

  @Post('conceptos')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_EDITAR')
  @ApiOperation({ summary: 'Crear concepto de costo propio de la empresa' })
  createConcepto(
    @Body(new ValidationPipe({ transform: true })) dto: CreateConceptoCostoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.crearConcepto(dto, user.empresa_id);
  }

  @Patch('conceptos/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_EDITAR')
  @ApiOperation({ summary: 'Editar concepto de costo propio de la empresa' })
  updateConcepto(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true, skipMissingProperties: true })) dto: UpdateConceptoCostoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.actualizarConcepto(id, dto, user.empresa_id);
  }

  @Delete('conceptos/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_EDITAR')
  @ApiOperation({ summary: 'Desactivar concepto de costo propio de la empresa' })
  removeConcepto(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.eliminarConcepto(id, user.empresa_id);
  }

  @Post('embarques/:id/costos')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_COS_COSTO_CREAR')
  @ApiOperation({ summary: 'Agregar componente de costo y recalcular' })
  addCosto(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true })) dto: CreateComponenteCostoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.addCosto(id, dto, user.empresa_id, user.id);
  }

  @Patch('embarques/:id/costos/:costoId')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_COS_COSTO_EDITAR')
  @ApiOperation({ summary: 'Actualizar componente de costo y recalcular' })
  updateCosto(
    @Param('id') id: string,
    @Param('costoId') costoId: string,
    @Body(new ValidationPipe({ transform: true, skipMissingProperties: true })) dto: UpdateComponenteCostoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.updateCosto(id, costoId, dto, user.empresa_id, user.id);
  }

  @Delete('embarques/:id/costos/:costoId')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_COS_COSTO_EDITAR')
  @ApiOperation({ summary: 'Eliminar componente de costo y recalcular' })
  removeCosto(@Param('id') id: string, @Param('costoId') costoId: string, @GetUser() user: LoginUserInfo) {
    return this.service.removeCosto(id, costoId, user.empresa_id, user.id);
  }

  // ── Fase 2: Despacho aduanero ──────────────────────────────────────

  @Get('embarques/:id/despachos')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_DES_DESPACHO_VER')
  @ApiOperation({ summary: 'Obtener el despacho aduanero del embarque (si existe)' })
  getDespacho(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.getDespacho(id, user.empresa_id);
  }

  @Post('embarques/:id/despachos')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_DES_DESPACHO_CREAR')
  @ApiOperation({ summary: 'Crear despacho aduanero (BORRADOR)' })
  createDespacho(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true })) dto: CreateDespachoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.createDespacho(id, dto, user.empresa_id, user.id);
  }

  @Patch('embarques/:id/despachos/:despachoId')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_DES_DESPACHO_EDITAR')
  @ApiOperation({ summary: 'Actualizar despacho aduanero (sólo BORRADOR)' })
  updateDespacho(
    @Param('id') id: string,
    @Param('despachoId') despachoId: string,
    @Body(new ValidationPipe({ transform: true, skipMissingProperties: true })) dto: UpdateDespachoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.updateDespacho(id, despachoId, dto, user.empresa_id, user.id);
  }

  @Delete('embarques/:id/despachos/:despachoId')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_DES_DESPACHO_ELIMINAR')
  @ApiOperation({ summary: 'Eliminar despacho aduanero (sólo BORRADOR)' })
  removeDespacho(
    @Param('id') id: string,
    @Param('despachoId') despachoId: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.removeDespacho(id, despachoId, user.empresa_id, user.id);
  }

  @Post('embarques/:id/despachos/:despachoId/confirmar')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_DES_DESPACHO_PROCESAR')
  @ApiOperation({
    summary:
      'Confirmar despacho: congela cotización, inserta tributos como componentes, recalcula costos y dispara asiento contable',
  })
  confirmarDespacho(
    @Param('id') id: string,
    @Param('despachoId') despachoId: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.confirmarDespacho(id, despachoId, user.empresa_id, user.id);
  }

  @Post('embarques/:id/despachos/:despachoId/reintegrar-contabilidad')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_DES_DESPACHO_PROCESAR')
  @ApiOperation({
    summary:
      'Reintentar el asiento contable de un despacho CONFIRMADO cuya integración no se generó (idempotente)',
  })
  reintegrarContabilidadDespacho(
    @Param('id') id: string,
    @Param('despachoId') despachoId: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.reintegrarContabilidadDespacho(id, despachoId, user.empresa_id);
  }

  @Post('embarques/:id/liberar')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_EMB_EMBARQUE_CERRAR')
  @ApiOperation({
    summary: 'Liberar embarque (DESPACHADO → LIBERADO): crea producto/stock por chasis y registra movimientos',
  })
  liberarEmbarque(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true })) dto: LiberarEmbarqueDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.liberarEmbarque(id, dto, user.empresa_id, user.id);
  }

  // ── Fase 2: Generación de CxP por componente ───────────────────────

  @Post('embarques/:id/costos/:costoId/generar-cxp')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_COS_COSTO_EDITAR')
  @ApiOperation({ summary: 'Generar Cuentas por Pagar a partir de un componente de costo' })
  generarCxP(
    @Param('id') id: string,
    @Param('costoId') costoId: string,
    @Body(new ValidationPipe({ transform: true })) dto: GenerarCxPDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.cxpService.generarCxP(id, costoId, dto, user.empresa_id, user.id);
  }

  // ── Fase 2: Tasas ISC vehículos administrables ─────────────────────

  @Get('isc-vehiculos')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_VER')
  @ApiOperation({ summary: 'Listar tasas ISC vehículos vigentes (sistema + empresa)' })
  listIsc(@GetUser() user: LoginUserInfo) {
    return this.iscService.findAll(user.empresa_id);
  }

  @Post('isc-vehiculos')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_EDITAR')
  @ApiOperation({ summary: 'Crear tasa ISC vehículos para la empresa' })
  createIsc(
    @Body(new ValidationPipe({ transform: true })) dto: CreateTasaIscDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.iscService.create(user.empresa_id, dto);
  }

  @Patch('isc-vehiculos/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_EDITAR')
  @ApiOperation({ summary: 'Actualizar tasa ISC vehículos de la empresa' })
  updateIsc(
    @Param('id') id: string,
    @Body(new ValidationPipe({ transform: true, skipMissingProperties: true })) dto: UpdateTasaIscDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.iscService.update(user.empresa_id, id, dto);
  }

  @Delete('isc-vehiculos/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('IMPORTACIONES', 'IMP_CFG_CONFIG_EDITAR')
  @ApiOperation({ summary: 'Eliminar tasa ISC vehículos de la empresa' })
  removeIsc(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.iscService.remove(user.empresa_id, id);
  }
}
