import {
  Body,
  Controller,
  ForbiddenException,
  Get,
  HttpCode,
  Param,
  ParseIntPipe,
  ParseUUIDPipe,
  Patch,
  Post,
  Query,
} from '@nestjs/common';
import { ClsService } from 'nestjs-cls';
import { createZodDto } from 'nestjs-zod';
import {
  AprovarPedidoSchema,
  CancelPedidoSchema,
  CreatePedidoSchema,
  UpdatePedidoSchema,
  PedidoErpConsultaQuerySchema,
  PedidoListQuerySchema,
  RecusarPedidoSchema,
  type AprovarPedido,
  type CancelPedido,
  type CreatePedido,
  type UpdatePedido,
  type PedidoDetail,
  type PedidoErpConsultaQuery,
  type PedidoErpConsultaResponse,
  type PedidoListQuery,
  type PedidoListResponse,
  type RecusarPedido,
} from '@sar/api-interface';
import type { WorkspaceClsStore } from '../workspace/workspace.types';
import { OrdersService } from './orders.service';

class PedidoListQueryDto extends createZodDto(PedidoListQuerySchema) {}
class CreatePedidoDto extends createZodDto(CreatePedidoSchema) {}
class UpdatePedidoDto extends createZodDto(UpdatePedidoSchema) {}
class CancelPedidoDto extends createZodDto(CancelPedidoSchema) {}
class AprovarPedidoDto extends createZodDto(AprovarPedidoSchema) {}
class RecusarPedidoDto extends createZodDto(RecusarPedidoSchema) {}
class PedidoErpConsultaQueryDto extends createZodDto(PedidoErpConsultaQuerySchema) {}

@Controller({ path: 'orders' })
export class OrdersController {
  constructor(
    private readonly orders: OrdersService,
    private readonly cls: ClsService<WorkspaceClsStore>,
  ) {}

  @Get()
  list(@Query() query: PedidoListQueryDto): Promise<PedidoListResponse> {
    const parsed = PedidoListQuerySchema.parse(query) as PedidoListQuery;
    return this.orders.list(parsed);
  }

  @Post()
  @HttpCode(201)
  create(@Body() body: CreatePedidoDto): Promise<PedidoDetail> {
    const parsed = CreatePedidoSchema.parse(body) as CreatePedido;
    return this.orders.create(parsed);
  }

  @Patch(':id/transmit')
  transmit(@Param('id', ParseUUIDPipe) id: string): Promise<PedidoDetail> {
    return this.orders.transmit(id);
  }

  @Patch(':id/approve')
  approve(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() body: AprovarPedidoDto,
  ): Promise<PedidoDetail> {
    const role = this.cls.get('role') ?? 'rep';
    if (role === 'rep') throw new ForbiddenException('Apenas supervisores podem aprovar pedidos');
    const parsed = AprovarPedidoSchema.parse(body) as AprovarPedido;
    return this.orders.approve(id, parsed);
  }

  @Patch(':id/reject')
  reject(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() body: RecusarPedidoDto,
  ): Promise<PedidoDetail> {
    const role = this.cls.get('role') ?? 'rep';
    if (role === 'rep') throw new ForbiddenException('Apenas supervisores podem recusar pedidos');
    const parsed = RecusarPedidoSchema.parse(body) as RecusarPedido;
    return this.orders.reject(id, parsed);
  }

  @Patch(':id/cancel')
  cancel(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() body: CancelPedidoDto,
  ): Promise<PedidoDetail> {
    const parsed = CancelPedidoSchema.parse(body) as CancelPedido;
    return this.orders.cancel(id, parsed);
  }

  // Edição de orçamento (situa 0) — depois de transmitido não é mais editável
  @Patch(':id')
  update(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() body: UpdatePedidoDto,
  ): Promise<PedidoDetail> {
    const parsed = UpdatePedidoSchema.parse(body) as UpdatePedido;
    return this.orders.update(id, parsed);
  }

  @Get('erp/:idPedido')
  findOneErp(@Param('idPedido', ParseIntPipe) idPedido: number): Promise<PedidoDetail> {
    return this.orders.findOneErp(idPedido);
  }

  @Get('erp-consulta')
  listErpConsulta(@Query() query: PedidoErpConsultaQueryDto): Promise<PedidoErpConsultaResponse> {
    const parsed = PedidoErpConsultaQuerySchema.parse(query) as PedidoErpConsultaQuery;
    return this.orders.listErpConsulta(parsed);
  }

  @Get(':id')
  findOne(@Param('id', ParseUUIDPipe) id: string): Promise<PedidoDetail> {
    return this.orders.findOne(id);
  }
}
