import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import {
  Invoice,
  InvoiceList,
  InvoiceListQuery,
  InvoiceStatus,
  INVOICE_PAGINATION,
  VALID_INVOICE_STATUSES,
} from "@customer-portal/domain/billing";
import { InvoiceRetrievalService } from "./invoice-retrieval.service";
import { InvoiceHealthService } from "./invoice-health.service";
import type { InvoiceHealthStatus, InvoiceServiceStats } from "../types/invoice-monitoring.types";

/**
 * Main orchestrator service for invoice operations
 * Coordinates all invoice-related services and provides a unified interface
 */
@Injectable()
export class InvoicesOrchestratorService {
  constructor(
    private readonly retrievalService: InvoiceRetrievalService,
    private readonly healthService: InvoiceHealthService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  // ==========================================
  // INVOICE RETRIEVAL METHODS
  // ==========================================

  /**
   * Get paginated invoices for a user
   */
  async getInvoices(userId: string, options: InvoiceListQuery = {}): Promise<InvoiceList> {
    const startTime = Date.now();

    try {
      const result = await this.retrievalService.getInvoices(userId, options);
      this.healthService.recordInvoiceRetrieval(Date.now() - startTime);
      return result;
    } catch (error) {
      this.healthService.recordError();
      throw error;
    }
  }

  /**
   * Get individual invoice by ID
   */
  async getInvoiceById(userId: string, invoiceId: number): Promise<Invoice> {
    const startTime = Date.now();

    try {
      const result = await this.retrievalService.getInvoiceById(userId, invoiceId);
      this.healthService.recordInvoiceRetrieval(Date.now() - startTime);
      return result;
    } catch (error) {
      this.healthService.recordError();
      throw error;
    }
  }

  /**
   * Get invoices by status
   */
  async getInvoicesByStatus(
    userId: string,
    status: InvoiceStatus,
    options: Partial<InvoiceListQuery> = {}
  ): Promise<InvoiceList> {
    const startTime = Date.now();

    try {
      const result = await this.retrievalService.getInvoicesByStatus(userId, status, options);
      this.healthService.recordInvoiceRetrieval(Date.now() - startTime);
      return result;
    } catch (error) {
      this.healthService.recordError();
      throw error;
    }
  }

  /**
   * Get unpaid invoices for a user
   */
  async getUnpaidInvoices(
    userId: string,
    options: Partial<InvoiceListQuery> = {}
  ): Promise<InvoiceList> {
    return this.retrievalService.getUnpaidInvoices(userId, options);
  }

  /**
   * Get overdue invoices for a user
   */
  async getOverdueInvoices(
    userId: string,
    options: Partial<InvoiceListQuery> = {}
  ): Promise<InvoiceList> {
    return this.retrievalService.getOverdueInvoices(userId, options);
  }

  /**
   * Get paid invoices for a user
   */
  async getPaidInvoices(
    userId: string,
    options: Partial<InvoiceListQuery> = {}
  ): Promise<InvoiceList> {
    return this.retrievalService.getPaidInvoices(userId, options);
  }

  /**
   * Get cancelled invoices for a user
   */
  async getCancelledInvoices(
    userId: string,
    options: Partial<InvoiceListQuery> = {}
  ): Promise<InvoiceList> {
    return this.retrievalService.getCancelledInvoices(userId, options);
  }

  /**
   * Get invoices in collections for a user
   */
  async getCollectionsInvoices(
    userId: string,
    options: Partial<InvoiceListQuery> = {}
  ): Promise<InvoiceList> {
    return this.retrievalService.getCollectionsInvoices(userId, options);
  }

  // ==========================================
  // INVOICE OPERATIONS METHODS
  // ==========================================

  // ==========================================
  // UTILITY METHODS
  // ==========================================

  /**
   * Check if user has any invoices
   */
  async hasInvoices(userId: string): Promise<boolean> {
    return this.retrievalService.hasInvoices(userId);
  }

  /**
   * Get invoice count by status
   */
  async getInvoiceCountByStatus(userId: string, status: InvoiceStatus): Promise<number> {
    return this.retrievalService.getInvoiceCountByStatus(userId, status);
  }

  /**
   * Health check for invoice service
   */
  async healthCheck(): Promise<InvoiceHealthStatus> {
    return this.healthService.healthCheck();
  }

  /**
   * Get service statistics
   */
  getServiceStats(): InvoiceServiceStats {
    return this.healthService.getStats();
  }

  /**
   * Reset service statistics
   */
  resetServiceStats(): void {
    this.healthService.resetStats();
  }

  /**
   * Get health summary
   */
  async getHealthSummary(): Promise<{
    status: string;
    uptime: number;
    stats: InvoiceServiceStats;
    lastCheck: string;
  }> {
    return this.healthService.getHealthSummary();
  }

  /**
   * Get valid invoice statuses (from domain)
   */
  getValidStatuses(): readonly InvoiceStatus[] {
    return VALID_INVOICE_STATUSES;
  }

  /**
   * Get pagination limits (from domain)
   */
  getPaginationLimits(): { min: number; max: number } {
    return {
      min: INVOICE_PAGINATION.MIN_LIMIT,
      max: INVOICE_PAGINATION.MAX_LIMIT,
    };
  }
}
