import { Controller, Post, Body, UseGuards, Res, Req, HttpCode } from "@nestjs/common";
import type { Request, Response } from "express";
import { createZodDto } from "nestjs-zod";

import { RateLimitGuard, RateLimit, getRequestFingerprint } from "@bff/core/rate-limiting/index.js";
import { SalesforceWriteThrottleGuard } from "@bff/integrations/salesforce/guards/salesforce-write-throttle.guard.js";
import { Public } from "../../decorators/public.decorator.js";

import {
  sendVerificationCodeRequestSchema,
  sendVerificationCodeResponseSchema,
  verifyCodeRequestSchema,
  verifyCodeResponseSchema,
  guestEligibilityRequestSchema,
  guestEligibilityResponseSchema,
  completeAccountRequestSchema,
  signupWithEligibilityRequestSchema,
  signupWithEligibilityResponseSchema,
  migrateWhmcsAccountRequestSchema,
} from "@customer-portal/domain/get-started";
import type { User } from "@customer-portal/domain/customer";

import { GetStartedWorkflowService } from "../../infra/workflows/get-started-workflow.service.js";
import { setAuthCookies, buildSessionInfo, type SessionInfo } from "./utils/auth-cookie.util.js";

// DTO classes using Zod schemas
class SendVerificationCodeRequestDto extends createZodDto(sendVerificationCodeRequestSchema) {}
class SendVerificationCodeResponseDto extends createZodDto(sendVerificationCodeResponseSchema) {}
class VerifyCodeRequestDto extends createZodDto(verifyCodeRequestSchema) {}
class VerifyCodeResponseDto extends createZodDto(verifyCodeResponseSchema) {}
class GuestEligibilityRequestDto extends createZodDto(guestEligibilityRequestSchema) {}
class GuestEligibilityResponseDto extends createZodDto(guestEligibilityResponseSchema) {}
class CompleteAccountRequestDto extends createZodDto(completeAccountRequestSchema) {}
class SignupWithEligibilityRequestDto extends createZodDto(signupWithEligibilityRequestSchema) {}
class SignupWithEligibilityResponseDto extends createZodDto(signupWithEligibilityResponseSchema) {}
class MigrateWhmcsAccountRequestDto extends createZodDto(migrateWhmcsAccountRequestSchema) {}

interface AuthSuccessResponse {
  user: User;
  session: SessionInfo;
}

/**
 * Get Started Controller
 *
 * Handles the unified "Get Started" flow:
 * - Email verification via OTP
 * - Account status detection
 * - Guest eligibility check (no OTP required)
 * - Account completion (SF-only users)
 * - Signup with eligibility (full flow)
 *
 * All endpoints are public (no authentication required)
 */
@Controller("auth/get-started")
export class GetStartedController {
  constructor(private readonly workflow: GetStartedWorkflowService) {}

  /**
   * Send OTP verification code to email
   */
  @Public()
  @Post("send-code")
  @HttpCode(200)
  @UseGuards(RateLimitGuard)
  @RateLimit({ limit: 5, ttl: 300 })
  async sendVerificationCode(
    @Body() body: SendVerificationCodeRequestDto,
    @Req() req: Request
  ): Promise<SendVerificationCodeResponseDto> {
    const fingerprint = getRequestFingerprint(req);
    return this.workflow.sendVerificationCode(body, fingerprint);
  }

  /**
   * Verify OTP code and determine account status
   */
  @Public()
  @Post("verify-code")
  @HttpCode(200)
  @UseGuards(RateLimitGuard)
  @RateLimit({ limit: 10, ttl: 300 })
  async verifyCode(
    @Body() body: VerifyCodeRequestDto,
    @Req() req: Request
  ): Promise<VerifyCodeResponseDto> {
    const fingerprint = getRequestFingerprint(req);
    return this.workflow.verifyCode(body, fingerprint);
  }

  /**
   * Guest eligibility check - NO email verification required
   *
   * Creates SF Account + eligibility case without OTP verification.
   * Email verification happens later when they create an account.
   */
  @Public()
  @Post("guest-eligibility")
  @HttpCode(200)
  @UseGuards(RateLimitGuard, SalesforceWriteThrottleGuard)
  @RateLimit({ limit: 3, ttl: 900 })
  async guestEligibilityCheck(
    @Body() body: GuestEligibilityRequestDto,
    @Req() req: Request
  ): Promise<GuestEligibilityResponseDto> {
    const fingerprint = getRequestFingerprint(req);
    return this.workflow.guestEligibilityCheck(body, fingerprint);
  }

  /**
   * Complete account for SF-only users
   *
   * Creates WHMCS client and Portal user, links to existing SF account.
   * Returns auth tokens (sets httpOnly cookies).
   */
  @Public()
  @Post("complete-account")
  @HttpCode(200)
  @UseGuards(RateLimitGuard, SalesforceWriteThrottleGuard)
  @RateLimit({ limit: 5, ttl: 900 })
  async completeAccount(
    @Body() body: CompleteAccountRequestDto,
    @Res({ passthrough: true }) res: Response
  ): Promise<AuthSuccessResponse> {
    const result = await this.workflow.completeAccount(body);

    setAuthCookies(res, result.tokens);

    return {
      user: result.user,
      session: buildSessionInfo(result.tokens),
    };
  }

  /**
   * Full signup with eligibility check (inline flow)
   *
   * Creates SF Account + Case + WHMCS + Portal in one operation.
   * This is the primary signup path from the eligibility check page.
   * Returns auth tokens (sets httpOnly cookies) on success.
   */
  @Public()
  @Post("signup-with-eligibility")
  @HttpCode(200)
  @UseGuards(RateLimitGuard, SalesforceWriteThrottleGuard)
  @RateLimit({ limit: 5, ttl: 900 })
  async signupWithEligibility(
    @Body() body: SignupWithEligibilityRequestDto,
    @Res({ passthrough: true }) res: Response
  ): Promise<
    | SignupWithEligibilityResponseDto
    | (AuthSuccessResponse & { success: true; eligibilityRequestId?: string })
  > {
    const result = await this.workflow.signupWithEligibility(body);

    if (!result.success || !result.authResult) {
      return {
        success: false,
        message: result.message,
      };
    }

    setAuthCookies(res, result.authResult.tokens);

    return {
      success: true,
      eligibilityRequestId: result.eligibilityRequestId,
      user: result.authResult.user,
      session: buildSessionInfo(result.authResult.tokens),
    };
  }

  /**
   * Migrate WHMCS account to portal (passwordless)
   *
   * For whmcs_unmapped users after email verification.
   * Email verification serves as identity proof - no legacy password needed.
   * Creates portal user, syncs password to WHMCS, and returns auth tokens.
   */
  @Public()
  @Post("migrate-whmcs-account")
  @HttpCode(200)
  @UseGuards(RateLimitGuard, SalesforceWriteThrottleGuard)
  @RateLimit({ limit: 5, ttl: 900 })
  async migrateWhmcsAccount(
    @Body() body: MigrateWhmcsAccountRequestDto,
    @Res({ passthrough: true }) res: Response
  ): Promise<AuthSuccessResponse> {
    const result = await this.workflow.migrateWhmcsAccount(body);

    setAuthCookies(res, result.tokens);

    return {
      user: result.user,
      session: buildSessionInfo(result.tokens),
    };
  }
}
