import { Injectable } from "@nestjs/common";
import type {
  WhmcsClientResponse,
  WhmcsCreateSsoTokenParams,
  WhmcsValidateLoginParams,
  WhmcsAddClientParams,
} from "@customer-portal/domain/customer";
import type {
  WhmcsGetInvoicesParams,
  WhmcsCreateInvoiceParams,
  WhmcsUpdateInvoiceParams,
  WhmcsCapturePaymentParams,
} from "@customer-portal/domain/billing";
import type { WhmcsGetPayMethodsParams } from "@customer-portal/domain/payments";
import type { WhmcsGetClientsProductsParams } from "@customer-portal/domain/subscriptions";
import type {
  WhmcsInvoiceListResponse,
  WhmcsInvoiceResponse,
  WhmcsCreateInvoiceResponse,
  WhmcsUpdateInvoiceResponse,
  WhmcsCapturePaymentResponse,
} from "@customer-portal/domain/billing";
import type {
  WhmcsAddClientResponse,
  WhmcsValidateLoginResponse,
  WhmcsSsoResponse,
} from "@customer-portal/domain/customer";
import type { WhmcsProductListResponse } from "@customer-portal/domain/subscriptions";
import type {
  WhmcsPaymentMethodListResponse,
  WhmcsPaymentGatewayListResponse,
} from "@customer-portal/domain/payments";
import type { WhmcsCatalogProductListResponse } from "@customer-portal/domain/catalog";
import { WhmcsHttpClientService } from "./whmcs-http-client.service";
import { WhmcsConfigService } from "../config/whmcs-config.service";
import type { WhmcsRequestOptions } from "../types/connection.types";

/**
 * Service containing all WHMCS API method implementations
 * Organized by functional area (clients, invoices, payments, etc.)
 */
@Injectable()
export class WhmcsApiMethodsService {
  constructor(
    private readonly httpClient: WhmcsHttpClientService,
    private readonly configService: WhmcsConfigService
  ) {}

  // ==========================================
  // HEALTH CHECK METHODS
  // ==========================================

  /**
   * Perform health check on WHMCS API
   */
  async healthCheck(): Promise<boolean> {
    try {
      await this.makeRequest("GetProducts", { limitnum: 1 });
      return true;
    } catch {
      return false;
    }
  }

  /**
   * Check if WHMCS service is available
   */
  async isAvailable(): Promise<boolean> {
    return this.healthCheck();
  }

  /**
   * Get WHMCS system information
   */
  async getSystemInfo(): Promise<unknown> {
    return this.makeRequest("GetProducts", { limitnum: 1 });
  }

  // ==========================================
  // CLIENT API METHODS
  // ==========================================

  async getClientDetails(clientId: number): Promise<WhmcsClientResponse> {
    return this.makeRequest<WhmcsClientResponse>("GetClientsDetails", {
      clientid: clientId,
      stats: true, // Required by some WHMCS versions to include defaultpaymethodid
    });
  }

  async getClientDetailsByEmail(email: string): Promise<WhmcsClientResponse> {
    return this.makeRequest<WhmcsClientResponse>("GetClientsDetails", {
      email,
      stats: true,
    });
  }

  async updateClient(
    clientId: number,
    updateData: Partial<WhmcsClientResponse["client"]>
  ): Promise<{ result: string }> {
    return this.makeRequest<{ result: string }>("UpdateClient", {
      clientid: clientId,
      ...updateData,
    });
  }

  async addClient(params: WhmcsAddClientParams): Promise<WhmcsAddClientResponse> {
    return this.makeRequest("AddClient", params);
  }

  async validateLogin(params: WhmcsValidateLoginParams): Promise<WhmcsValidateLoginResponse> {
    return this.makeRequest("ValidateLogin", params);
  }

  // ==========================================
  // INVOICE API METHODS
  // ==========================================

  async getInvoices(params: WhmcsGetInvoicesParams = {}): Promise<WhmcsInvoiceListResponse> {
    return this.makeRequest("GetInvoices", params);
  }

  async getInvoice(invoiceId: number): Promise<WhmcsInvoiceResponse> {
    return this.makeRequest("GetInvoice", { invoiceid: invoiceId });
  }

  // ==========================================
  // PRODUCT/SUBSCRIPTION API METHODS
  // ==========================================

  async getClientsProducts(
    params: WhmcsGetClientsProductsParams
  ): Promise<WhmcsProductListResponse> {
    return this.makeRequest("GetClientsProducts", params);
  }

  async getCatalogProducts(): Promise<WhmcsCatalogProductListResponse> {
    return this.makeRequest("GetProducts", {});
  }

  // ==========================================
  // PAYMENT API METHODS
  // ==========================================

  async getPaymentMethods(
    params: WhmcsGetPayMethodsParams
  ): Promise<WhmcsPaymentMethodListResponse> {
    return this.makeRequest("GetPayMethods", params);
  }

  async getPaymentGateways(): Promise<WhmcsPaymentGatewayListResponse> {
    return this.makeRequest("GetPaymentMethods", {});
  }

  async createInvoice(params: WhmcsCreateInvoiceParams): Promise<WhmcsCreateInvoiceResponse> {
    return this.makeRequest("CreateInvoice", params);
  }

  async updateInvoice(params: WhmcsUpdateInvoiceParams): Promise<WhmcsUpdateInvoiceResponse> {
    return this.makeRequest("UpdateInvoice", params);
  }

  async capturePayment(params: WhmcsCapturePaymentParams): Promise<WhmcsCapturePaymentResponse> {
    return this.makeRequest("CapturePayment", params);
  }

  // ==========================================
  // ORDER API METHODS (Used by order services)
  // ==========================================

  async addOrder(params: Record<string, unknown>) {
    return this.makeRequest("AddOrder", params);
  }

  async getOrders(params: Record<string, unknown> = {}) {
    return this.makeRequest("GetOrders", params);
  }

  // ==========================================
  // ADMIN API METHODS (require admin permissions on API key)
  // ==========================================

  /**
   * Accept and provision an order
   * Note: Your API key must have AcceptOrder permission granted
   */
  async acceptOrder(orderId: number): Promise<{ result: string }> {
    return this.makeRequest<{ result: string }>("AcceptOrder", {
      orderid: orderId.toString(),
      autosetup: true,
      sendemail: false,
    });
  }

  /**
   * Cancel an order
   * Note: Your API key must have CancelOrder permission granted
   */
  async cancelOrder(orderId: number): Promise<{ result: string }> {
    return this.makeRequest<{ result: string }>("CancelOrder", {
      orderid: orderId,
    });
  }

  // ==========================================
  // SSO API METHODS
  // ==========================================

  async createSsoToken(params: WhmcsCreateSsoTokenParams): Promise<WhmcsSsoResponse> {
    return this.makeRequest("CreateSsoToken", params);
  }

  async getProducts() {
    return this.makeRequest("GetProducts", {});
  }

  async getCurrencies() {
    return this.makeRequest("GetCurrencies", {});
  }

  // ==========================================
  // PRIVATE HELPER METHODS
  // ==========================================

  /**
   * Make a request using the HTTP client
   */
  private async makeRequest<T>(
    action: string,
    params: Record<string, unknown>,
    options: WhmcsRequestOptions = {}
  ): Promise<T> {
    const config = this.configService.getConfig();
    const response = await this.httpClient.makeRequest<T>(config, action, params, options);
    return response.data as T;
  }
}
