import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Put,
  Query,
  UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiBody, ApiCreatedResponse, ApiOperation, ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { GetUser } from 'src/auth/get-user.decorator';
import { CreateProveedorDto } from './dto/create-proveedor.dto';
import { UpdateProveedorDto } from './dto/update-proveedor.dto';
import { ProveedoresService } from './proveedores.service';

@ApiTags('Proveedores')
@Controller({ path: 'proveedores', version: '1' })
export class ProveedoresController {
  constructor(private readonly proveedoresService: ProveedoresService) {}

  @Post()
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiBody({ type: CreateProveedorDto })
  @ApiCreatedResponse({ description: 'Proveedor creado exitosamente' })
  create(@Body() createProveedorDto: CreateProveedorDto, @GetUser() user: LoginUserInfo) {
    return this.proveedoresService.create(createProveedorDto, user.empresa_id, user.id);
  }

  @Get('search')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiQuery({ name: 'q', required: true })
  @ApiQuery({ name: 'limit', required: false })
  @ApiQuery({
    name: 'tipo_entidad',
    required: false,
    description:
      'Filtra por tipo de entidad (CSV admite múltiples): PROVEEDOR_LOCAL, PROVEEDOR_EXTERIOR, ACREEDOR_VARIO',
  })
  @ApiQuery({
    name: 'rubro_id',
    required: false,
    description: 'Rubro en contexto. Devuelve los proveedores del rubro más los que no tienen rubro asignado.',
  })
  async search(
    @GetUser() user: LoginUserInfo,
    @Query('q') query: string,
    @Query('limit') limit?: string,
    @Query('tipo_entidad') tipo_entidad?: string,
    @Query('rubro_id') rubro_id?: string,
  ) {
    const tipos = tipo_entidad
      ? (tipo_entidad
          .split(',')
          .map((t) => t.trim())
          .filter(Boolean) as any)
      : undefined;
    const proveedores = await this.proveedoresService.search(query, user.empresa_id, Number(limit) || 20, {
      ...(tipos ? { tipo_entidad: tipos } : {}),
      rubro_id: rubro_id || null,
      usuario_id: user.id,
    });
    return {
      message: 'Búsqueda realizada exitosamente',
      data: proveedores,
    };
  }

  @Get()
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiQuery({ name: 'page', type: 'string', required: false, description: 'Pagina actual' })
  @ApiQuery({ name: 'limit', type: 'string', required: false, description: 'Limit' })
  @ApiQuery({ name: 'q', required: false, description: 'Busca por razón social, RUC o documento' })
  @ApiQuery({
    name: 'tipo_entidad',
    required: false,
    description:
      'Filtra por tipo de entidad (CSV admite múltiples): PROVEEDOR_LOCAL, PROVEEDOR_EXTERIOR, ACREEDOR_VARIO',
  })
  @ApiQuery({
    name: 'rubro_id',
    required: false,
    description: 'Rubro en contexto. Devuelve los proveedores del rubro más los que no tienen rubro asignado.',
  })
  @ApiCreatedResponse({ description: 'Listado de proveedores' })
  findAll(
    @GetUser() user: LoginUserInfo,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
    @Query('q') q?: string,
    @Query('tipo_entidad') tipo_entidad?: string,
    @Query('rubro_id') rubro_id?: string,
  ) {
    const tipos = tipo_entidad
      ? (tipo_entidad
          .split(',')
          .map((t) => t.trim())
          .filter(Boolean) as any)
      : undefined;
    return this.proveedoresService.findAll(Number(page) || 1, Number(limit) || 10, user.empresa_id, q, {
      ...(tipos ? { tipo_entidad: tipos } : {}),
      rubro_id: rubro_id || null,
      usuario_id: user.id,
    });
  }

  @Get('reporte-clasificacion')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiQuery({ name: 'tipo_entidad', required: false, description: 'CSV: PROVEEDOR_LOCAL,PROVEEDOR_EXTERIOR,ACREEDOR_VARIO' })
  @ApiQuery({ name: 'activo', required: false, description: 'true|false' })
  async reporteClasificacion(
    @GetUser() user: LoginUserInfo,
    @Query('tipo_entidad') tipo_entidad?: string,
    @Query('activo') activo?: string,
  ) {
    const tipos = tipo_entidad
      ? (tipo_entidad
          .split(',')
          .map((t) => t.trim())
          .filter(Boolean) as any)
      : undefined;
    const activoFiltro = activo == null || activo === '' ? undefined : activo === 'true';
    const data = await this.proveedoresService.reporteClasificacion(user.empresa_id, {
      tipo_entidad: tipos,
      activo: activoFiltro,
    });
    return { message: 'Reporte de clasificación', data };
  }

  @Get(':id')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiParam({ name: 'id', type: 'string', required: true, description: 'ID del proveedor' })
  @ApiCreatedResponse({ description: 'Proveedor encontrado exitosamente' })
  findOne(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.proveedoresService.findOne(id, user.empresa_id);
  }

  @Put('activar-desactivar/:id')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiParam({ name: 'id', type: 'string', required: true, description: 'ID del proveedor' })
  @ApiCreatedResponse({ description: 'Proveedor activado/desactivado' })
  activarDesactivar(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.proveedoresService.activarDesactivar(id, user.empresa_id, user.id);
  }

  @Put(':id')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiParam({ name: 'id', type: 'string', required: true, description: 'ID del proveedor' })
  @ApiBody({ type: UpdateProveedorDto })
  @ApiCreatedResponse({ description: 'Proveedor actualizado' })
  update(@Param('id') id: string, @Body() updateProveedorDto: UpdateProveedorDto, @GetUser() user: LoginUserInfo) {
    return this.proveedoresService.update(id, updateProveedorDto, user.empresa_id, user.id);
  }

  @Patch(':id/tipo-entidad')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiParam({ name: 'id', type: 'string', required: true, description: 'ID del proveedor' })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['tipo_entidad'],
      properties: {
        tipo_entidad: {
          type: 'string',
          enum: ['PROVEEDOR_LOCAL', 'PROVEEDOR_EXTERIOR', 'ACREEDOR_VARIO'],
        },
        cuenta_contable_id: { type: 'string', nullable: true },
        motivo: { type: 'string' },
      },
    },
  })
  @ApiCreatedResponse({ description: 'Tercero reclasificado' })
  reclasificarTipoEntidad(
    @Param('id') id: string,
    @Body() dto: { tipo_entidad: string; cuenta_contable_id?: string | null; motivo?: string },
    @GetUser() user: LoginUserInfo,
  ) {
    return this.proveedoresService.reclasificarTipoEntidad(id, dto, user.empresa_id, user.id);
  }

  @Put(':id/rubros')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiParam({ name: 'id', type: 'string', required: true, description: 'ID del proveedor' })
  @ApiOperation({
    summary: 'Reemplaza el set de rubros del proveedor',
    description: 'Lista vacía = proveedor de todos los rubros. Ver docs/plan-rubros-multi-sucursal.md.',
  })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['rubro_ids'],
      properties: { rubro_ids: { type: 'array', items: { type: 'string' } } },
    },
  })
  setRubros(@Param('id') id: string, @Body() dto: { rubro_ids: string[] }, @GetUser() user: LoginUserInfo) {
    return this.proveedoresService.setRubros(id, dto?.rubro_ids ?? [], user.empresa_id, user.id);
  }

  @Delete(':id')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiParam({ name: 'id', type: 'string', required: true, description: 'ID del proveedor' })
  @ApiCreatedResponse({ description: 'Proveedor eliminado' })
  remove(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.proveedoresService.remove(id, user.empresa_id, user.id);
  }
}
