import { ref } from 'vue'
import { BaseService } from '@/core/base/BaseService'
import type { PaymentStatus, LightningInvoice } from '@/core/services/invoiceService'
import type { Order } from '@/modules/market/stores/market'

export interface PaymentMonitorState {
  isMonitoring: boolean
  activeInvoices: Map<string, LightningInvoice>
  paymentStatuses: Map<string, PaymentStatus>
  lastUpdate: number
  error: string | null
}

export interface PaymentUpdate {
  orderId: string
  paymentHash: string
  status: 'pending' | 'paid' | 'expired'
  amount: number
  paidAt?: number
}

export class PaymentMonitorService extends BaseService {
  // Service metadata
  protected readonly metadata = {
    name: 'PaymentMonitorService',
    version: '1.0.0',
    dependencies: ['InvoiceService'] // Only depends on InvoiceService for payment status checking
  }

  private state = ref<PaymentMonitorState>({
    isMonitoring: false,
    activeInvoices: new Map(),
    paymentStatuses: new Map(),
    lastUpdate: 0,
    error: null
  })

  private monitoringInterval: number | null = null
  private updateCallbacks: Map<string, (update: PaymentUpdate) => void> = new Map()

  /**
   * Service-specific initialization (called by BaseService)
   */
  protected async onInitialize(): Promise<void> {
    this.debug('PaymentMonitorService initialized')
    // No special initialization needed
  }

  // Computed properties
  get isMonitoring() { return this.state.value.isMonitoring }
  get activeInvoices() { return this.state.value.activeInvoices }
  get paymentStatuses() { return this.state.value.paymentStatuses }
  get lastUpdate() { return this.state.value.lastUpdate }
  get error() { return this.state.value.error }

  /**
   * Start monitoring payments for a specific order
   */
  async startMonitoring(order: Order, invoice: LightningInvoice): Promise<void> {
    try {
      // Add invoice to active monitoring
      this.state.value.activeInvoices.set(order.id, invoice)
      this.state.value.paymentStatuses.set(invoice.payment_hash, {
        paid: false,
        amount_paid: 0,
        payment_hash: invoice.payment_hash
      })

      // Start monitoring if not already running
      if (!this.state.value.isMonitoring) {
        await this.startMonitoringLoop()
      }

      console.log('Started monitoring payment for order:', {
        orderId: order.id,
        paymentHash: invoice.payment_hash,
        amount: invoice.amount
      })
    } catch (error) {
      console.error('Failed to start payment monitoring:', error)
      this.state.value.error = 'Failed to start payment monitoring'
    }
  }

  /**
   * Stop monitoring a specific order
   */
  stopMonitoring(orderId: string): void {
    const invoice = this.state.value.activeInvoices.get(orderId)
    if (invoice) {
      this.state.value.activeInvoices.delete(orderId)
      this.state.value.paymentStatuses.delete(invoice.payment_hash)
      console.log('Stopped monitoring payment for order:', orderId)
    }

    // Stop monitoring loop if no more active invoices
    if (this.state.value.activeInvoices.size === 0) {
      this.stopMonitoringLoop()
    }
  }

  /**
   * Start the monitoring loop
   */
  private async startMonitoringLoop(): Promise<void> {
    if (this.state.value.isMonitoring) return

    this.state.value.isMonitoring = true
    console.log('Starting payment monitoring loop')

    // Check immediately
    await this.checkAllPayments()

    // Set up interval for periodic checks
    this.monitoringInterval = setInterval(async () => {
      await this.checkAllPayments()
    }, 30000) as unknown as number // Check every 30 seconds
  }

  /**
   * Stop the monitoring loop
   */
  private stopMonitoringLoop(): void {
    if (this.monitoringInterval) {
      clearInterval(this.monitoringInterval)
      this.monitoringInterval = null
    }
    this.state.value.isMonitoring = false
    console.log('Stopped payment monitoring loop')
  }

  /**
   * Check payment status for all active invoices
   */
  private async checkAllPayments(): Promise<void> {
    try {
      this.state.value.error = null
      this.state.value.lastUpdate = Date.now()

      const promises = Array.from(this.state.value.activeInvoices.entries()).map(
        async ([orderId, invoice]) => {
          try {
            // Get payment status from LNBits
            const status = await this.getPaymentStatus(invoice.payment_hash)
            
            // Update local status
            this.state.value.paymentStatuses.set(invoice.payment_hash, status)
            
            // Check if status changed
            const previousStatus = this.state.value.paymentStatuses.get(invoice.payment_hash)
            if (previousStatus && previousStatus.paid !== status.paid) {
              await this.handlePaymentStatusChange(orderId, invoice, status)
            }

            return { orderId, status }
          } catch (error) {
            console.error(`Failed to check payment for order ${orderId}:`, error)
            return { orderId, error }
          }
        }
      )

      await Promise.allSettled(promises)
    } catch (error) {
      console.error('Payment monitoring error:', error)
      this.state.value.error = 'Payment monitoring failed'
    }
  }

  /**
   * Get payment status from LNBits
   */
  private async getPaymentStatus(paymentHash: string): Promise<PaymentStatus> {
    try {
      // Use injected InvoiceService for payment status checking
      if (!this.invoiceService) {
        console.warn('InvoiceService not available, returning default pending status')
        return {
          paid: false,
          amount_paid: 0,
          payment_hash: paymentHash
        }
      }
      
      console.log('Checking payment status for:', paymentHash)
      
      // TODO: Need to pass adminKey from order context - for now return pending
      // In a complete implementation, we'd store wallet context with each order
      // const status = await this.invoiceService.checkPaymentStatus(paymentHash, adminKey)
      // return status
      
      // Return default pending status until wallet context is available
      return {
        paid: false,
        amount_paid: 0,
        payment_hash: paymentHash
      }
    } catch (error) {
      console.error('Failed to get payment status:', error)
      // Return default pending status
      return {
        paid: false,
        amount_paid: 0,
        payment_hash: paymentHash
      }
    }
  }

  /**
   * Handle payment status changes
   */
  private async handlePaymentStatusChange(
    orderId: string, 
    invoice: LightningInvoice, 
    status: PaymentStatus
  ): Promise<void> {
    const update: PaymentUpdate = {
      orderId,
      paymentHash: invoice.payment_hash,
      status: status.paid ? 'paid' : 'pending',
      amount: invoice.amount,
      paidAt: status.paid_at
    }

    console.log('Payment status changed:', update)

    // Notify callbacks
    const callback = this.updateCallbacks.get(orderId)
    if (callback) {
      try {
        callback(update)
      } catch (error) {
        console.error('Payment update callback error:', error)
      }
    }

    // If payment is complete, stop monitoring this order
    if (status.paid) {
      this.stopMonitoring(orderId)
    }
  }

  /**
   * Register a callback for payment updates
   */
  onPaymentUpdate(orderId: string, callback: (update: PaymentUpdate) => void): void {
    this.updateCallbacks.set(orderId, callback)
  }

  /**
   * Unregister a payment update callback
   */
  offPaymentUpdate(orderId: string): void {
    this.updateCallbacks.delete(orderId)
  }

  /**
   * Get current payment status for an order
   */
  getOrderPaymentStatus(orderId: string): PaymentStatus | null {
    const invoice = this.state.value.activeInvoices.get(orderId)
    if (!invoice) return null

    return this.state.value.paymentStatuses.get(invoice.payment_hash) || null
  }

  /**
   * Check if an order payment is complete
   */
  isOrderPaid(orderId: string): boolean {
    const status = this.getOrderPaymentStatus(orderId)
    return status?.paid || false
  }

  /**
   * Get all pending payments
   */
  getPendingPayments(): Array<{ orderId: string; invoice: LightningInvoice }> {
    return Array.from(this.state.value.activeInvoices.entries())
      .filter(([orderId]) => !this.isOrderPaid(orderId))
      .map(([orderId, invoice]) => ({ orderId, invoice }))
  }

  /**
   * Clean up resources
   */
  cleanup(): void {
    this.stopMonitoringLoop()
    this.state.value.activeInvoices.clear()
    this.state.value.paymentStatuses.clear()
    this.updateCallbacks.clear()
    this.state.value.error = null
    console.log('Payment monitor cleaned up')
  }
}

// Service is now registered in the DI container

