<script lang="ts" setup>
import { ref, computed, watch } from 'vue'
import type { PlanConfigGroup, PlanConfigOption, PlanConfigValue } from '@/types'

interface ConfigSelection {
  option_id: number
  value_id: number | null
  quantity: number | null
  text_value: string | null
  locked_price: number
  locked_hourly_price: number | null
}

interface Props {
  configGroups: PlanConfigGroup[]
  billingCycle: string
  modelValue: ConfigSelection[]
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
})

const emit = defineEmits<{
  'update:modelValue': [selections: ConfigSelection[]]
  'update:totalPrice': [price: number]
}>()

// Internal state keyed by option_id
const selections = ref<Record<number, { value_id: number | null; quantity: number | null; text_value: string | null; checked: boolean }>>({})

// Initialize selections with defaults
function initSelections(): void {
  const sel: typeof selections.value = {}
  for (const group of props.configGroups) {
    for (const option of group.options) {
      if (option.type === 'dropdown' || option.type === 'radio') {
        const defaultVal = option.values.find(v => v.is_default) || option.values[0]
        sel[option.id] = { value_id: defaultVal?.id ?? null, quantity: null, text_value: null, checked: false }
      } else if (option.type === 'quantity' || option.type === 'slider') {
        sel[option.id] = { value_id: null, quantity: option.min_qty ?? 0, text_value: null, checked: false }
      } else if (option.type === 'checkbox') {
        sel[option.id] = { value_id: null, quantity: null, text_value: null, checked: false }
      } else if (option.type === 'text') {
        sel[option.id] = { value_id: null, quantity: null, text_value: '', checked: false }
      }
    }
  }
  selections.value = sel
}

initSelections()

// Cycle-aware price field
const cycleKey = computed<string>(() => {
  return `${props.billingCycle}_price`
})

function getValuePrice(value: PlanConfigValue): number {
  const key = cycleKey.value as keyof PlanConfigValue
  return Number(value[key] ?? value.monthly_price ?? 0)
}

function getOptionPrice(option: PlanConfigOption): number {
  const key = cycleKey.value as keyof PlanConfigOption
  return Number(option[key] ?? option.monthly_price ?? 0)
}

function getOptionHourlyPrice(option: PlanConfigOption): number {
  return Number(option.hourly_price ?? 0)
}

// Calculate total config price
const configTotal = computed<number>(() => {
  let total = 0
  for (const group of props.configGroups) {
    for (const option of group.options) {
      const sel = selections.value[option.id]
      if (!sel) continue

      if (option.type === 'dropdown' || option.type === 'radio') {
        const selectedValue = option.values.find(v => v.id === sel.value_id)
        if (selectedValue) {
          total += getValuePrice(selectedValue)
        }
      } else if (option.type === 'quantity' || option.type === 'slider') {
        const qty = sel.quantity ?? 0
        total += getOptionPrice(option) * qty
      } else if (option.type === 'checkbox') {
        if (sel.checked) {
          total += getOptionPrice(option)
        }
      }
      // text options have no price impact
    }
  }
  return total
})

// Build selection array for form submission
function buildSelections(): ConfigSelection[] {
  const result: ConfigSelection[] = []
  for (const group of props.configGroups) {
    for (const option of group.options) {
      const sel = selections.value[option.id]
      if (!sel) continue

      // Skip unset optional items
      if (option.type === 'checkbox' && !sel.checked) continue
      if (option.type === 'text' && !sel.text_value) continue

      let lockedPrice = 0
      let lockedHourlyPrice: number | null = null

      if (option.type === 'dropdown' || option.type === 'radio') {
        const selectedValue = option.values.find(v => v.id === sel.value_id)
        if (selectedValue) {
          lockedPrice = getValuePrice(selectedValue)
        }
      } else if (option.type === 'quantity' || option.type === 'slider') {
        const qty = sel.quantity ?? 0
        lockedPrice = getOptionPrice(option) * qty
        lockedHourlyPrice = getOptionHourlyPrice(option) * qty
      } else if (option.type === 'checkbox') {
        lockedPrice = getOptionPrice(option)
      }

      result.push({
        option_id: option.id,
        value_id: sel.value_id,
        quantity: sel.quantity,
        text_value: sel.text_value,
        locked_price: lockedPrice,
        locked_hourly_price: lockedHourlyPrice,
      })
    }
  }
  return result
}

// Emit changes on any selection update
watch(selections, () => {
  emit('update:modelValue', buildSelections())
  emit('update:totalPrice', configTotal.value)
}, { deep: true })

// Re-emit when billing cycle changes (prices change)
watch(() => props.billingCycle, () => {
  emit('update:modelValue', buildSelections())
  emit('update:totalPrice', configTotal.value)
})

// Dropdown items for VSelect
function getDropdownItems(option: PlanConfigOption): Array<{ title: string; value: number }> {
  return option.values.map(v => ({
    title: `${v.label}${getValuePrice(v) > 0 ? ` (+$${getValuePrice(v).toFixed(2)})` : ''}`,
    value: v.id,
  }))
}

// Slider display value
function getSliderDisplayValue(option: PlanConfigOption): string {
  const qty = selections.value[option.id]?.quantity ?? 0
  return `${qty} ${option.unit_label ?? ''}`
}

function getSliderPriceDisplay(option: PlanConfigOption): string {
  const qty = selections.value[option.id]?.quantity ?? 0
  const price = getOptionPrice(option) * qty
  return `$${price.toFixed(2)}`
}
</script>

<template>
  <div
    v-for="group in configGroups"
    :key="group.id"
    class="config-group mb-6"
  >
    <div class="text-subtitle-1 font-weight-bold d-flex align-center mb-2">
      <VIcon
        icon="tabler-adjustments"
        size="22"
        class="me-2 text-primary"
      />
      {{ group.name }}
    </div>
    <p
      v-if="group.description"
      class="text-body-2 text-medium-emphasis mb-4"
    >
      {{ group.description }}
    </p>

    <VRow>
      <VCol
        v-for="option in group.options"
        :key="option.id"
        cols="12"
        :md="option.type === 'slider' ? 12 : 6"
      >
        <!-- Dropdown -->
        <VSelect
          v-if="option.type === 'dropdown'"
          v-model="selections[option.id].value_id"
          :label="option.name"
          :items="getDropdownItems(option)"
          :hint="option.description ?? undefined"
          persistent-hint
          density="comfortable"
        />

        <!-- Radio -->
        <div v-else-if="option.type === 'radio'">
          <label class="text-body-2 font-weight-medium mb-2 d-block">{{ option.name }}</label>
          <p
            v-if="option.description"
            class="text-caption text-medium-emphasis mb-2"
          >
            {{ option.description }}
          </p>
          <VRadioGroup
            v-model="selections[option.id].value_id"
            hide-details
          >
            <VRadio
              v-for="val in option.values"
              :key="val.id"
              :value="val.id"
            >
              <template #label>
                <span>{{ val.label }}</span>
                <VChip
                  v-if="getValuePrice(val) > 0"
                  size="x-small"
                  color="primary"
                  class="ml-2"
                >
                  +${{ getValuePrice(val).toFixed(2) }}
                </VChip>
              </template>
            </VRadio>
          </VRadioGroup>
        </div>

        <!-- Quantity -->
        <div v-else-if="option.type === 'quantity'">
          <VTextField
            v-model.number="selections[option.id].quantity"
            :label="option.name"
            type="number"
            :min="option.min_qty ?? 0"
            :max="option.max_qty ?? 999"
            :step="option.step ?? 1"
            :hint="option.description ? `${option.description} — $${getOptionPrice(option).toFixed(2)} each` : `$${getOptionPrice(option).toFixed(2)} each`"
            persistent-hint
            density="comfortable"
          >
            <template #prepend-inner>
              <VIcon
                icon="tabler-hash"
                size="20"
              />
            </template>
            <template #append-inner>
              <VChip
                v-if="(selections[option.id]?.quantity ?? 0) > 0"
                size="small"
                color="primary"
                variant="tonal"
              >
                ${{ (getOptionPrice(option) * (selections[option.id]?.quantity ?? 0)).toFixed(2) }}
              </VChip>
            </template>
          </VTextField>
        </div>

        <!-- Checkbox -->
        <VCheckbox
          v-else-if="option.type === 'checkbox'"
          v-model="selections[option.id].checked"
          :label="`${option.name}${getOptionPrice(option) > 0 ? ` (+$${getOptionPrice(option).toFixed(2)})` : ''}`"
          :hint="option.description ?? undefined"
          persistent-hint
          density="comfortable"
        />

        <!-- Text -->
        <VTextField
          v-else-if="option.type === 'text'"
          v-model="selections[option.id].text_value"
          :label="option.name"
          :hint="option.description ?? undefined"
          persistent-hint
          density="comfortable"
        />

        <!-- Slider -->
        <div
          v-else-if="option.type === 'slider'"
          class="slider-option"
        >
          <div class="d-flex justify-space-between align-center mb-1">
            <label class="text-body-2 font-weight-medium">{{ option.name }}</label>
            <div class="d-flex align-center ga-2">
              <span class="text-body-2 font-weight-bold">{{ getSliderDisplayValue(option) }}</span>
              <VChip
                size="small"
                color="primary"
                variant="tonal"
              >
                {{ getSliderPriceDisplay(option) }}
              </VChip>
            </div>
          </div>
          <p
            v-if="option.description"
            class="text-caption text-medium-emphasis mb-2"
          >
            {{ option.description }}
          </p>
          <VSlider
            v-model="selections[option.id].quantity"
            :min="option.min_qty ?? 0"
            :max="option.max_qty ?? 100"
            :step="option.step ?? 1"
            color="primary"
            track-color="grey-lighten-2"
            thumb-label="always"
            class="mt-2"
          >
            <template #thumb-label="{ modelValue }">
              {{ modelValue }} {{ option.unit_label ?? '' }}
            </template>
          </VSlider>
          <div class="d-flex justify-space-between text-caption text-medium-emphasis">
            <span>{{ option.min_qty ?? 0 }} {{ option.unit_label ?? '' }}</span>
            <span>{{ option.max_qty ?? 100 }} {{ option.unit_label ?? '' }}</span>
          </div>
        </div>
      </VCol>
    </VRow>
  </div>
</template>

<style scoped>
.config-group {
  padding: 1rem;
  border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
  border-radius: 12px;
  background: rgba(var(--v-theme-surface), 1);
}

.slider-option {
  padding: 0.5rem 0;
}
</style>
