<script setup lang="ts">
/**
 * Formula simulator page.
 *
 * Allows interactive adjustment of formula parameters with live threshold
 * computation, a visual gauge, and a table of thresholds at various
 * participation levels.
 */
import type { FormulaConfig } from '~/stores/protocols'
import { encodeModeParams } from '~/utils/mode-params'

const { computeThreshold, computeRequiredRatio, computeInertiaFactor } = useVoteFormula()

/** Default formula config for the simulator. */
const formulaConfig = ref<FormulaConfig>({
  id: 'simulator',
  name: 'Simulateur',
  description: null,
  duration_days: 30,
  majority_pct: 50,
  base_exponent: 0.1,
  gradient_exponent: 0.2,
  constant_base: 0,
  smith_exponent: null,
  techcomm_exponent: null,
  nuanced_min_participants: null,
  nuanced_threshold_pct: null,
  created_at: new Date().toISOString(),
})

/** Simulation inputs. */
const wotSize = ref(7224)
const simulatedVotes = ref(120)
const simulatedFor = ref(97)

/** Computed threshold for current params. */
const threshold = computed(() => {
  try {
    return computeThreshold(wotSize.value, simulatedVotes.value, {
      majority_pct: formulaConfig.value.majority_pct,
      base_exponent: formulaConfig.value.base_exponent,
      gradient_exponent: formulaConfig.value.gradient_exponent,
      constant_base: formulaConfig.value.constant_base,
    })
  } catch {
    return 0
  }
})

/** Computed required ratio. */
const requiredRatio = computed(() => {
  return computeRequiredRatio(
    simulatedVotes.value,
    wotSize.value,
    formulaConfig.value.majority_pct,
    formulaConfig.value.gradient_exponent,
  )
})

/** Computed inertia factor. */
const inertiaFactor = computed(() => {
  return computeInertiaFactor(
    simulatedVotes.value,
    wotSize.value,
    formulaConfig.value.gradient_exponent,
  )
})

/** Simulated votes against. */
const simulatedAgainst = computed(() => {
  return Math.max(0, simulatedVotes.value - simulatedFor.value)
})

/** Mode params string for current config. */
const modeParamsString = computed(() => {
  try {
    return encodeModeParams({
      duration_days: formulaConfig.value.duration_days,
      majority_pct: formulaConfig.value.majority_pct,
      base_exponent: formulaConfig.value.base_exponent,
      gradient_exponent: formulaConfig.value.gradient_exponent,
      constant_base: formulaConfig.value.constant_base,
      smith_exponent: formulaConfig.value.smith_exponent,
      techcomm_exponent: formulaConfig.value.techcomm_exponent,
    })
  } catch {
    return ''
  }
})

/** Table of thresholds at various participation levels. */
const participationLevels = [10, 50, 100, 200, 500, 1000, 3000, 5000, 7000]

const thresholdTable = computed(() => {
  return participationLevels
    .filter(n => n <= wotSize.value)
    .map(totalVotes => {
      let t: number
      let ratio: number
      try {
        t = computeThreshold(wotSize.value, totalVotes, {
          majority_pct: formulaConfig.value.majority_pct,
          base_exponent: formulaConfig.value.base_exponent,
          gradient_exponent: formulaConfig.value.gradient_exponent,
          constant_base: formulaConfig.value.constant_base,
        })
        ratio = computeRequiredRatio(
          totalVotes,
          wotSize.value,
          formulaConfig.value.majority_pct,
          formulaConfig.value.gradient_exponent,
        )
      } catch {
        t = 0
        ratio = 0
      }
      const participation = ((totalVotes / wotSize.value) * 100).toFixed(2)
      return {
        totalVotes,
        threshold: t,
        ratio: (ratio * 100).toFixed(1),
        participation,
      }
    })
})

/** Keep simulatedFor within bounds when simulatedVotes changes. */
watch(simulatedVotes, (newTotal) => {
  if (simulatedFor.value > newTotal) {
    simulatedFor.value = newTotal
  }
})
</script>

<template>
  <div class="space-y-8">
    <!-- Header -->
    <div>
      <div class="flex items-center gap-3 mb-2">
        <NuxtLink to="/protocols" class="text-gray-400 hover:text-gray-600">
          <UIcon name="i-lucide-arrow-left" />
        </NuxtLink>
        <h1 class="text-2xl font-bold text-gray-900 dark:text-white">
          Simulateur de formule de seuil
        </h1>
      </div>
      <p class="text-sm text-gray-600 dark:text-gray-400">
        Ajustez les parametres de la formule et observez le seuil calcule en temps reel.
      </p>
    </div>

    <!-- Current mode params -->
    <UCard v-if="modeParamsString">
      <div class="flex items-center gap-3">
        <span class="text-sm font-medium text-gray-700 dark:text-gray-300">Mode params :</span>
        <ModeParamsDisplay :mode-params="modeParamsString" />
      </div>
    </UCard>

    <!-- Formula editor -->
    <UCard>
      <template #header>
        <h2 class="text-lg font-semibold text-gray-900 dark:text-white">
          Parametres de la formule
        </h2>
      </template>
      <FormulaEditor v-model="formulaConfig" />
    </UCard>

    <!-- Simulation inputs -->
    <UCard>
      <template #header>
        <h2 class="text-lg font-semibold text-gray-900 dark:text-white">
          Simulation
        </h2>
      </template>

      <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
        <!-- WoT size -->
        <div class="space-y-2">
          <div class="flex items-center justify-between">
            <label class="text-sm font-medium text-gray-700 dark:text-gray-300">
              Taille du corpus WoT (W)
            </label>
            <span class="text-sm font-mono font-bold text-primary">{{ wotSize }}</span>
          </div>
          <UInput v-model.number="wotSize" type="number" :min="1" :max="100000" />
        </div>

        <!-- Total votes -->
        <div class="space-y-2">
          <div class="flex items-center justify-between">
            <label class="text-sm font-medium text-gray-700 dark:text-gray-300">
              Votes totaux (T)
            </label>
            <span class="text-sm font-mono font-bold text-primary">{{ simulatedVotes }}</span>
          </div>
          <URange v-model="simulatedVotes" :min="0" :max="wotSize" :step="1" />
        </div>

        <!-- Votes for -->
        <div class="space-y-2">
          <div class="flex items-center justify-between">
            <label class="text-sm font-medium text-gray-700 dark:text-gray-300">
              Votes pour
            </label>
            <span class="text-sm font-mono font-bold text-green-600">{{ simulatedFor }}</span>
          </div>
          <URange v-model="simulatedFor" :min="0" :max="simulatedVotes" :step="1" />
        </div>
      </div>
    </UCard>

    <!-- Results -->
    <UCard>
      <template #header>
        <h2 class="text-lg font-semibold text-gray-900 dark:text-white">
          Resultat
        </h2>
      </template>

      <div class="space-y-6">
        <!-- Threshold gauge -->
        <ThresholdGauge
          :votes-for="simulatedFor"
          :votes-against="simulatedAgainst"
          :threshold="threshold"
          :wot-size="wotSize"
        />

        <!-- Key metrics -->
        <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
          <div class="p-3 bg-gray-50 dark:bg-gray-800 rounded-lg text-center">
            <p class="text-xs text-gray-500 mb-1">Seuil requis</p>
            <p class="text-2xl font-bold text-primary">{{ threshold }}</p>
          </div>
          <div class="p-3 bg-gray-50 dark:bg-gray-800 rounded-lg text-center">
            <p class="text-xs text-gray-500 mb-1">Ratio requis</p>
            <p class="text-2xl font-bold text-gray-900 dark:text-white">
              {{ (requiredRatio * 100).toFixed(1) }}%
            </p>
          </div>
          <div class="p-3 bg-gray-50 dark:bg-gray-800 rounded-lg text-center">
            <p class="text-xs text-gray-500 mb-1">Facteur d'inertie</p>
            <p class="text-2xl font-bold text-gray-900 dark:text-white">
              {{ inertiaFactor.toFixed(4) }}
            </p>
          </div>
          <div class="p-3 bg-gray-50 dark:bg-gray-800 rounded-lg text-center">
            <p class="text-xs text-gray-500 mb-1">Participation</p>
            <p class="text-2xl font-bold text-gray-900 dark:text-white">
              {{ ((simulatedVotes / wotSize) * 100).toFixed(2) }}%
            </p>
          </div>
        </div>
      </div>
    </UCard>

    <!-- Formula display -->
    <UCard>
      <template #header>
        <h2 class="text-lg font-semibold text-gray-900 dark:text-white">
          Formule
        </h2>
      </template>
      <FormulaDisplay :formula-config="formulaConfig" show-explanation />
    </UCard>

    <!-- Threshold table -->
    <UCard>
      <template #header>
        <h2 class="text-lg font-semibold text-gray-900 dark:text-white">
          Seuils par niveau de participation
        </h2>
      </template>

      <div class="overflow-x-auto">
        <table class="w-full text-sm">
          <thead>
            <tr class="border-b border-gray-200 dark:border-gray-700">
              <th class="text-left px-4 py-3 font-medium text-gray-500">Votes totaux (T)</th>
              <th class="text-left px-4 py-3 font-medium text-gray-500">Participation</th>
              <th class="text-left px-4 py-3 font-medium text-gray-500">Ratio requis</th>
              <th class="text-left px-4 py-3 font-medium text-gray-500">Seuil (votes pour)</th>
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="row in thresholdTable"
              :key="row.totalVotes"
              class="border-b border-gray-100 dark:border-gray-800"
              :class="row.totalVotes === simulatedVotes ? 'bg-primary-50 dark:bg-primary-900/20' : ''"
            >
              <td class="px-4 py-3 font-mono text-gray-900 dark:text-white">{{ row.totalVotes }}</td>
              <td class="px-4 py-3 text-gray-600">{{ row.participation }}%</td>
              <td class="px-4 py-3 text-gray-600">{{ row.ratio }}%</td>
              <td class="px-4 py-3 font-mono font-bold text-primary">{{ row.threshold }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </UCard>
  </div>
</template>
