// otp.controller.ts

import {
  BadRequestException,
  Body,
  Controller,
  Post,
} from "@nestjs/common";


import { OtpService, OtpTarget } from "./otp.service";
import { Public } from "@edr/api-common";

// At least one of phone/email must be present. When BOTH are given the code is
// sent to both and either one verifies it — the caller no longer picks a single
// channel, it just states every address it knows for the account.
function toTarget(phone?: string, email?: string): OtpTarget {
  const target: OtpTarget = {};
  if (email?.trim()) target.email = email;
  if (phone?.trim()) target.phone = phone;
  if (!target.email && !target.phone) {
    throw new BadRequestException("phone or email is required");
  }
  return target;
}

// TODO: these public routes need per-target + per-IP rate limiting (a NestJS
// ThrottlerGuard / @Throttle on /otp/send and /otp/verify). No Throttler is
// wired into the app yet; add @nestjs/throttler and apply it here.
@Controller("otp")
@Public()
export class OtpController {
  constructor(
    private readonly otpService: OtpService
  ) {}

  // ---------------------------------------------------------------------------
  // Send OTP
  // ---------------------------------------------------------------------------

  @Post("send")
  async sendOtp(
    @Body("phone")
    phone?: string,

    @Body("email")
    email?: string
  ) {
    // `delivered` stays server-side: this route is @Public(), and whether our
    // broker accepted the publish is infrastructure state an anonymous caller has
    // no need for. It is on the `otp.dispatch` log line instead.
    const { success, message } = await this.otpService.sendOtp(
      toTarget(phone, email)
    );
    return { success, message };
  }

  // ---------------------------------------------------------------------------
  // Verify OTP
  // ---------------------------------------------------------------------------

  @Post("verify")
  async verifyOtp(
    @Body("phone")
    phone: string | undefined,

    @Body("email")
    email: string | undefined,

    @Body("otp")
    otp: string
  ) {
    return this.otpService.verifyOtp(
      toTarget(phone, email),
      otp
    );
  }
}