import {
  Controller,
  Get,
  Post,
  Put,
  Patch,
  Delete,
  Body,
  Param,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
} from '@nestjs/swagger';
import { CharactersService } from './characters.service';
import { PathbuilderImportService } from './pathbuilder-import.service';
import {
  CreateCharacterDto,
  UpdateCharacterDto,
  CreateAbilityDto,
  CreateSkillDto,
  CreateFeatDto,
  CreateSpellDto,
  CreateItemDto,
  UpdateItemDto,
  CreateConditionDto,
  CreateResourceDto,
  PathbuilderImportDto,
} from './dto';
import { CurrentUser } from '../../common/decorators/current-user.decorator';

@ApiTags('Characters')
@ApiBearerAuth()
@Controller('campaigns/:campaignId/characters')
export class CharactersController {
  constructor(
    private readonly charactersService: CharactersService,
    private readonly pathbuilderImportService: PathbuilderImportService,
  ) {}

  @Post()
  @ApiOperation({ summary: 'Create a new character' })
  @ApiResponse({ status: 201, description: 'Character created successfully' })
  async create(
    @Param('campaignId') campaignId: string,
    @Body() dto: CreateCharacterDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.create(campaignId, dto, userId);
  }

  @Post('import')
  @ApiOperation({ summary: 'Import character from Pathbuilder JSON' })
  @ApiResponse({ status: 201, description: 'Character imported successfully' })
  async importFromPathbuilder(
    @Param('campaignId') campaignId: string,
    @Body() dto: PathbuilderImportDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.pathbuilderImportService.importCharacter(
      campaignId,
      userId,
      dto.pathbuilderJson,
    );
  }

  @Get()
  @ApiOperation({ summary: 'Get all characters in a campaign' })
  @ApiResponse({ status: 200, description: 'List of characters' })
  async findAll(
    @Param('campaignId') campaignId: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.findAllByCampaign(campaignId, userId);
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get character by ID' })
  @ApiResponse({ status: 200, description: 'Character details' })
  @ApiResponse({ status: 404, description: 'Character not found' })
  async findOne(
    @Param('id') id: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.findOne(id, userId);
  }

  @Put(':id')
  @ApiOperation({ summary: 'Update character' })
  @ApiResponse({ status: 200, description: 'Character updated' })
  async update(
    @Param('id') id: string,
    @Body() dto: UpdateCharacterDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.update(id, dto, userId);
  }

  @Delete(':id')
  @ApiOperation({ summary: 'Delete character' })
  @ApiResponse({ status: 200, description: 'Character deleted' })
  async remove(
    @Param('id') id: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.remove(id, userId);
  }

  // HP Management
  @Patch(':id/hp')
  @ApiOperation({ summary: 'Update character HP' })
  async updateHp(
    @Param('id') id: string,
    @Body() body: { hpCurrent: number; hpTemp?: number },
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.updateHp(id, body.hpCurrent, body.hpTemp, userId);
  }

  // Credits Management
  @Patch(':id/credits')
  @ApiOperation({ summary: 'Update character credits' })
  async updateCredits(
    @Param('id') id: string,
    @Body() body: { credits: number },
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.updateCredits(id, body.credits, userId);
  }

  // Abilities
  @Put(':id/abilities')
  @ApiOperation({ summary: 'Set character abilities' })
  async setAbilities(
    @Param('id') id: string,
    @Body() abilities: CreateAbilityDto[],
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.setAbilities(id, abilities, userId);
  }

  // Skills
  @Put(':id/skills')
  @ApiOperation({ summary: 'Set character skills' })
  async setSkills(
    @Param('id') id: string,
    @Body() skills: CreateSkillDto[],
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.setSkills(id, skills, userId);
  }

  @Patch(':id/skills/:skillName')
  @ApiOperation({ summary: 'Update single skill proficiency' })
  async updateSkill(
    @Param('id') id: string,
    @Param('skillName') skillName: string,
    @Body() body: { proficiency: string },
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.updateSkill(id, skillName, body.proficiency, userId);
  }

  // Feats
  @Post(':id/feats')
  @ApiOperation({ summary: 'Add feat to character' })
  async addFeat(
    @Param('id') id: string,
    @Body() dto: CreateFeatDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.addFeat(id, dto, userId);
  }

  @Delete(':id/feats/:featId')
  @ApiOperation({ summary: 'Remove feat from character' })
  async removeFeat(
    @Param('id') id: string,
    @Param('featId') featId: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.removeFeat(id, featId, userId);
  }

  // Spells
  @Post(':id/spells')
  @ApiOperation({ summary: 'Add spell to character' })
  async addSpell(
    @Param('id') id: string,
    @Body() dto: CreateSpellDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.addSpell(id, dto, userId);
  }

  @Patch(':id/spells/:spellId')
  @ApiOperation({ summary: 'Update spell (prepared status)' })
  async updateSpell(
    @Param('id') id: string,
    @Param('spellId') spellId: string,
    @Body() body: { prepared: boolean },
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.updateSpell(id, spellId, body.prepared, userId);
  }

  @Delete(':id/spells/:spellId')
  @ApiOperation({ summary: 'Remove spell from character' })
  async removeSpell(
    @Param('id') id: string,
    @Param('spellId') spellId: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.removeSpell(id, spellId, userId);
  }

  // Items
  @Post(':id/items')
  @ApiOperation({ summary: 'Add item to character' })
  async addItem(
    @Param('id') id: string,
    @Body() dto: CreateItemDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.addItem(id, dto, userId);
  }

  @Patch(':id/items/:itemId')
  @ApiOperation({ summary: 'Update item (players can edit alias, GMs can edit custom properties)' })
  async updateItem(
    @Param('id') id: string,
    @Param('itemId') itemId: string,
    @Body() body: UpdateItemDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.updateItem(id, itemId, body, userId);
  }

  @Delete(':id/items/:itemId')
  @ApiOperation({ summary: 'Remove item from character' })
  async removeItem(
    @Param('id') id: string,
    @Param('itemId') itemId: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.removeItem(id, itemId, userId);
  }

  // Conditions
  @Post(':id/conditions')
  @ApiOperation({ summary: 'Add condition to character' })
  async addCondition(
    @Param('id') id: string,
    @Body() dto: CreateConditionDto,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.addCondition(id, dto, userId);
  }

  @Patch(':id/conditions/:conditionId')
  @ApiOperation({ summary: 'Update condition value' })
  async updateCondition(
    @Param('id') id: string,
    @Param('conditionId') conditionId: string,
    @Body() body: { value: number },
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.updateCondition(id, conditionId, body.value, userId);
  }

  @Delete(':id/conditions/:conditionId')
  @ApiOperation({ summary: 'Remove condition from character' })
  async removeCondition(
    @Param('id') id: string,
    @Param('conditionId') conditionId: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.removeCondition(id, conditionId, userId);
  }

  // Resources
  @Put(':id/resources')
  @ApiOperation({ summary: 'Set character resources' })
  async setResources(
    @Param('id') id: string,
    @Body() resources: CreateResourceDto[],
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.setResources(id, resources, userId);
  }

  @Patch(':id/resources/:resourceName')
  @ApiOperation({ summary: 'Update resource current value' })
  async updateResource(
    @Param('id') id: string,
    @Param('resourceName') resourceName: string,
    @Body() body: { current: number },
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.updateResource(id, resourceName, body.current, userId);
  }

  // Rest System
  @Get(':id/rest/preview')
  @ApiOperation({ summary: 'Preview what will happen when resting' })
  @ApiResponse({ status: 200, description: 'Rest preview data' })
  async getRestPreview(
    @Param('id') id: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.getRestPreview(id, userId);
  }

  @Post(':id/rest')
  @ApiOperation({ summary: 'Perform a full rest (8 hours + daily preparation)' })
  @ApiResponse({ status: 200, description: 'Rest completed successfully' })
  async performRest(
    @Param('id') id: string,
    @CurrentUser('id') userId: string,
  ) {
    return this.charactersService.performRest(id, userId);
  }
}
