import {
  Body,
  Controller,
  Delete,
  Get,
  HttpCode,
  HttpStatus,
  Inject,
  NotFoundException,
  Param,
  Patch,
  Post,
  UseGuards,
} from '@nestjs/common';
import type { Brain } from '@mosaicstack/brain';
import { BRAIN } from '../brain/brain.tokens.js';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';
import {
  CreateMissionDto,
  UpdateMissionDto,
  CreateMissionTaskDto,
  UpdateMissionTaskDto,
} from './missions.dto.js';

@Controller('api/missions')
@UseGuards(AuthGuard)
export class MissionsController {
  constructor(@Inject(BRAIN) private readonly brain: Brain) {}

  // ── Missions CRUD (user-scoped) ──

  @Get()
  async list(@CurrentUser() user: { id: string }) {
    return this.brain.missions.findAllByUser(user.id);
  }

  @Get(':id')
  async findOne(@Param('id') id: string, @CurrentUser() user: { id: string }) {
    const mission = await this.brain.missions.findByIdAndUser(id, user.id);
    if (!mission) throw new NotFoundException('Mission not found');
    return mission;
  }

  @Post()
  async create(@Body() dto: CreateMissionDto, @CurrentUser() user: { id: string }) {
    return this.brain.missions.create({
      name: dto.name,
      description: dto.description,
      projectId: dto.projectId,
      userId: user.id,
      phase: dto.phase,
      milestones: dto.milestones,
      config: dto.config,
      status: dto.status,
    });
  }

  @Patch(':id')
  async update(
    @Param('id') id: string,
    @Body() dto: UpdateMissionDto,
    @CurrentUser() user: { id: string },
  ) {
    const existing = await this.brain.missions.findByIdAndUser(id, user.id);
    if (!existing) throw new NotFoundException('Mission not found');
    const mission = await this.brain.missions.update(id, dto);
    if (!mission) throw new NotFoundException('Mission not found');
    return mission;
  }

  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  async remove(@Param('id') id: string, @CurrentUser() user: { id: string }) {
    const existing = await this.brain.missions.findByIdAndUser(id, user.id);
    if (!existing) throw new NotFoundException('Mission not found');
    const deleted = await this.brain.missions.remove(id);
    if (!deleted) throw new NotFoundException('Mission not found');
  }

  // ── Mission Tasks sub-routes ──

  @Get(':missionId/tasks')
  async listTasks(@Param('missionId') missionId: string, @CurrentUser() user: { id: string }) {
    const mission = await this.brain.missions.findByIdAndUser(missionId, user.id);
    if (!mission) throw new NotFoundException('Mission not found');
    return this.brain.missionTasks.findByMissionAndUser(missionId, user.id);
  }

  @Get(':missionId/tasks/:taskId')
  async getTask(
    @Param('missionId') missionId: string,
    @Param('taskId') taskId: string,
    @CurrentUser() user: { id: string },
  ) {
    const mission = await this.brain.missions.findByIdAndUser(missionId, user.id);
    if (!mission) throw new NotFoundException('Mission not found');
    const task = await this.brain.missionTasks.findByIdAndUser(taskId, user.id);
    if (!task) throw new NotFoundException('Mission task not found');
    return task;
  }

  @Post(':missionId/tasks')
  async createTask(
    @Param('missionId') missionId: string,
    @Body() dto: CreateMissionTaskDto,
    @CurrentUser() user: { id: string },
  ) {
    const mission = await this.brain.missions.findByIdAndUser(missionId, user.id);
    if (!mission) throw new NotFoundException('Mission not found');
    return this.brain.missionTasks.create({
      missionId,
      taskId: dto.taskId,
      userId: user.id,
      status: dto.status,
      description: dto.description,
      notes: dto.notes,
      pr: dto.pr,
    });
  }

  @Patch(':missionId/tasks/:taskId')
  async updateTask(
    @Param('missionId') missionId: string,
    @Param('taskId') taskId: string,
    @Body() dto: UpdateMissionTaskDto,
    @CurrentUser() user: { id: string },
  ) {
    const mission = await this.brain.missions.findByIdAndUser(missionId, user.id);
    if (!mission) throw new NotFoundException('Mission not found');
    const existing = await this.brain.missionTasks.findByIdAndUser(taskId, user.id);
    if (!existing) throw new NotFoundException('Mission task not found');
    const updated = await this.brain.missionTasks.update(taskId, dto);
    if (!updated) throw new NotFoundException('Mission task not found');
    return updated;
  }

  @Delete(':missionId/tasks/:taskId')
  @HttpCode(HttpStatus.NO_CONTENT)
  async removeTask(
    @Param('missionId') missionId: string,
    @Param('taskId') taskId: string,
    @CurrentUser() user: { id: string },
  ) {
    const mission = await this.brain.missions.findByIdAndUser(missionId, user.id);
    if (!mission) throw new NotFoundException('Mission not found');
    const existing = await this.brain.missionTasks.findByIdAndUser(taskId, user.id);
    if (!existing) throw new NotFoundException('Mission task not found');
    const deleted = await this.brain.missionTasks.remove(taskId);
    if (!deleted) throw new NotFoundException('Mission task not found');
  }
}
