import {
  Controller,
  Get,
  HttpException,
  HttpStatus,
  Inject,
  Param,
  UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '../auth/auth.guard.js';
import { CurrentUser } from '../auth/current-user.decorator.js';
import { scopeFromUser, type AuthenticatedUserLike } from '../auth/session-scope.js';
import { HarnessAdapterUnavailableError, HarnessRegistry } from './harness.registry.js';
import { HARNESS_REGISTRY } from './harness.tokens.js';
import {
  readContextFromScope,
  toHarnessSummary,
  toSafeCatalog,
  type HarnessCatalogDto,
  type HarnessSummaryDto,
} from './harness.dto.js';

/**
 * Generic harness catalog surface. It exposes only harness-neutral, browser-safe
 * fields (identity, capabilities, provider/model catalog) — never executables,
 * native paths, home/cwd, env, or secrets. There is NO provider-probe route here;
 * `/api/providers` and `POST /api/providers/test` are intentionally out of scope.
 */
@Controller('api/harnesses')
@UseGuards(AuthGuard)
export class HarnessController {
  constructor(@Inject(HARNESS_REGISTRY) private readonly registry: HarnessRegistry) {}

  @Get()
  async list(@CurrentUser() user: AuthenticatedUserLike): Promise<HarnessSummaryDto[]> {
    const context = readContextFromScope(scopeFromUser(user));
    const summaries: HarnessSummaryDto[] = [];
    for (const adapter of this.registry.list()) {
      summaries.push(toHarnessSummary(await adapter.describe(context)));
    }
    return summaries;
  }

  @Get(':harnessId/catalog')
  async catalog(
    @CurrentUser() user: AuthenticatedUserLike,
    @Param('harnessId') harnessId: string,
  ): Promise<HarnessCatalogDto> {
    const context = readContextFromScope(scopeFromUser(user));
    let adapter;
    try {
      adapter = this.registry.get(harnessId);
    } catch (error) {
      if (error instanceof HarnessAdapterUnavailableError) {
        // Typed failure — NEVER a fallback catalog for an unknown harness id.
        throw new HttpException(
          { code: error.code, message: error.message, harnessId },
          HttpStatus.NOT_FOUND,
        );
      }
      throw error;
    }
    return toSafeCatalog(await adapter.catalog(context));
  }
}
