import type { Event, Ticket } from '../types/event'
import { config } from '@/lib/config'
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import type { LnbitsAPI } from './lnbits'

const API_BASE_URL = config.api.baseUrl || 'http://lnbits'
const API_KEY = config.api.key

// Generic error type for API responses
interface ApiError {
  detail: string | Array<{ loc: [string, number]; msg: string; type: string }>
}

export async function fetchEvents(): Promise<Event[]> {
  try {
    // Use the new public endpoint that allows access to all events without authentication
    const response = await fetch(
      `${API_BASE_URL}/events/api/v1/events/public`,
      {
        headers: {
          'accept': 'application/json',
        },
      }
    )

    if (!response.ok) {
      const error: ApiError = await response.json()
      const errorMessage = typeof error.detail === 'string' 
        ? error.detail 
        : error.detail[0]?.msg || 'Failed to fetch events'
      throw new Error(errorMessage)
    }

    return await response.json() as Event[]
  } catch (error) {
    console.error('Error fetching events:', error)
    throw error
  }
}

export async function purchaseTicket(eventId: string): Promise<{ payment_hash: string; payment_request: string }> {
  try {
    // Get injected LnbitsAPI service
    const lnbitsAPI = injectService(SERVICE_TOKENS.LNBITS_API) as LnbitsAPI
    
    // Get current user to ensure authentication
    const user = await lnbitsAPI.getCurrentUser()
    if (!user) {
      throw new Error('User not authenticated')
    }

    const response = await fetch(
      `${API_BASE_URL}/events/api/v1/tickets/${eventId}/user/${user.id}`,
      {
        method: 'GET',
        headers: {
          'accept': 'application/json',
          'X-API-KEY': API_KEY,
          'Authorization': `Bearer ${lnbitsAPI.getAccessToken()}`,
        },
      }
    )

    if (!response.ok) {
      const error: ApiError = await response.json()
      const errorMessage = typeof error.detail === 'string' 
        ? error.detail 
        : error.detail[0]?.msg || 'Failed to purchase ticket'
      throw new Error(errorMessage)
    }

    return await response.json()
  } catch (error) {
    console.error('Error purchasing ticket:', error)
    throw error
  }
}

export async function payInvoiceWithWallet(paymentRequest: string, _walletId: string, adminKey: string): Promise<{ payment_hash: string; fee_msat: number; preimage: string }> {
  try {
    const response = await fetch(
      `${API_BASE_URL}/api/v1/payments`,
      {
        method: 'POST',
        headers: {
          'accept': 'application/json',
          'Content-Type': 'application/json',
          'X-API-KEY': adminKey,
        },
        body: JSON.stringify({
          out: true,
          bolt11: paymentRequest,
        }),
      }
    )

    if (!response.ok) {
      const error: ApiError = await response.json()
      const errorMessage = typeof error.detail === 'string' 
        ? error.detail 
        : error.detail[0]?.msg || 'Failed to pay invoice'
      throw new Error(errorMessage)
    }

    return await response.json()
  } catch (error) {
    console.error('Error paying invoice:', error)
    throw error
  }
}

export async function checkPaymentStatus(eventId: string, paymentHash: string): Promise<{ paid: boolean; ticket_id?: string }> {
  try {
    const response = await fetch(
      `${API_BASE_URL}/events/api/v1/tickets/${eventId}/${paymentHash}`,
      {
        method: 'POST',
        headers: {
          'accept': 'application/json',
          'X-API-KEY': API_KEY,
        },
      }
    )

    if (!response.ok) {
      const error: ApiError = await response.json()
      const errorMessage = typeof error.detail === 'string' 
        ? error.detail 
        : error.detail[0]?.msg || 'Failed to check payment status'
      throw new Error(errorMessage)
    }

    return await response.json()
  } catch (error) {
    console.error('Error checking payment status:', error)
    throw error
  }
}

export async function fetchUserTickets(userId: string): Promise<Ticket[]> {
  try {
    // Get injected LnbitsAPI service
    const lnbitsAPI = injectService(SERVICE_TOKENS.LNBITS_API) as LnbitsAPI
    
    const response = await fetch(
      `${API_BASE_URL}/events/api/v1/tickets/user/${userId}`,
      {
        headers: {
          'accept': 'application/json',
          'X-API-KEY': API_KEY,
          'Authorization': `Bearer ${lnbitsAPI.getAccessToken()}`,
        },
      }
    )

    if (!response.ok) {
      const error: ApiError = await response.json()
      const errorMessage = typeof error.detail === 'string' 
        ? error.detail 
        : error.detail[0]?.msg || 'Failed to fetch user tickets'
      throw new Error(errorMessage)
    }

    return await response.json()
  } catch (error) {
    console.error('Error fetching user tickets:', error)
    throw error
  }
} 