import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

export interface EstimatorPlan {
  id: number
  slug: string
  name: string
  price: string
  features: Record<string, string | number> | null
  prices?: Array<{ billing_cycle: string; price: string }>
}

export interface EstimatorConfigValue {
  id: number
  label: string
  value: string
  monthly_price: string
  quarterly_price: string
  semi_annual_price: string
  annual_price: string
}

export interface EstimatorConfigOption {
  id: number
  name: string
  type: string
  monthly_price: string | null
  quarterly_price: string | null
  semi_annual_price: string | null
  annual_price: string | null
  min_qty: number | null
  max_qty: number | null
  values: EstimatorConfigValue[]
}

export interface EstimatorAddOnGroup {
  id: number
  name: string
  options: EstimatorConfigOption[]
}

export interface WorkloadEntry {
  default: string | null
  alternates: string[]
  label: string
  icon: string
}

export interface AppExample {
  key: string
  label: string
  plan: string | null
  icon: string
}

export type ManagedTier = 'self' | 'basic' | 'pro' | 'pilot'
export type BackupTier = 'none' | 'lite' | 'standard' | 'extended' | 'vault'
export type EstimatorCycle = 'monthly' | 'quarterly' | 'annual'

export const MIN_PILOT_TIER = 8
export const PILOT_FALLBACK_TIER: ManagedTier = 'pro'

export const CYCLE_MONTHS: Record<EstimatorCycle, number> = {
  monthly: 1,
  quarterly: 3,
  annual: 12,
}

export const useEstimatorStore = defineStore('estimator', () => {
  const plans = ref<EstimatorPlan[]>([])
  const addOns = ref<EstimatorAddOnGroup[]>([])
  const workloadMap = ref<Record<string, WorkloadEntry>>({})
  const appExamples = ref<AppExample[]>([])
  const accountUrl = ref<string>('')

  const workload = ref<string | null>(null)
  const planId = ref<number | null>(null)
  const ipv4Count = ref<number>(1)
  const managedTier = ref<ManagedTier>('self')
  const backupTier = ref<BackupTier>('none')
  const cycle = ref<EstimatorCycle>('monthly')

  function init(catalog: {
    plans: EstimatorPlan[]
    addOns: EstimatorAddOnGroup[]
    workloadMap: Record<string, WorkloadEntry>
    appExamples: AppExample[]
    accountUrl: string
  }): void {
    plans.value = catalog.plans
    addOns.value = catalog.addOns
    workloadMap.value = catalog.workloadMap
    appExamples.value = catalog.appExamples
    accountUrl.value = catalog.accountUrl
  }

  function planBySlug(slug: string): EstimatorPlan | undefined {
    return plans.value.find(p => p.slug === slug)
  }

  function planById(id: number): EstimatorPlan | undefined {
    return plans.value.find(p => p.id === id)
  }

  const selectedPlan = computed<EstimatorPlan | null>(() => {
    if (planId.value === null) return null
    return planById(planId.value) ?? null
  })

  const selectedPlanTier = computed<number>(() => {
    const tier = selectedPlan.value?.features?.tier
    return typeof tier === 'number' ? tier : 0
  })

  const pilotAvailable = computed<boolean>(() => selectedPlanTier.value >= MIN_PILOT_TIER)

  const recommendedPlanId = computed<number | null>(() => {
    if (!workload.value) return null
    const entry = workloadMap.value[workload.value]
    if (!entry?.default) return null
    return planBySlug(entry.default)?.id ?? null
  })

  function findOption(groupName: string, optionName: string): EstimatorConfigOption | null {
    for (const g of addOns.value) {
      if (g.name !== groupName) continue
      for (const o of g.options) {
        if (o.name === optionName) return o
      }
    }
    return null
  }

  function findValue(groupName: string, optionName: string, valueSlug: string): EstimatorConfigValue | null {
    const opt = findOption(groupName, optionName)
    if (!opt) return null
    return opt.values.find(v => v.value === valueSlug) ?? null
  }

  function pickCyclePrice(
    monthly: string | null | undefined,
    quarterly: string | null | undefined,
    annual: string | null | undefined,
    c: EstimatorCycle,
  ): number {
    const raw = c === 'monthly' ? monthly : c === 'quarterly' ? quarterly : annual
    return raw ? parseFloat(raw) : 0
  }

  function planPriceForCycle(plan: EstimatorPlan, c: EstimatorCycle): number {
    if (plan.prices && plan.prices.length > 0) {
      const pp = plan.prices.find(p => p.billing_cycle === c)
      if (pp) return parseFloat(pp.price)
    }
    return parseFloat(plan.price) * CYCLE_MONTHS[c]
  }

  const ipv4ExtraPrice = computed<number>(() => {
    const opt = findOption('VPS Add-ons', 'IPv4 Addresses')
    if (!opt) return 0
    const extras = Math.max(0, ipv4Count.value - 1)
    const price = pickCyclePrice(opt.monthly_price, opt.quarterly_price, opt.annual_price, cycle.value)
    return extras * price
  })

  const managedPrice = computed<number>(() => {
    if (managedTier.value === 'self') return 0
    const v = findValue('VPS Managed Support', 'Managed Support', managedTier.value)
    if (!v) return 0
    return pickCyclePrice(v.monthly_price, v.quarterly_price, v.annual_price, cycle.value)
  })

  const backupPrice = computed<number>(() => {
    if (backupTier.value === 'none') return 0
    const v = findValue('Off-site Backup', 'Backup Tier', backupTier.value)
    if (!v) return 0
    return pickCyclePrice(v.monthly_price, v.quarterly_price, v.annual_price, cycle.value)
  })

  const planCyclePrice = computed<number>(() => {
    if (!selectedPlan.value) return 0
    return planPriceForCycle(selectedPlan.value, cycle.value)
  })

  const cycleTotal = computed<number>(() =>
    planCyclePrice.value + ipv4ExtraPrice.value + managedPrice.value + backupPrice.value,
  )

  const monthlyEffectiveTotal = computed<number>(() => cycleTotal.value / CYCLE_MONTHS[cycle.value])

  function setWorkload(key: string): void {
    workload.value = key
    const recommended = recommendedPlanId.value
    if (recommended !== null) planId.value = recommended
  }

  function setPlan(id: number): void {
    planId.value = id
    if (managedTier.value === 'pilot' && !pilotAvailable.value) {
      managedTier.value = PILOT_FALLBACK_TIER
    }
  }

  function setManagedTier(tier: ManagedTier): void {
    if (tier === 'pilot' && !pilotAvailable.value) return
    managedTier.value = tier
  }

  const shareUrl = computed<string>(() => {
    const params = new URLSearchParams()
    if (workload.value) params.set('w', workload.value)
    if (planId.value !== null) params.set('plan', String(planId.value))
    if (ipv4Count.value > 1) params.set('ipv4', String(ipv4Count.value))
    if (managedTier.value !== 'self') params.set('managed', managedTier.value)
    if (backupTier.value !== 'none') params.set('backup', backupTier.value)
    if (cycle.value !== 'monthly') params.set('cycle', cycle.value)
    const qs = params.toString()
    if (typeof window === 'undefined') return qs ? `/vps-hosting?${qs}` : '/vps-hosting'
    return qs ? `${window.location.origin}${window.location.pathname}?${qs}` : `${window.location.origin}${window.location.pathname}`
  })

  const checkoutUrl = computed<string | null>(() => {
    if (planId.value === null) return null
    const params = new URLSearchParams()
    if (ipv4Count.value > 1) params.set('ipv4', String(ipv4Count.value))
    if (managedTier.value !== 'self') params.set('managed', managedTier.value)
    if (backupTier.value !== 'none') params.set('backup', backupTier.value)
    if (cycle.value !== 'monthly') params.set('cycle', cycle.value)
    const qs = params.toString()
    const base = `${accountUrl.value}/checkout/${planId.value}`
    return qs ? `${base}?${qs}` : base
  })

  function hydrateFromUrl(search: string): void {
    const p = new URLSearchParams(search)

    const w = p.get('w')
    if (w && workloadMap.value[w]) workload.value = w

    const planParam = p.get('plan')
    if (planParam) {
      const id = parseInt(planParam, 10)
      if (!Number.isNaN(id) && planById(id)) planId.value = id
    }

    const ipv4 = p.get('ipv4')
    if (ipv4) {
      const n = parseInt(ipv4, 10)
      if (!Number.isNaN(n) && n >= 1 && n <= 8) ipv4Count.value = n
    }

    const m = p.get('managed')
    if (m && ['self', 'basic', 'pro', 'pilot'].includes(m)) managedTier.value = m as ManagedTier

    const b = p.get('backup')
    if (b && ['none', 'lite', 'standard', 'extended', 'vault'].includes(b)) backupTier.value = b as BackupTier

    const c = p.get('cycle')
    if (c && ['monthly', 'quarterly', 'annual'].includes(c)) cycle.value = c as EstimatorCycle

    if (managedTier.value === 'pilot' && !pilotAvailable.value) {
      managedTier.value = PILOT_FALLBACK_TIER
    }
  }

  return {
    plans,
    addOns,
    workloadMap,
    appExamples,
    accountUrl,
    workload,
    planId,
    ipv4Count,
    managedTier,
    backupTier,
    cycle,
    selectedPlan,
    selectedPlanTier,
    pilotAvailable,
    ipv4ExtraPrice,
    managedPrice,
    backupPrice,
    planCyclePrice,
    cycleTotal,
    monthlyEffectiveTotal,
    recommendedPlanId,
    shareUrl,
    checkoutUrl,
    init,
    setWorkload,
    setPlan,
    setManagedTier,
    hydrateFromUrl,
    findOption,
    findValue,
  }
})
