import { Body, Controller, Delete, Get, Param, Post, Put, Query, UseGuards, ValidationPipe } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import type { LoginUserInfo } from '../auth/dto/login.dto';
import { GetUser } from '../auth/get-user.decorator';
import { CreateCotizacionDto } from './dto/create-cotizacion.dto';
import { CreateEmpresaMonedaDto } from './dto/create-empresa-moneda.dto';
import { CreateMonedaDto } from './dto/create-moneda.dto';
import { UpdateCotizacionDto } from './dto/update-cotizacion.dto';
import { UpdateEmpresaMonedaDto } from './dto/update-empresa-moneda.dto';
import { UpdateMonedaDto } from './dto/update-moneda.dto';
import { MonedasService } from './monedas.service';

@ApiTags('Monedas')
@Controller({ version: '1', path: 'monedas' })
@UseGuards(AuthGuard('jwt'))
@ApiBearerAuth()
export class MonedasController {
  constructor(private readonly monedasService: MonedasService) {}

  // ==================== MONEDAS (Catálogo global) ====================

  @Post()
  @ApiOperation({ summary: 'Crear moneda (catálogo global)' })
  create(@Body(ValidationPipe) dto: CreateMonedaDto, @GetUser() user: LoginUserInfo) {
    return this.monedasService.createMoneda(dto, user.id);
  }

  @Get()
  @ApiOperation({ summary: 'Listar todas las monedas del catálogo' })
  @ApiQuery({ name: 'includeInactive', required: false, type: Boolean })
  findAll(@Query('includeInactive') includeInactive?: string) {
    return this.monedasService.findAllMonedas(includeInactive === 'true');
  }

  @Get('cotizacion-vigente')
  @ApiOperation({
    summary:
      'Obtener cotización vigente unificada (single source of truth). ' +
      'Cascada: contabilidad → facturación → fallback(1).',
  })
  @ApiQuery({ name: 'codigo', required: true, description: 'Código ISO (USD, BRL, EUR…)' })
  @ApiQuery({ name: 'fecha', required: false, description: 'YYYY-MM-DD (default: hoy)' })
  getCotizacionVigente(
    @GetUser() user: LoginUserInfo,
    @Query('codigo') codigo: string,
    @Query('fecha') fecha?: string,
  ) {
    return this.monedasService.getCotizacionVigente(
      user.empresa_id,
      codigo,
      fecha ? new Date(fecha) : undefined,
    );
  }

  @Get(':id')
  @ApiOperation({ summary: 'Obtener moneda por ID' })
  findOne(@Param('id') id: string) {
    return this.monedasService.findOneMoneda(id);
  }

  @Put(':id')
  @ApiOperation({ summary: 'Actualizar moneda' })
  update(@Param('id') id: string, @Body(ValidationPipe) dto: UpdateMonedaDto, @GetUser() user: LoginUserInfo) {
    return this.monedasService.updateMoneda(id, dto, user.id);
  }

  @Put(':id/toggle')
  @ApiOperation({ summary: 'Activar/Desactivar moneda' })
  toggle(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.monedasService.toggleMonedaStatus(id, user.id);
  }

  // ==================== EMPRESA MONEDAS ====================

  @Get('empresa/configuracion')
  @ApiOperation({ summary: 'Listar monedas configuradas para la empresa' })
  findEmpresaMonedas(@GetUser() user: LoginUserInfo) {
    return this.monedasService.findEmpresaMonedas(user.empresa_id);
  }

  @Post('empresa/configuracion')
  @ApiOperation({ summary: 'Agregar moneda a la empresa' })
  addEmpresaMoneda(@Body(ValidationPipe) dto: CreateEmpresaMonedaDto, @GetUser() user: LoginUserInfo) {
    return this.monedasService.addEmpresaMoneda(user.empresa_id, dto, user.id);
  }

  @Put('empresa/configuracion/:id')
  @ApiOperation({ summary: 'Actualizar configuración de moneda de empresa' })
  updateEmpresaMoneda(
    @Param('id') id: string,
    @Body(ValidationPipe) dto: UpdateEmpresaMonedaDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.monedasService.updateEmpresaMoneda(user.empresa_id, id, dto, user.id);
  }

  @Delete('empresa/configuracion/:id')
  @ApiOperation({ summary: 'Remover moneda de la empresa' })
  removeEmpresaMoneda(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.monedasService.removeEmpresaMoneda(user.empresa_id, id, user.id);
  }

  // ==================== COTIZACIONES ====================

  @Get('cotizaciones/lista')
  @ApiOperation({ summary: 'Listar cotizaciones de la empresa' })
  @ApiQuery({ name: 'moneda_id', required: false })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  findCotizaciones(
    @GetUser() user: LoginUserInfo,
    @Query('moneda_id') moneda_id?: string,
    @Query('limit') limit?: string,
  ) {
    return this.monedasService.findCotizaciones(user.empresa_id, moneda_id, limit ? parseInt(limit) : 30);
  }

  @Get('cotizaciones/fecha')
  @ApiOperation({ summary: 'Obtener cotización por fecha' })
  @ApiQuery({ name: 'moneda_id', required: true })
  @ApiQuery({ name: 'fecha', required: true })
  findCotizacionByFecha(
    @GetUser() user: LoginUserInfo,
    @Query('moneda_id') moneda_id: string,
    @Query('fecha') fecha: string,
  ) {
    return this.monedasService.findCotizacionByFecha(user.empresa_id, moneda_id, fecha);
  }

  @Get('cotizaciones/ultima/:moneda_id')
  @ApiOperation({ summary: 'Obtener última cotización de una moneda' })
  getUltimaCotizacion(@Param('moneda_id') moneda_id: string, @GetUser() user: LoginUserInfo) {
    return this.monedasService.getUltimaCotizacion(user.empresa_id, moneda_id);
  }

  @Post('cotizaciones')
  @ApiOperation({ summary: 'Registrar cotización' })
  createCotizacion(@Body(ValidationPipe) dto: CreateCotizacionDto, @GetUser() user: LoginUserInfo) {
    return this.monedasService.createCotizacion(user.empresa_id, dto, user.id);
  }

  @Put('cotizaciones/:id')
  @ApiOperation({ summary: 'Actualizar cotización' })
  updateCotizacion(
    @Param('id') id: string,
    @Body(ValidationPipe) dto: UpdateCotizacionDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.monedasService.updateCotizacion(user.empresa_id, id, dto, user.id);
  }

  @Delete('cotizaciones/:id')
  @ApiOperation({ summary: 'Eliminar cotización' })
  deleteCotizacion(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.monedasService.deleteCotizacion(user.empresa_id, id, user.id);
  }
}
