import {
  Controller,
  Get,
  Post,
  Patch,
  Body,
  Param,
  Query,
  UseGuards,
  ParseUUIDPipe,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
  ApiResponse,
  ApiParam,
} from '@nestjs/swagger';
import { SalesService } from './sales.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles, UserRole } from '../../common/decorators/roles.decorator';
import {
  CurrentUser,
  JwtPayload,
} from '../../common/decorators/current-user.decorator';
import { CreateSaleDto, UpdateSaleDto, FindSalesDto } from './dto';

@ApiTags('Sales')
@ApiBearerAuth()
@Controller('sales')
@UseGuards(JwtAuthGuard)
export class SalesController {
  constructor(private readonly salesService: SalesService) {}

  @Get()
  @ApiOperation({ summary: 'List sales with pagination and filters' })
  @ApiResponse({ status: 200, description: 'Paginated list of sales' })
  async findAll(
    @CurrentUser() user: JwtPayload,
    @Query() query: FindSalesDto,
  ) {
    const params = this.applyTrainerFilter(user, query);
    return this.salesService.findAll(user.clubId, params);
  }

  @Get('debts')
  @ApiOperation({ summary: 'List unpaid sales (debts)' })
  @ApiResponse({ status: 200, description: 'Paginated list of unpaid sales' })
  async getDebts(
    @CurrentUser() user: JwtPayload,
    @Query() query: FindSalesDto,
  ) {
    const params = this.applyTrainerFilter(user, query);
    return this.salesService.getDebts(user.clubId, params);
  }

  @Get('debts/summary')
  @ApiOperation({ summary: 'Get debt summary (total amount and count)' })
  @ApiResponse({ status: 200, description: 'Debt summary' })
  async getDebtsSummary(@CurrentUser() user: JwtPayload) {
    const trainerId =
      user.role === UserRole.TRAINER ? user.sub : undefined;
    return this.salesService.getDebtsSummary(user.clubId, trainerId);
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get sale by ID' })
  @ApiParam({ name: 'id', description: 'Sale UUID' })
  @ApiResponse({ status: 200, description: 'Sale details' })
  @ApiResponse({ status: 404, description: 'Sale not found' })
  async findById(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.salesService.findById(user.clubId, id);
  }

  @Post()
  @UseGuards(RolesGuard)
  @Roles(
    UserRole.TRAINER,
    UserRole.MANAGER,
    UserRole.RECEPTIONIST,
    UserRole.CLUB_ADMIN,
  )
  @ApiOperation({ summary: 'Create a new sale' })
  @ApiResponse({ status: 201, description: 'Sale created' })
  @ApiResponse({ status: 403, description: 'Insufficient role' })
  @ApiResponse({ status: 404, description: 'Client or package not found' })
  async create(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreateSaleDto,
  ) {
    return this.salesService.create(user.clubId, user.sub, dto);
  }

  @Patch(':id')
  @UseGuards(RolesGuard)
  @Roles(
    UserRole.TRAINER,
    UserRole.MANAGER,
    UserRole.RECEPTIONIST,
    UserRole.CLUB_ADMIN,
  )
  @ApiOperation({ summary: 'Update a pending sale' })
  @ApiParam({ name: 'id', description: 'Sale UUID' })
  @ApiResponse({ status: 200, description: 'Sale updated' })
  @ApiResponse({ status: 400, description: 'Sale is not in PENDING status' })
  @ApiResponse({ status: 404, description: 'Sale not found' })
  async update(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateSaleDto,
  ) {
    return this.salesService.update(user.clubId, id, dto);
  }

  @Post(':id/pay')
  @HttpCode(HttpStatus.OK)
  @UseGuards(RolesGuard)
  @Roles(UserRole.MANAGER, UserRole.RECEPTIONIST, UserRole.CLUB_ADMIN)
  @ApiOperation({ summary: 'Mark a sale as paid' })
  @ApiParam({ name: 'id', description: 'Sale UUID' })
  @ApiResponse({ status: 200, description: 'Sale marked as paid' })
  @ApiResponse({ status: 400, description: 'Sale is not in PENDING status' })
  @ApiResponse({ status: 404, description: 'Sale not found' })
  async markAsPaid(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.salesService.markAsPaid(user.clubId, id);
  }

  @Post(':id/cancel')
  @HttpCode(HttpStatus.OK)
  @UseGuards(RolesGuard)
  @Roles(UserRole.TRAINER, UserRole.MANAGER, UserRole.CLUB_ADMIN)
  @ApiOperation({ summary: 'Cancel a pending sale' })
  @ApiParam({ name: 'id', description: 'Sale UUID' })
  @ApiResponse({ status: 200, description: 'Sale cancelled' })
  @ApiResponse({ status: 400, description: 'Sale is not in PENDING status' })
  @ApiResponse({ status: 404, description: 'Sale not found' })
  async cancel(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.salesService.cancel(user.clubId, id);
  }

  @Post(':id/refund')
  @HttpCode(HttpStatus.OK)
  @UseGuards(RolesGuard)
  @Roles(UserRole.MANAGER, UserRole.CLUB_ADMIN)
  @ApiOperation({ summary: 'Refund a paid sale' })
  @ApiParam({ name: 'id', description: 'Sale UUID' })
  @ApiResponse({ status: 200, description: 'Sale refunded' })
  @ApiResponse({ status: 400, description: 'Sale is not in PAID status' })
  @ApiResponse({ status: 404, description: 'Sale not found' })
  async refund(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.salesService.refund(user.clubId, id);
  }

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