import {
  Body,
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Post,
  Put,
  Patch,
  ParseIntPipe,
  Query,
  Req,
  UseGuards,
} from '@nestjs/common';
import { TransactionsQueryDto } from 'src/transactions/dto/transactions-query.dto';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Roles } from 'src/roles/roles.decorator';
import { RoleEnum } from 'src/roles/roles.enum';
import { RolesGuard } from 'src/roles/roles.guard';
import { CreateTeamDTO } from './dto/create-team.dto';
import { TeamActivityRow, TeamsService } from './teams.service';
import { PublicTeamAccessService } from './public-team-access.service';
import { UpdatePublicAccessDto } from './dto/public-access.dto';
import { UpdatePlayerProfileDto } from './dto/update-player-profile.dto';
import { PlayerActiveDto, PlayerTeamRoleDto } from './dto/player-management.dto';
import { UpdateTeamPermissionsDto } from './dto/team-permissions.dto';
import { TeamMembersService } from './team-members.service';
import { TeamPermissionsService } from './team-permissions.service';

@ApiTags('Teams')
@Controller({
  path: 'teams',
  version: '1',
})
export class TeamsController {
  constructor(
    private service: TeamsService,
    private publicAccess: PublicTeamAccessService,
    private teamMembers: TeamMembersService,
    private teamPermissions: TeamPermissionsService,
  ) {}

  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Get(':id/public-access')
  getPublicAccess(@Req() req, @Param('id', ParseIntPipe) id: number) {
    return this.publicAccess.getStatus(Number(req.user.id), id);
  }

  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Patch(':id/public-access')
  setPublicAccess(
    @Req() req,
    @Param('id', ParseIntPipe) id: number,
    @Body() body: UpdatePublicAccessDto,
  ) {
    return this.publicAccess.setEnabled(Number(req.user.id), id, body.enabled);
  }

  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Post(':id/public-access/rotate')
  rotatePublicAccess(@Req() req, @Param('id', ParseIntPipe) id: number) {
    return this.publicAccess.rotate(Number(req.user.id), id);
  }

  @ApiOperation({
    summary: 'Team-Berechtigungen abrufen',
    description:
      'Gibt die pro Team konfigurierte Mindestrolle je Aktion zurück.',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Get(':id/permissions')
  getPermissions(@Req() req, @Param('id', ParseIntPipe) id: number) {
    return this.teamPermissions.getPermissions(Number(req.user.id), id);
  }

  @ApiOperation({
    summary: 'Team-Berechtigungen ändern',
    description:
      'Setzt die Mindestrolle je Aktion für dieses Team. Nur Team-Manager (Kapitän aufwärts).',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Patch(':id/permissions')
  updatePermissions(
    @Req() req,
    @Param('id', ParseIntPipe) id: number,
    @Body() body: UpdateTeamPermissionsDto,
  ) {
    return this.teamPermissions.updatePermissions(Number(req.user.id), id, body);
  }

  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Get(':id/players/:playerId/transactions')
  getPlayerTransactions(
    @Req() req,
    @Param('id', ParseIntPipe) id: number,
    @Param('playerId', ParseIntPipe) playerId: number,
  ) {
    return this.publicAccess.getMemberPlayerTransactions(
      Number(req.user.id),
      id,
      playerId,
    );
  }

  @ApiBearerAuth()
  @Roles([RoleEnum.user, RoleEnum.admin])
  @UseGuards(AuthGuard('jwt'), RolesGuard)
  @Get(':id/overview')
  @HttpCode(HttpStatus.OK)
  findOne(@Req() req, @Param('id') id: string) {
    return this.service.getOverview(id, req.user?.id);
  }

  @ApiBearerAuth()
  @Roles([RoleEnum.user, RoleEnum.admin])
  @UseGuards(AuthGuard('jwt'), RolesGuard)
  @Get(':id/overview/stats')
  @HttpCode(HttpStatus.OK)
  getOverviewStats(@Req() req, @Param('id') id: string) {
    const userId = req.user?.id;
    return this.service.getOverviewStats(id, userId);
  }

  @ApiOperation({
    summary: 'Transactionen für ein Team',
    description:
      'Gibt alle Transaktionen, Spieler und Teamwallet, für ein bestimmtes Team zurück und sortiert absteigend nach Datum',
  })
  @ApiBearerAuth()
  @Roles([RoleEnum.user, RoleEnum.admin])
  @UseGuards(AuthGuard('jwt'), RolesGuard)
  @Get(':id/transactions')
  @HttpCode(HttpStatus.OK)
  getAllTransactions(@Req() req, @Param('id') id: string) {
    const userId = req.user?.id;
    return this.service.getTeamTransactions(id, userId);
  }

  @ApiOperation({
    summary: 'Paginiertes Kassenjournal für ein Team',
    description:
      'Gibt Transaktionen (Spieler und Teamwallet) seitenweise zurück, mit serverseitiger Sortierung, Typ-Filter und Freitextsuche - für das AG-Grid-Journal.',
  })
  @ApiBearerAuth()
  @Roles([RoleEnum.user, RoleEnum.admin])
  @UseGuards(AuthGuard('jwt'), RolesGuard)
  @Get(':id/transactions/journal')
  @HttpCode(HttpStatus.OK)
  getTransactionsJournal(
    @Req() req,
    @Param('id') id: string,
    @Query() query: TransactionsQueryDto,
  ): Promise<{ data: TeamActivityRow[]; total: number }> {
    const userId = req.user?.id;
    return this.service.getTeamTransactionsJournal(id, userId, query);
  }

  @ApiOperation({
    summary: 'Neuen Spieler anlegen',
    description:
      'Erstellt einen neuen Spieler für das Team mit der ID aus der URL',
  })
  @ApiBearerAuth()
  @Roles([RoleEnum.user, RoleEnum.admin])
  @UseGuards(AuthGuard('jwt'), RolesGuard)
  @Post(':id/players')
  @HttpCode(HttpStatus.CREATED)
  createPlayer(
    @Req() req,
    @Param('id') id: string,
    @Body() playerDto: any,
  ) {
    return this.service.createNewPlayer(id, playerDto, req.user?.id);
  }

  @Roles([RoleEnum.user, RoleEnum.admin])
  @UseGuards(AuthGuard('jwt'), RolesGuard)
  @ApiOperation({
    summary: 'Spieler updaten',
    description: 'verändert den Spieler mit der team id',
  })
  @Put(':id/players')
  @HttpCode(HttpStatus.CREATED)
  updatePlayer(
    @Req() req,
    @Param('id') id: string,
    @Body() playerDto: UpdatePlayerProfileDto,
  ) {
    return this.service.updatePlayer(id, playerDto, req.user?.id);
  }

  @ApiOperation({
    summary: 'Spieler aktivieren/deaktivieren',
    description:
      'Setzt den Aktiv-Status eines Spielers. Bei Deaktivierung wird die offene Balance über eine Ausgleichsbuchung genullt.',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Patch(':id/players/:playerId/active')
  @HttpCode(HttpStatus.OK)
  setPlayerActive(
    @Req() req,
    @Param('id', ParseIntPipe) id: number,
    @Param('playerId', ParseIntPipe) playerId: number,
    @Body() dto: PlayerActiveDto,
  ) {
    return this.teamMembers.setActive(Number(req.user.id), id, playerId, dto.active);
  }

  @ApiOperation({
    summary: 'Team-Rolle eines Spielers ändern',
    description:
      'Ändert die Team-Rolle eines Spielers (z.B. Spieler -> Kassenwart). Blockiert, wenn dadurch kein aktiver Kassenwart mehr im Team verbleiben würde.',
  })
  @ApiBearerAuth()
  @UseGuards(AuthGuard('jwt'))
  @Patch(':id/players/:playerId/team-role')
  @HttpCode(HttpStatus.OK)
  setPlayerTeamRole(
    @Req() req,
    @Param('id', ParseIntPipe) id: number,
    @Param('playerId', ParseIntPipe) playerId: number,
    @Body() dto: PlayerTeamRoleDto,
  ) {
    return this.teamMembers.setTeamRole(
      Number(req.user.id),
      id,
      playerId,
      dto.teamRoleId,
    );
  }

  @ApiOperation({
    summary: 'Neues Team anlegen',
    description:
      'Erstellt ein neues Team mit gegebenem Namen und gibt es zurück.',
  })
  @ApiBearerAuth()
  @Roles([RoleEnum.user, RoleEnum.admin])
  @UseGuards(AuthGuard('jwt'), RolesGuard)
  @Post()
  @HttpCode(HttpStatus.CREATED)
  create(@Req() req, @Body() teamDto: CreateTeamDTO) {
    const userId = req.user?.id;
    return this.service.createNewTeam(teamDto, userId);
  }
}
