import {
  BadRequestException,
  Controller,
  Get,
  Inject,
  NotFoundException,
  Param,
  Query,
  UseGuards,
} from '@nestjs/common';
import fs from 'node:fs';
import path from 'node:path';
import { AuthGuard } from '../auth/auth.guard.js';
import { CoordService } from './coord.service.js';

/** Walk up from cwd to find the monorepo root (has pnpm-workspace.yaml). */
function findMonorepoRoot(start: string): string {
  let dir = start;
  for (let i = 0; i < 5; i++) {
    try {
      fs.accessSync(path.join(dir, 'pnpm-workspace.yaml'));
      return dir;
    } catch {
      const parent = path.dirname(dir);
      if (parent === dir) break;
      dir = parent;
    }
  }
  return start;
}

/** Only paths under these roots are allowed for coord queries. */
const WORKSPACE_ROOT = process.env['MOSAIC_WORKSPACE_ROOT'] ?? findMonorepoRoot(process.cwd());
const ALLOWED_ROOTS = [process.cwd(), WORKSPACE_ROOT];

function resolveAndValidatePath(raw: string | undefined): string {
  const resolved = path.resolve(raw ?? process.cwd());
  const isAllowed = ALLOWED_ROOTS.some(
    (root) => resolved === root || resolved.startsWith(`${root}/`),
  );
  if (!isAllowed) {
    throw new BadRequestException('projectPath is outside the allowed workspace');
  }
  return resolved;
}

/**
 * File-based coord endpoints for agent tool consumption.
 * DB-backed mission CRUD has moved to MissionsController at /api/missions.
 */
@Controller('api/coord')
@UseGuards(AuthGuard)
export class CoordController {
  constructor(@Inject(CoordService) private readonly coordService: CoordService) {}

  @Get('status')
  async missionStatus(@Query('projectPath') projectPath?: string) {
    const resolvedPath = resolveAndValidatePath(projectPath);
    const status = await this.coordService.getMissionStatus(resolvedPath);
    if (!status) throw new NotFoundException('No active coord mission found');
    return status;
  }

  @Get('tasks')
  async listTasks(@Query('projectPath') projectPath?: string) {
    const resolvedPath = resolveAndValidatePath(projectPath);
    return this.coordService.listTasks(resolvedPath);
  }

  @Get('tasks/:taskId')
  async taskStatus(@Param('taskId') taskId: string, @Query('projectPath') projectPath?: string) {
    const resolvedPath = resolveAndValidatePath(projectPath);
    const detail = await this.coordService.getTaskStatus(resolvedPath, taskId);
    if (!detail) throw new NotFoundException(`Task ${taskId} not found in coord mission`);
    return detail;
  }
}
