import { Injectable, Inject, BadRequestException } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { PrismaService } from "@bff/infra/database/prisma.service.js";
import { extractErrorMessage } from "@bff/core/utils/error.util.js";

export interface CreatePortalUserParams {
  email: string;
  passwordHash: string;
  sfAccountId: string;
  whmcsClientId: number;
}

export interface CreatePortalUserResult {
  userId: string;
}

/**
 * Step: Create a portal user with ID mapping.
 *
 * Creates both the User row and the IdMapping row atomically
 * in a single Prisma transaction.
 *
 * Rollback deletes the user and associated ID mapping.
 */
@Injectable()
export class CreatePortalUserStep {
  constructor(
    private readonly prisma: PrismaService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  async execute(params: CreatePortalUserParams): Promise<CreatePortalUserResult> {
    try {
      const result = await this.prisma.$transaction(async tx => {
        const created = await tx.user.create({
          data: {
            email: params.email,
            passwordHash: params.passwordHash,
            emailVerified: true,
            failedLoginAttempts: 0,
            lockedUntil: null,
            lastLoginAt: null,
          },
          select: { id: true, email: true },
        });

        await tx.idMapping.create({
          data: {
            userId: created.id,
            whmcsClientId: params.whmcsClientId,
            sfAccountId: params.sfAccountId,
          },
        });

        return { userId: created.id };
      });

      this.logger.log(
        {
          userId: result.userId,
          email: params.email,
          whmcsClientId: params.whmcsClientId,
          sfAccountId: params.sfAccountId,
        },
        "Portal user created with ID mapping"
      );

      return result;
    } catch (dbError) {
      this.logger.error(
        {
          whmcsClientId: params.whmcsClientId,
          email: params.email,
          error: extractErrorMessage(dbError),
        },
        "Database transaction failed"
      );

      throw new BadRequestException(
        `Failed to create user account: ${extractErrorMessage(dbError)}`
      );
    }
  }

  async rollback(userId: string): Promise<void> {
    this.logger.warn({ userId }, "Rolling back portal user creation");
    try {
      await this.prisma.$transaction(async tx => {
        await tx.idMapping.deleteMany({ where: { userId } });
        await tx.user.delete({ where: { id: userId } });
      });
      this.logger.log({ userId }, "Portal user and mapping deleted in rollback");
    } catch (error) {
      this.logger.error(
        { userId, error: extractErrorMessage(error) },
        "Failed to rollback portal user — manual cleanup required"
      );
    }
  }
}
