import { Injectable, Inject, InternalServerErrorException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Logger } from "nestjs-pino";
import { getErrorMessage } from "@bff/core/utils/error.util";
import type {
  FreebitConfig,
  FreebitAuthRequest,
  FreebitAuthResponse,
} from "../interfaces/freebit.types";
import { FreebitError } from "./freebit-error.service";

@Injectable()
export class FreebitAuthService {
  private readonly config: FreebitConfig;
  private authKeyCache: { token: string; expiresAt: number } | null = null;

  constructor(
    private readonly configService: ConfigService,
    @Inject(Logger) private readonly logger: Logger
  ) {
    this.config = {
      baseUrl:
        this.configService.get<string>("FREEBIT_BASE_URL") || "https://i1.mvno.net/emptool/api",
      oemId: this.configService.get<string>("FREEBIT_OEM_ID") || "PASI",
      oemKey: this.configService.get<string>("FREEBIT_OEM_KEY") || "",
      timeout: this.configService.get<number>("FREEBIT_TIMEOUT") || 30000,
      retryAttempts: this.configService.get<number>("FREEBIT_RETRY_ATTEMPTS") || 3,
      detailsEndpoint:
        this.configService.get<string>("FREEBIT_DETAILS_ENDPOINT") || "/master/getAcnt/",
    };

    if (!this.config.oemKey) {
      this.logger.warn("FREEBIT_OEM_KEY is not configured. SIM management features will not work.");
    }

    this.logger.debug("Freebit auth service initialized", {
      baseUrl: this.config.baseUrl,
      oemId: this.config.oemId,
      hasOemKey: !!this.config.oemKey,
    });
  }

  /**
   * Get the current configuration
   */
  getConfig(): FreebitConfig {
    return this.config;
  }

  /**
   * Get authentication key (cached or fetch new one)
   */
  async getAuthKey(): Promise<string> {
    if (this.authKeyCache && this.authKeyCache.expiresAt > Date.now()) {
      return this.authKeyCache.token;
    }

    try {
      if (!this.config.oemKey) {
        throw new Error("Freebit API not configured: FREEBIT_OEM_KEY is missing");
      }

      const request: FreebitAuthRequest = {
        oemId: this.config.oemId,
        oemKey: this.config.oemKey,
      };

      // Ensure proper URL construction - remove double slashes
      const baseUrl = this.config.baseUrl.replace(/\/$/, '');
      const authUrl = `${baseUrl}/authOem/`;

      const response = await fetch(authUrl, {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: `json=${JSON.stringify(request)}`,
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const data = (await response.json()) as FreebitAuthResponse;
      const resultCode = data?.resultCode != null ? String(data.resultCode).trim() : undefined;
      const statusCode =
        data?.status?.statusCode != null ? String(data.status.statusCode).trim() : undefined;

      if (resultCode !== "100") {
        throw new FreebitError(
          `Authentication failed: ${data.status.message}`,
          resultCode,
          statusCode,
          data.status.message
        );
      }

      this.authKeyCache = { token: data.authKey, expiresAt: Date.now() + 50 * 60 * 1000 };
      this.logger.log("Successfully authenticated with Freebit API");
      return data.authKey;
    } catch (error: unknown) {
      const message = getErrorMessage(error);
      this.logger.error("Failed to authenticate with Freebit API", { error: message });
      throw new InternalServerErrorException("Failed to authenticate with Freebit API");
    }
  }

  /**
   * Clear cached authentication key
   */
  clearAuthCache(): void {
    this.authKeyCache = null;
    this.logger.debug("Cleared Freebit auth cache");
  }

  /**
   * Check if we have a valid cached auth key
   */
  hasValidAuthCache(): boolean {
    return !!(this.authKeyCache && this.authKeyCache.expiresAt > Date.now());
  }
}
