/**
 * Identity Linking Controller
 *
 * API endpoints for cross-instance identity verification and management.
 */

import { Controller, Post, Get, Patch, Delete, Body, Param, UseGuards } from "@nestjs/common";
import { Throttle } from "@nestjs/throttler";
import { AuthGuard } from "../auth/guards/auth.guard";
import { IdentityLinkingService } from "./identity-linking.service";
import { IdentityResolutionService } from "./identity-resolution.service";
import { CurrentUser } from "../auth/decorators/current-user.decorator";
import type {
  VerifyIdentityDto,
  ResolveIdentityDto,
  BulkResolveIdentityDto,
  CreateIdentityMappingDto,
  UpdateIdentityMappingDto,
} from "./dto/identity-linking.dto";
import type {
  IdentityVerificationResponse,
  IdentityResolutionResponse,
  BulkIdentityResolutionResponse,
  IdentityMappingValidation,
} from "./types/identity-linking.types";
import type { FederatedIdentity } from "./types/oidc.types";

/**
 * User object from authentication
 */
interface AuthenticatedUser {
  id: string;
  email: string;
  name: string;
}

@Controller("federation/identity")
export class IdentityLinkingController {
  constructor(
    private readonly identityLinkingService: IdentityLinkingService,
    private readonly identityResolutionService: IdentityResolutionService
  ) {}

  /**
   * POST /api/v1/federation/identity/verify
   *
   * Verify a user's identity from a remote instance.
   * Validates signature and OIDC token.
   * Rate limit: "strict" tier (10 req/min) - public endpoint requiring authentication
   */
  @Post("verify")
  @UseGuards(AuthGuard)
  @Throttle({ strict: { limit: 10, ttl: 60000 } })
  async verifyIdentity(@Body() dto: VerifyIdentityDto): Promise<IdentityVerificationResponse> {
    return this.identityLinkingService.verifyIdentity(dto);
  }

  /**
   * POST /api/v1/federation/identity/resolve
   *
   * Resolve a remote user to a local user.
   */
  @Post("resolve")
  @UseGuards(AuthGuard)
  async resolveIdentity(@Body() dto: ResolveIdentityDto): Promise<IdentityResolutionResponse> {
    return this.identityResolutionService.resolveIdentity(dto.remoteInstanceId, dto.remoteUserId);
  }

  /**
   * POST /api/v1/federation/identity/bulk-resolve
   *
   * Bulk resolve multiple remote users to local users.
   */
  @Post("bulk-resolve")
  @UseGuards(AuthGuard)
  async bulkResolveIdentity(
    @Body() dto: BulkResolveIdentityDto
  ): Promise<BulkIdentityResolutionResponse> {
    return this.identityResolutionService.bulkResolveIdentities(
      dto.remoteInstanceId,
      dto.remoteUserIds
    );
  }

  /**
   * GET /api/v1/federation/identity/me
   *
   * Get the current user's federated identities.
   */
  @Get("me")
  @UseGuards(AuthGuard)
  async getCurrentUserIdentities(
    @CurrentUser() user: AuthenticatedUser
  ): Promise<FederatedIdentity[]> {
    return this.identityLinkingService.listUserIdentities(user.id);
  }

  /**
   * POST /api/v1/federation/identity/link
   *
   * Create a new identity mapping for the current user.
   */
  @Post("link")
  @UseGuards(AuthGuard)
  async createIdentityMapping(
    @CurrentUser() user: AuthenticatedUser,
    @Body() dto: CreateIdentityMappingDto
  ): Promise<FederatedIdentity> {
    return this.identityLinkingService.createIdentityMapping(user.id, dto);
  }

  /**
   * PATCH /api/v1/federation/identity/:remoteInstanceId
   *
   * Update an existing identity mapping.
   */
  @Patch(":remoteInstanceId")
  @UseGuards(AuthGuard)
  async updateIdentityMapping(
    @CurrentUser() user: AuthenticatedUser,
    @Param("remoteInstanceId") remoteInstanceId: string,
    @Body() dto: UpdateIdentityMappingDto
  ): Promise<FederatedIdentity> {
    return this.identityLinkingService.updateIdentityMapping(user.id, remoteInstanceId, dto);
  }

  /**
   * DELETE /api/v1/federation/identity/:remoteInstanceId
   *
   * Revoke an identity mapping.
   */
  @Delete(":remoteInstanceId")
  @UseGuards(AuthGuard)
  async revokeIdentityMapping(
    @CurrentUser() user: AuthenticatedUser,
    @Param("remoteInstanceId") remoteInstanceId: string
  ): Promise<{ success: boolean }> {
    await this.identityLinkingService.revokeIdentityMapping(user.id, remoteInstanceId);
    return { success: true };
  }

  /**
   * GET /api/v1/federation/identity/:remoteInstanceId/validate
   *
   * Validate an identity mapping exists and is valid.
   */
  @Get(":remoteInstanceId/validate")
  @UseGuards(AuthGuard)
  async validateIdentityMapping(
    @CurrentUser() user: AuthenticatedUser,
    @Param("remoteInstanceId") remoteInstanceId: string
  ): Promise<IdentityMappingValidation> {
    return this.identityLinkingService.validateIdentityMapping(user.id, remoteInstanceId);
  }
}
