import { Body, Controller, Get, Param, Patch, Post, Res } from '@nestjs/common';
import { Response } from 'express';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { DunningLevel } from '@prisma/client';
import { IsBoolean, IsEnum, IsNumber, IsOptional, IsString } from 'class-validator';
import { DunningService } from './dunning.service';
import { Roles } from '../../common/decorators/roles.decorator';
import { CurrentUser, AuthenticatedUser } from '../../common/decorators/current-user.decorator';

class UpsertDunningRuleDto {
  @IsEnum(DunningLevel) level!: DunningLevel;
  @IsOptional() @IsNumber() daysAfterDue?: number;
  @IsOptional() @IsString() template?: string;
  @IsOptional() @IsNumber() penaltyRate?: number;
  @IsOptional() @IsBoolean() enabled?: boolean;
}

@ApiTags('dunning')
@ApiBearerAuth()
@Controller()
export class DunningController {
  constructor(private readonly service: DunningService) {}

  @Get('complexes/:complexId/dunning-rules')
  @Roles('SUPERADMIN', 'SYNDIC')
  list(@CurrentUser() user: AuthenticatedUser, @Param('complexId') complexId: string) {
    return this.service.listRules(user, complexId);
  }

  @Post('complexes/:complexId/dunning-rules/defaults')
  @Roles('SUPERADMIN', 'SYNDIC')
  seedDefaults(@CurrentUser() user: AuthenticatedUser, @Param('complexId') complexId: string) {
    return this.service.ensureDefaultRules(user, complexId);
  }

  @Patch('complexes/:complexId/dunning-rules')
  @Roles('SUPERADMIN', 'SYNDIC')
  upsert(
    @CurrentUser() user: AuthenticatedUser,
    @Param('complexId') complexId: string,
    @Body() dto: UpsertDunningRuleDto,
  ) {
    return this.service.upsertRule(user, complexId, dto.level, dto);
  }

  @Post('dunning/run-now')
  @Roles('SUPERADMIN', 'SYNDIC')
  runNow(@CurrentUser() user: AuthenticatedUser) {
    return this.service.triggerNow(user);
  }

  @Get('dunning/fund-call-items/:id/formal-notice.pdf')
  @Roles('SUPERADMIN', 'SYNDIC')
  async formalNoticePdf(
    @CurrentUser() user: AuthenticatedUser,
    @Param('id') fundCallItemId: string,
    @Res() res: Response,
  ) {
    const pdf = await this.service.generateFormalNoticePdf(user, fundCallItemId);
    if (!pdf) {
      res.status(404).send('No formal-notice-level dunning action for this item');
      return;
    }
    res
      .status(200)
      .type('application/pdf')
      .set('Content-Disposition', `inline; filename=formal-notice-${fundCallItemId}.pdf`)
      .send(pdf);
  }
}
