import {
  Controller,
  Get,
  Post,
  Put,
  Patch,
  Body,
  Param,
  Query,
  UseGuards,
  ParseUUIDPipe,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
  ApiResponse,
  ApiParam,
} from '@nestjs/swagger';
import { SipService } from './sip.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { ModuleGuard } from '../../common/guards/module.guard';
import { Roles, UserRole } from '../../common/decorators/roles.decorator';
import {
  CurrentUser,
  JwtPayload,
} from '../../common/decorators/current-user.decorator';
import { RequireModule } from '../../common/decorators/require-module.decorator';
import {
  CreateCallDto,
  FindCallsDto,
  UpdateCallStatusDto,
  CreateSipConfigDto,
  UpdateSipConfigDto,
  UpdateOwnSipAccountDto,
} from './dto';

@ApiTags('SIP')
@ApiBearerAuth()
@Controller('sip')
@UseGuards(JwtAuthGuard, ModuleGuard)
@RequireModule('sip')
export class SipController {
  constructor(private readonly sipService: SipService) {}

  // ─── Call endpoints ───────────────────────────────────────────────

  @Get('calls')
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'List call log with pagination and filters' })
  @ApiResponse({ status: 200, description: 'Paginated list of calls' })
  async findCalls(
    @CurrentUser() user: JwtPayload,
    @Query() query: FindCallsDto,
  ) {
    const params = this.applyTrainerFilter(user, query);
    return this.sipService.findCalls(user.clubId, params);
  }

  @Get('calls/stats')
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'Get call statistics (total, avg duration, answered rate)' })
  @ApiResponse({ status: 200, description: 'Call statistics' })
  async getCallStats(
    @CurrentUser() user: JwtPayload,
    @Query('trainerId') trainerId?: string,
    @Query('dateFrom') dateFrom?: string,
    @Query('dateTo') dateTo?: string,
  ) {
    const effectiveTrainerId =
      user.role === UserRole.TRAINER ? user.sub : trainerId;
    return this.sipService.getCallStats(
      user.clubId,
      effectiveTrainerId,
      dateFrom,
      dateTo,
    );
  }

  @Get('calls/:id')
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'Get call details by ID' })
  @ApiParam({ name: 'id', description: 'Call UUID' })
  @ApiResponse({ status: 200, description: 'Call details' })
  @ApiResponse({ status: 404, description: 'Call not found' })
  async findCallById(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.sipService.findCallById(user.clubId, id);
  }

  @Post('calls')
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'Create a new call record' })
  @ApiResponse({ status: 201, description: 'Call record created' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async createCall(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreateCallDto,
  ) {
    return this.sipService.createCall(user.clubId, user.sub, dto);
  }

  @Patch('calls/:id/status')
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'Update call status and timing' })
  @ApiParam({ name: 'id', description: 'Call UUID' })
  @ApiResponse({ status: 200, description: 'Call status updated' })
  @ApiResponse({ status: 404, description: 'Call not found' })
  async updateCallStatus(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateCallStatusDto,
  ) {
    return this.sipService.updateCallStatus(user.clubId, id, dto);
  }

  // ─── Config endpoints ─────────────────────────────────────────────

  @Get('config')
  @UseGuards(RolesGuard)
  @Roles(UserRole.CLUB_ADMIN)
  @ApiOperation({ summary: 'Get SIP configuration for the club' })
  @ApiResponse({ status: 200, description: 'SIP configuration' })
  @ApiResponse({ status: 404, description: 'SIP config not found' })
  async getConfig(@CurrentUser() user: JwtPayload) {
    return this.sipService.getConfig(user.clubId);
  }

  @Put('config')
  @UseGuards(RolesGuard)
  @Roles(UserRole.CLUB_ADMIN)
  @ApiOperation({ summary: 'Create or update SIP configuration for the club' })
  @ApiResponse({ status: 200, description: 'SIP configuration saved' })
  async upsertConfig(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreateSipConfigDto,
  ) {
    return this.sipService.upsertConfig(user.clubId, dto);
  }

  // ─── Account endpoints ────────────────────────────────────────────

  @Get('account')
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'Get current user SIP account' })
  @ApiResponse({ status: 200, description: 'SIP account details' })
  @ApiResponse({ status: 404, description: 'SIP account not found' })
  async getAccount(@CurrentUser() user: JwtPayload) {
    return this.sipService.getAccount(user.clubId, user.sub);
  }

  @Put('account')
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'Update own SIP account display name' })
  @ApiResponse({ status: 200, description: 'SIP account updated' })
  async upsertOwnAccount(
    @CurrentUser() user: JwtPayload,
    @Body() dto: UpdateOwnSipAccountDto,
  ) {
    return this.sipService.upsertAccount(user.clubId, user.sub, dto);
  }

  // ─── Private helpers ──────────────────────────────────────────────

  /**
   * For TRAINER role, force the trainerId filter to their own user ID.
   * COORDINATOR and MANAGER see all calls or use the provided filter.
   */
  private applyTrainerFilter(
    user: JwtPayload,
    query: FindCallsDto,
  ): FindCallsDto {
    if (user.role === UserRole.TRAINER) {
      return { ...query, trainerId: user.sub };
    }
    return query;
  }
}
