import {
  Controller,
  Get,
  Post,
  Patch,
  Delete,
  Body,
  Param,
  Query,
  ParseIntPipe,
  Req,
  Res,
  Logger,
  UploadedFile,
  UseInterceptors,
  BadRequestException,
  Header,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';

import { LeadService } from './services/lead.service';
import { CreateLeadDto } from './dto/create-lead.dto';
import { UpdateLeadDto } from './dto/update-lead.dto';
import { AssignLeadDto } from './dto/assign-lead.dto';
import {
  ListLeadsQueryDto,
  KanbanQueryDto,
  KanbanLoadMoreQueryDto,
} from './dto/list-leads.dto';
import { BulkUpdateLeadDto, BulkDestroyLeadDto } from './dto/bulk-update-lead.dto';
import { CheckDuplicatesDto, RequestHandoverDto } from './dto/check-duplicates.dto';

@Controller('leads')
export class LeadController {
  private readonly logger = new Logger('LeadController');

  constructor(private readonly service: LeadService) {}

  private getCurrentUser(req: Request): { id: number; name: string } {
    const user = (req as any).user;
    const id = user?.id ?? user?.userId ?? user?.sub;
    if (id === undefined || id === null) {
      throw new Error('User id not found on request.user (JwtAuthGuard / strategy issue?)');
    }
    const name =
      user?.name ??
      [user?.firstName, user?.lastName].filter(Boolean).join(' ') ??
      user?.email ??
      'Unknown user';
    return { id: Number(id), name };
  }

  // ═══════════════════ LIST + KANBAN + ANALYTICS ═══════════════════

  // GET /leads
  @Get()
  list(@Query() q: ListLeadsQueryDto, @Req() req: Request) {
    const { id } = this.getCurrentUser(req);
    return this.service.findAll(q, id);
  }

  // GET /leads/analytics
  @Get('analytics')
  analytics(@Req() req: Request) {
    const { id } = this.getCurrentUser(req);
    return this.service.getAnalytics(id);
  }

  // 🆕 GET /leads/client-groups — options for the dropdown.
  // Static routes must be declared before @Get(':id') or Nest will try to
  // parse "client-groups" as an id.
  @Get('client-groups')
  clientGroups() {
    return this.service.clientGroupOptions();
  }

  // GET /leads/tags — distinct tag suggestions
  @Get('tags')
  tags() {
    return this.service.distinctTags();
  }

  // GET /leads/kanban
  @Get('kanban')
  kanban(@Query() q: KanbanQueryDto, @Req() req: Request) {
    const { id } = this.getCurrentUser(req);
    return this.service.kanban(q, id);
  }

  // GET /leads/kanban/load-more
  @Get('kanban/load-more')
  kanbanLoadMore(@Query() q: KanbanLoadMoreQueryDto, @Req() req: Request) {
    const { id } = this.getCurrentUser(req);
    return this.service.kanbanLoadMore(q, id);
  }

  // GET /leads/check-duplicates
  @Get('check-duplicates')
  checkDuplicates(@Query() q: CheckDuplicatesDto) {
    return this.service.checkDuplicates(q);
  }

  // ═══════════════════ CSV IMPORT ═══════════════════

  // GET /leads/import/template — download the CSV template
  @Get('import/template')
  @Header('Content-Type', 'text/csv; charset=UTF-8')
  @Header('Content-Disposition', 'attachment; filename="leads-import-template.csv"')
  importTemplate(@Res() res: Response) {
    res.send(this.service.getImportTemplateCsv());
  }

  // POST /leads/import — upload + process a CSV
  @Post('import')
  @UseInterceptors(FileInterceptor('file'))
  async importLeads(
    @UploadedFile() file: Express.Multer.File,
    @Body('skip_duplicates') skipDuplicates: string | undefined,
    @Body('default_assigned_to') defaultAssignedTo: string | undefined,
    @Req() req: Request,
  ) {
    if (!file) throw new BadRequestException('A CSV file is required (field name: "file").');
    const { id } = this.getCurrentUser(req);

    return this.service.importLeads(
      file.buffer.toString('utf-8'),
      {
        skipDuplicates: skipDuplicates === undefined ? true : skipDuplicates === 'true',
        defaultAssignedTo: defaultAssignedTo ? Number(defaultAssignedTo) : id,
      },
      id,
    );
  }

  // ═══════════════════ SINGLE-LEAD READ ═══════════════════

  // GET /leads/:id
  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number) {
    return this.service.findOne(id);
  }

  // ═══════════════════ WRITE ACTIONS ═══════════════════

  // POST /leads
  @Post()
  async create(@Body() dto: CreateLeadDto, @Req() req: Request) {
    const { id } = this.getCurrentUser(req);
    this.logger.log(
      `POST /leads — user=${id}, company=${dto.company}, group=${dto.client_group ?? '—'}`,
    );
    try {
      return await this.service.create(dto, id);
    } catch (err: any) {
      this.logger.error(`POST /leads failed: ${err.message}`);
      throw err;
    }
  }

  // PATCH /leads/:id
  @Patch(':id')
  update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateLeadDto, @Req() req: Request) {
    const { id: userId } = this.getCurrentUser(req);
    this.logger.log(`PATCH /leads/${id} — user=${userId}`);
    return this.service.update(id, dto, userId);
  }

  // 🆕 POST /leads/:id/assign ★ KEY ENDPOINT
  // Moves ownership, writes the activity entry, and fires the real-time
  // notification + email to the new owner (and an in-app heads-up to the
  // previous one). Mirrors POST /audit-requests/:id/schedule.
  @Post(':id/assign')
  assign(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: AssignLeadDto,
    @Req() req: Request,
  ) {
    const { id: userId } = this.getCurrentUser(req);
    this.logger.log(
      `POST /leads/${id}/assign — user=${userId}, to=${dto.assigned_to}`,
    );
    return this.service.assign(id, dto, userId);
  }

  // DELETE /leads/:id (soft delete)
  @Delete(':id')
  remove(@Param('id', ParseIntPipe) id: number, @Req() req: Request) {
    const { id: userId } = this.getCurrentUser(req);
    this.logger.log(`DELETE /leads/${id} — user=${userId}`);
    return this.service.remove(id, userId);
  }

  // POST /leads/:id/request-handover
  @Post(':id/request-handover')
  requestHandover(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: RequestHandoverDto,
    @Req() req: Request,
  ) {
    const { id: userId, name } = this.getCurrentUser(req);
    return this.service.requestHandover(id, dto, userId, name);
  }

  // ═══════════════════ BULK ACTIONS ═══════════════════

  // POST /leads/bulk-update
  @Post('bulk-update')
  bulkUpdate(@Body() dto: BulkUpdateLeadDto, @Req() req: Request) {
    const { id } = this.getCurrentUser(req);
    return this.service.bulkUpdate(dto, id);
  }

  // POST /leads/bulk-destroy
  @Post('bulk-destroy')
  bulkDestroy(@Body() dto: BulkDestroyLeadDto, @Req() req: Request) {
    const { id } = this.getCurrentUser(req);
    return this.service.bulkDestroy(dto, id);
  }
}
