<script lang="ts" setup>
import type { Subscription, Price, Product } from '~/types/database'

interface PlanWithProduct extends Price {
  product: Product
}

interface ProductGroup {
  product: Product
  plans: PlanWithProduct[]
  activeSubscription?: Subscription
}

const { t } = useI18n()
const log = useLogger('Billing')

const { currentOrg } = useOrganization()
const currentOrgName = computed(() => {
  // Handle both ComputedRef and Ref types from useOrganization
  const org = toValue(currentOrg as ComputedRef<Organization | null>)
  return org?.name || ''
})
const { user: _user, fetchSession } = useAuth()

const { data: plans } = await useApiFetch<PlanWithProduct[]>('/api/stripe/plans')

const { data: activeSubscriptions, refresh: refreshSubscriptions, pending: isLoading } = await useApiFetch<Subscription[]>(
  '/api/stripe/subscriptions',
  {
    query: {
      organizationId: currentOrg.value?.id
    }
  }
)

const plansList = computed<PlanWithProduct[]>(() => {
  const plansData = plans.value
  return Array.isArray(plansData) ? plansData : []
})

const activeSubscriptionsList = computed<Subscription[]>(() => {
  const subsData = activeSubscriptions.value
  return Array.isArray(subsData) ? subsData : []
})

const toast = useToast()
const loadingPriceId = ref<string | null>(null)
const disabled = ref(false)
const route = useRoute()

const activeSubscriptionsByProduct = computed(() => {
  if (!activeSubscriptionsList.value.length || !plansList.value.length) return new Map()

  const subscriptionMap = new Map<string, Subscription>()

  activeSubscriptionsList.value.forEach((subscription: Subscription) => {
    const plan = plansList.value.find((p: PlanWithProduct) => p.id === subscription.priceId)
    if (plan) {
      subscriptionMap.set(plan.product.id, subscription)
    }
  })

  return subscriptionMap
})

// Group plans by product
const plansByProduct = computed(() => {
  if (!plansList.value.length) return []

  const grouped = new Map<string, ProductGroup>()

  plansList.value.forEach((plan: PlanWithProduct) => {
    const productId = plan.product.id

    if (!grouped.has(productId)) {
      grouped.set(productId, {
        product: plan.product,
        plans: [],
        activeSubscription: activeSubscriptionsByProduct.value.get(productId)
      })
    }

    grouped.get(productId)!.plans.push(plan)
  })

  return Array.from(grouped.values())
})

const handleSubscribe = async (priceId: string) => {
  try {
    loadingPriceId.value = priceId
    disabled.value = true

    if (!currentOrg.value?.id) {
      throw new Error(t('settings.billing.errors.organizationInfoMissing'))
    }

    const { apiCall, extractData } = useApiClient()
    const response = await apiCall<{ url: string }>('/api/stripe/checkout', {
      method: 'POST',
      body: {
        priceId,
        organizationId: currentOrg.value.id
      }
    })

    const checkoutData = extractData(response)
    const checkoutUrl = checkoutData?.url

    if (!checkoutUrl) {
      throw new Error(t('settings.billing.errors.noCheckoutUrl'))
    }

    window.location.href = checkoutUrl
  } catch (error) {
    toast.add({
      title: t('settings.billing.errors.checkoutFailed'),
      description:
        error instanceof Error ? error.message : t('settings.billing.errors.unexpectedError'),
      color: 'error'
    })
    log.error('Stripe checkout error:', error)
  } finally {
    loadingPriceId.value = null
    disabled.value = false
  }
}

const handleManageSubscription = async () => {
  try {
    if (!currentOrg.value?.id) {
      throw new Error(t('settings.billing.errors.organizationInfoMissing'))
    }

    const { apiCall, extractData } = useApiClient()
    const response = await apiCall<{ url: string }>('/api/stripe/portal', {
      method: 'POST',
      body: {
        organizationId: currentOrg.value.id
      }
    })

    const portalData = extractData(response)
    const portalUrl = portalData?.url

    if (!portalUrl) {
      throw new Error(t('settings.billing.errors.noPortalUrl'))
    }

    window.location.href = portalUrl
  } catch (error) {
    toast.add({
      title: t('settings.billing.errors.portalFailed'),
      description:
        error instanceof Error ? error.message : t('settings.billing.errors.unexpectedError'),
      color: 'error'
    })
    log.error('Billing portal error:', error)
  }
}

onMounted(async () => {
  if (route.query.success === 'true') {
    // Refresh session to get updated user data
    await fetchSession()
    // Refresh subscriptions to show the newly created subscription
    await refreshSubscriptions()

    // Show success message
    toast.add({
      title: t('settings.billing.success.title', 'Subscription successful'),
      description: t('settings.billing.success.description', 'Your subscription has been activated successfully.'),
      color: 'success'
    })
  }
})

definePageMeta({
  layout: 'dashboard'
})
</script>

<template>
  <NuxtLayout :page-title="$t('settings.billing.title')">
    <UPageBody>
      <PageRefresh :on-refresh="refreshSubscriptions" />
      <PageMainCard
        :title="$t('settings.billing.title')"
        :description="$t('settings.billing.description') + currentOrgName"
        :icon="useSolarIcon('money-bag')"
        :loading="isLoading"
        :on-refresh="refreshSubscriptions"
      >
        <div>
          <div
            v-for="productGroup in plansByProduct"
            :key="productGroup.product.id"
            class="space-y-4"
          >
            <div class="space-y-2">
              <h2 class="text-2xl font-bold">
                {{ productGroup.product.name }}
              </h2>
              <p
                v-if="productGroup.product.description"
                class="text-neutral-600 dark:text-neutral-400"
              >
                {{ productGroup.product.description }}
              </p>
            </div>
            <div class="grid grid-cols-1 gap-4 md:grid-cols-3">
              <AppSubscriptionPlanCard
                v-for="plan in productGroup.plans"
                :key="plan.id"
                :description="plan.description ?? undefined"
                :unit-amount="plan.unitAmount"
                :interval="plan.interval"
                :price-id="plan.id"
                :features="(plan.product.features as any) ?? undefined"
                :active="productGroup.activeSubscription?.priceId === plan.id"
                :subscription="(productGroup.activeSubscription as any)"
                :loading="loadingPriceId === plan.id"
                :disabled="disabled"
                :has-active-subscription="!!productGroup.activeSubscription"
                :can-switch="productGroup.plans.length > 1 && !!productGroup.activeSubscription"
                @subscribe="handleSubscribe"
                @manage="handleManageSubscription"
              />
            </div>
          </div>
        </div>
      </PageMainCard>
    </UPageBody>
  </NuxtLayout>
</template>
