import { Body, Controller, Get, Param, Patch, Post, Query, Req, UseGuards, UsePipes, ValidationPipe } from '@nestjs/common';
import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { AuthGuard } from 'src/auth/auth.guard';
import { RolesGuard } from 'src/guard/role.guard';
import { Roles } from 'src/guard/decorators/role.decorator';
import { CommonService } from 'src/common/common.service';
import { PANEL_ROLES } from 'src/user/schema/users.schema';
import { LeadService } from './lead.service';
import { PolicyService } from 'src/policy/policy.service';
import { ConvertLeadToPolicyDto } from 'src/policy/dto/policy.dto';
import { AddLeadNoteDto, AssigneesDto, CreateLeadDto, LeadBoardDto, LeadListDto, MoveLeadStageDto, UpdateLeadDto } from './dto/lead.dto';

@ApiTags('Leads')
@ApiBearerAuth('access_token')
@UseGuards(AuthGuard, RolesGuard)
@Roles(...PANEL_ROLES)
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
@Controller('admin/leads')
export class LeadController {
    constructor(
        private readonly leadService: LeadService,
        private readonly policyService: PolicyService,
        private readonly common: CommonService
    ) { }

    @Post()
    @ApiOperation({ summary: 'Capture a lead. The customer is found or created by mobile. Starts in NEW.' })
    @ApiBody({ type: CreateLeadDto })
    create(@Req() req: any, @Body() dto: CreateLeadDto) {
        return this.leadService.create(dto, req.user_data, this.common.getUserLanguage(req));
    }

    @Get()
    @ApiOperation({ summary: 'List leads (filter by stage, assigned_to, category_id, customer_id, follow_up_due, search). Policy Staff see only their own.' })
    list(@Req() req: any, @Query() query: LeadListDto) {
        return this.leadService.list(query, req.user_data, this.common.getUserLanguage(req));
    }

    @Get('board')
    @ApiOperation({ summary: 'Kanban board: a column per stage (New, In Discussion, Quotation Shared, Converted, Lost) with counts' })
    board(@Req() req: any, @Query() query: LeadBoardDto) {
        return this.leadService.board(query, req.user_data, this.common.getUserLanguage(req));
    }

    @Get('assignees')
    @ApiOperation({ summary: 'People a lead can be assigned to: approved agents (for the category) and active Policy Staff' })
    assignees(@Req() req: any, @Query() query: AssigneesDto) {
        return this.leadService.assignees(query, req.user_data, this.common.getUserLanguage(req));
    }

    @Get(':id')
    @ApiOperation({ summary: 'Lead detail with customer, last call, next follow-up and history' })
    @ApiResponse({ status: 404, description: 'Lead not found (or not assigned to you)' })
    getById(@Req() req: any, @Param('id') id: string) {
        return this.leadService.getById(id, req.user_data, this.common.getUserLanguage(req));
    }

    @Patch(':id')
    @ApiOperation({ summary: 'Edit category, assignee, estimated premium or requirement notes' })
    @ApiBody({ type: UpdateLeadDto })
    update(@Req() req: any, @Param('id') id: string, @Body() dto: UpdateLeadDto) {
        return this.leadService.update(id, dto, req.user_data, this.common.getUserLanguage(req));
    }

    @Patch(':id/stage')
    @ApiOperation({ summary: 'Move a lead to another stage (drag on the board). A converted lead cannot be moved.' })
    @ApiBody({ type: MoveLeadStageDto })
    moveStage(@Req() req: any, @Param('id') id: string, @Body() dto: MoveLeadStageDto) {
        return this.leadService.moveStage(id, dto, req.user_data, this.common.getUserLanguage(req));
    }

    @Post(':id/notes')
    @ApiOperation({ summary: 'Add a note or log a call, and optionally set the next follow-up' })
    @ApiBody({ type: AddLeadNoteDto })
    addNote(@Req() req: any, @Param('id') id: string, @Body() dto: AddLeadNoteDto) {
        return this.leadService.addNote(id, dto, req.user_data, this.common.getUserLanguage(req));
    }

    @Post(':id/convert-to-policy')
    @ApiOperation({ summary: 'Convert a lead: records the policy for the lead\'s customer and moves the lead to CONVERTED. The product must be in the lead\'s category.' })
    @ApiBody({ type: ConvertLeadToPolicyDto })
    @ApiResponse({ status: 400, description: 'Lead already converted, duplicate policy number, bad dates, or product not in the lead\'s category' })
    convertToPolicy(@Req() req: any, @Param('id') id: string, @Body() dto: ConvertLeadToPolicyDto) {
        return this.policyService.convertLead(id, dto, req.user_data, this.common.getUserLanguage(req));
    }
}
