/**
 * TabataFit Purchases Hook
 * Wraps RevenueCat API for subscription management
 *
 * DEV mode: If StoreKit purchase fails (no sandbox account / product mismatch),
 * shows an Alert offering to simulate the purchase for testing.
 */

import { useState, useEffect, useCallback, useRef } from 'react'
import { Alert } from 'react-native'
import { logger } from '../utils/logger'
import Purchases, {
  CustomerInfo,
  PurchasesOfferings,
  PurchasesPackage,
} from 'react-native-purchases'

import { useUserStore } from '../stores'
import { ENTITLEMENT_ID } from '../services/purchases'
import type { SubscriptionPlan } from '../types'

interface PurchaseResult {
  success: boolean
  cancelled: boolean
  error?: string
}

interface UsePurchasesReturn {
  isPremium: boolean
  isLoading: boolean
  monthlyPackage: PurchasesPackage | null
  annualPackage: PurchasesPackage | null
  purchasePackage: (pkg: PurchasesPackage) => Promise<PurchaseResult>
  restorePurchases: () => Promise<boolean>
}

/**
 * Helper to check if user has premium entitlement
 */
function hasPremiumEntitlement(info: CustomerInfo | null): boolean {
  if (!info) return false
  return ENTITLEMENT_ID in info.entitlements.active
}

/**
 * Hook to manage RevenueCat subscriptions
 * Syncs subscription state with userStore
 */
export function usePurchases(): UsePurchasesReturn {
  const [isLoading, setIsLoading] = useState(true)
  const [offerings, setOfferings] = useState<PurchasesOfferings | null>(null)
  const [customerInfo, setCustomerInfo] = useState<CustomerInfo | null>(null)

  const subscription = useUserStore((s) => s.profile.subscription)
  const setSubscription = useUserStore((s) => s.setSubscription)

  // Derive premium status from RevenueCat entitlement or local state
  const isPremium = customerInfo
    ? hasPremiumEntitlement(customerInfo)
    : subscription !== 'free'

  // Get packages from offerings
  const monthlyPackage = offerings?.current?.monthly ?? null
  const annualPackage = offerings?.current?.annual ?? null

  // Sync RevenueCat state to userStore
  const syncSubscriptionToStore = useCallback(
    (info: CustomerInfo | null) => {
      if (!info) return

      const hasPremium = hasPremiumEntitlement(info)
      const activeSubscriptions = info.activeSubscriptions

      let newPlan: SubscriptionPlan = 'free'

      if (hasPremium && activeSubscriptions.length > 0) {
        // Determine plan type from subscription identifier
        const subId = activeSubscriptions[0].toLowerCase()
        if (subId.includes('yearly') || subId.includes('annual')) {
          newPlan = 'premium-yearly'
        } else if (subId.includes('monthly')) {
          newPlan = 'premium-monthly'
        } else {
          // Default to yearly for any premium entitlement
          newPlan = 'premium-yearly'
        }
      }

      // Only update if different
      if (subscription !== newPlan) {
        logger.log('[Purchases] Syncing subscription to store:', newPlan)
        setSubscription(newPlan)
      }
    },
    [subscription, setSubscription]
  )

  // Keep a stable ref so the mount-only effect can call the latest version
  const syncRef = useRef(syncSubscriptionToStore)
  syncRef.current = syncSubscriptionToStore

  // Fetch offerings and customer info on mount
  useEffect(() => {
    const fetchData = async () => {
      try {
        const [offeringsResult, customerInfoResult] = await Promise.all([
          Purchases.getOfferings(),
          Purchases.getCustomerInfo(),
        ])

        setOfferings(offeringsResult)
        setCustomerInfo(customerInfoResult)
        syncRef.current(customerInfoResult)

        logger.log('[Purchases] Offerings loaded:', {
          hasMonthly: !!offeringsResult.current?.monthly,
          hasAnnual: !!offeringsResult.current?.annual,
          monthlyProductId: offeringsResult.current?.monthly?.product.identifier,
          annualProductId: offeringsResult.current?.annual?.product.identifier,
          monthlyPrice: offeringsResult.current?.monthly?.product.priceString,
          annualPrice: offeringsResult.current?.annual?.product.priceString,
        })
      } catch (error) {
        logger.error('[Purchases] Failed to fetch offerings/customerInfo:', error)
      } finally {
        setIsLoading(false)
      }
    }

    fetchData()
  }, []) // empty deps — only runs once per mount

  // Listen for customer info changes (renewals, expirations, etc.)
  useEffect(() => {
    const listener = (info: CustomerInfo) => {
      logger.log('[Purchases] Customer info updated')
      setCustomerInfo(info)
      syncRef.current(info)
    }

    Purchases.addCustomerInfoUpdateListener(listener)

    return () => {
      Purchases.removeCustomerInfoUpdateListener(listener)
    }
  }, [])

  // Purchase a package
  const purchasePackage = useCallback(
    async (pkg: PurchasesPackage): Promise<PurchaseResult> => {
      try {
        logger.log('[Purchases] Starting purchase for:', pkg.identifier, pkg.product.identifier)
        const { customerInfo: newInfo } = await Purchases.purchasePackage(pkg)

        setCustomerInfo(newInfo)
        syncSubscriptionToStore(newInfo)

        logger.log('[Purchases] Active entitlements:', Object.keys(newInfo.entitlements.active))
        logger.log('[Purchases] All entitlements:', Object.keys(newInfo.entitlements.all))
        logger.log('[Purchases] Looking for entitlement:', ENTITLEMENT_ID)
        const success = hasPremiumEntitlement(newInfo)
        logger.log('[Purchases] Purchase result:', { success })

        return { success, cancelled: false }
      } catch (error: unknown) {
        const purchaseError = error as { userCancelled?: boolean; message?: string }
        // Handle user cancellation
        if (purchaseError.userCancelled) {
          logger.log('[Purchases] Purchase cancelled by user')
          return { success: false, cancelled: true }
        }

        logger.error('[Purchases] Purchase error:', error)

        // DEV mode: offer to simulate the purchase when StoreKit fails
        if (__DEV__) {
          return new Promise((resolve) => {
            Alert.alert(
              'Purchase failed (DEV)',
              `StoreKit error: ${purchaseError.message || 'Unknown error'}\n\nProduct: ${pkg.product.identifier}\n\nSimulate a successful purchase for testing?`,
              [
                {
                  text: 'Cancel',
                  style: 'cancel',
                  onPress: () =>
                    resolve({ success: false, cancelled: true }),
                },
                {
                  text: 'Simulate Purchase',
                  onPress: () => {
                    // Determine plan from package identifier
                    const id = pkg.product.identifier.toLowerCase()
                    const plan: SubscriptionPlan =
                      id.includes('annual') || id.includes('year')
                        ? 'premium-yearly'
                        : 'premium-monthly'
                    setSubscription(plan)
                    
                    // DEV: Create mock customerInfo so isPremium returns true
                    const mockCustomerInfo = {
                      entitlements: {
                        active: {
                          [ENTITLEMENT_ID]: {
                            identifier: ENTITLEMENT_ID,
                            isActive: true,
                            willRenew: true,
                            periodType: 'NORMAL',
                            latestPurchaseDate: new Date().toISOString(),
                            originalPurchaseDate: new Date().toISOString(),
                            expirationDate: null,
                            store: 'APP_STORE',
                            productIdentifier: plan === 'premium-yearly' ? 'tabatafit.premium.yearly' : 'tabatafit.premium.monthly',
                            isSandbox: true,
                          }
                        }
                      },
                      activeSubscriptions: [plan === 'premium-yearly' ? 'tabatafit.premium.yearly' : 'tabatafit.premium.monthly'],
                      allPurchasedProductIdentifiers: [plan === 'premium-yearly' ? 'tabatafit.premium.yearly' : 'tabatafit.premium.monthly'],
                      firstSeen: new Date().toISOString(),
                      originalAppUserId: 'dev-user',
                      originalApplicationVersion: '1.0',
                      requestDate: new Date().toISOString(),
                      managementURL: null,
                      nonSubscriptionTransactions: [],
                    } as unknown as CustomerInfo
                    
                    setCustomerInfo(mockCustomerInfo)
                    syncSubscriptionToStore(mockCustomerInfo)
                    
                    logger.log('[Purchases] DEV: Simulated purchase →', plan)
                    resolve({ success: true, cancelled: false })
                  },
                },
              ]
            )
          })
        }

        return {
          success: false,
          cancelled: false,
          error: purchaseError.message || 'Purchase failed',
        }
      }
    },
    [syncSubscriptionToStore, setSubscription]
  )

  // Restore purchases
  const restorePurchases = useCallback(async (): Promise<boolean> => {
    try {
      logger.log('[Purchases] Restoring purchases...')
      const restoredInfo = await Purchases.restorePurchases()

      setCustomerInfo(restoredInfo)
      syncSubscriptionToStore(restoredInfo)

      const hasPremium = hasPremiumEntitlement(restoredInfo)
      logger.log('[Purchases] Restore result:', { hasPremium })

      return hasPremium
    } catch (error) {
      logger.error('[Purchases] Restore failed:', error)

      // DEV mode: offer to simulate restore
      if (__DEV__) {
        return new Promise((resolve) => {
          Alert.alert(
            'Restore failed (DEV)',
            'Simulate a restored premium subscription?',
            [
              { text: 'Cancel', style: 'cancel', onPress: () => resolve(false) },
              {
                text: 'Simulate Restore',
                onPress: () => {
                  const plan: SubscriptionPlan = 'premium-yearly'
                  setSubscription(plan)
                  
                  // DEV: Create mock customerInfo so isPremium returns true
                  const mockCustomerInfo = {
                    entitlements: {
                      active: {
                        [ENTITLEMENT_ID]: {
                          identifier: ENTITLEMENT_ID,
                          isActive: true,
                          willRenew: true,
                          periodType: 'NORMAL',
                          latestPurchaseDate: new Date().toISOString(),
                          originalPurchaseDate: new Date().toISOString(),
                          expirationDate: null,
                          store: 'APP_STORE',
                          productIdentifier: 'tabatafit.premium.yearly',
                          isSandbox: true,
                        }
                      }
                    },
                    activeSubscriptions: ['tabatafit.premium.yearly'],
                    allPurchasedProductIdentifiers: ['tabatafit.premium.yearly'],
                    firstSeen: new Date().toISOString(),
                    originalAppUserId: 'dev-user',
                    originalApplicationVersion: '1.0',
                    requestDate: new Date().toISOString(),
                    managementURL: null,
                    nonSubscriptionTransactions: [],
                  } as unknown as CustomerInfo
                  
                  setCustomerInfo(mockCustomerInfo)
                  syncSubscriptionToStore(mockCustomerInfo)
                  
                  logger.log('[Purchases] DEV: Simulated restore → premium-yearly')
                  resolve(true)
                },
              },
            ]
          )
        })
      }

      return false
    }
  }, [syncSubscriptionToStore, setSubscription])

  return {
    isPremium,
    isLoading,
    monthlyPackage,
    annualPackage,
    purchasePackage,
    restorePurchases,
  }
}
