import {
  Controller,
  Post,
  UseGuards,
  UsePipes,
  Param,
  Body,
  Get,
  Put,
  UseInterceptors,
  ClassSerializerInterceptor,
} from '@nestjs/common';

import { AuthGuard } from '../shared/auth.guard';
import { ValidationPipe } from '../shared/validation.pipe';
import { User } from '../user/user.decorator';
import {
  GameGroupDTO,
  PromotePlayerDTO,
  JoinFactionDTO,
  JoinGameGroupDTO,
} from './faction.dto';
import { FactionService } from './faction.service';
import { Roles, GameStates } from '../shared/guard.decorator';

@Controller('faction')
export class FactionController {
  constructor(private factionservice: FactionService) {}

  // takes gameId from the url to verify user role
  @Post('create-group/:id')
  @Roles('soldier')
  @GameStates('CREATED')
  @UsePipes(new ValidationPipe())
  async createGroup(
    @User('id') person,
    @Param('id') id: string,
    @Body() data: GameGroupDTO,
  ) {
    try {
      return this.factionservice.createGroup(person, id, data);
    } catch (error) {}
  }

  // id is faction ID
  @Get('get-groups/:id')
  async getGroups(@Param('id') id) {
    return this.factionservice.showGroups(id);
  }

  // takes gameId from the url to verify user role
  @Put('join-group/:id')
  @Roles('soldier')
  @GameStates('CREATED')
  async joinGroup(
    @User('id') person,
    @Param('id') id,
    @Body() data: JoinGameGroupDTO,
  ) {
    return this.factionservice.joinGroup(person, id, data);
  }

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('get-faction-members/:id')
  async getFactionMembers(@Param('id') factionId) {
    return this.factionservice.listFactionMembers(factionId);
  }

  // param game ID is passed to @Roles
  @Put('promote/:id')
  @Roles('admin')
  @GameStates('CREATED')
  @UsePipes(new ValidationPipe())
  promotePlayer(@Param('id') game, @Body() body: PromotePlayerDTO) {
    return this.factionservice.promotePlayer(body);
  }

  // used to join a faction
  // :id is the id of the game, and is needed for GameStates to check the state of the game
  @Put('join-faction/:id')
  @UseGuards(new AuthGuard())
  @GameStates('CREATED')
  @UsePipes(new ValidationPipe())
  joinFaction(
    @User('id') person,
    @Param('id') game,
    @Body() data: JoinFactionDTO,
  ) {
    return this.factionservice.joinFaction(person, data);
  }

  // check if person belongs to a faction in a game
  @Get('check-faction/:id')
  @UseGuards(new AuthGuard())
  checkFaction(@User('id') userId, @Param('id') gameId) {
    return this.factionservice.verifyUser(userId, gameId);
  }
}