/**
 * Composable for managing backtest state across components.
 */
import { ref, computed } from 'vue'
import type { BacktestResult, BacktestSummary, StrategyInfo, SymbolInfo } from '@/api/types'
import { getStrategies, getSymbols, getBacktests, getBacktest, runBacktest, deleteBacktest } from '@/api/client'
import type { BacktestRequest } from '@/api/types'

// Shared state
const strategies = ref<StrategyInfo[]>([])
const symbols = ref<SymbolInfo[]>([])
const runs = ref<BacktestSummary[]>([])
const currentResult = ref<BacktestResult | null>(null)
const selectedRuns = ref<string[]>([])
const loading = ref(false)
const error = ref<string | null>(null)

// Computed
const symbolsByMarket = computed(() => {
  const grouped: Record<string, SymbolInfo[]> = {}
  for (const s of symbols.value) {
    const key = `${s.market_type}`
    if (!grouped[key]) grouped[key] = []
    grouped[key].push(s)
  }
  return grouped
})

export function useBacktest() {
  /**
   * Load strategies and symbols on app init.
   */
  async function init() {
    try {
      const [stratRes, symRes] = await Promise.all([
        getStrategies(),
        getSymbols(),
      ])
      strategies.value = stratRes.strategies
      symbols.value = symRes.symbols
    } catch (e) {
      error.value = `Failed to load initial data: ${e}`
    }
  }

  /**
   * Refresh the run history list.
   */
  async function refreshRuns() {
    try {
      const res = await getBacktests({ limit: 100 })
      runs.value = res.runs
    } catch (e) {
      error.value = `Failed to load runs: ${e}`
    }
  }

  /**
   * Execute a new backtest.
   */
  async function executeBacktest(request: BacktestRequest) {
    loading.value = true
    error.value = null
    try {
      const result = await runBacktest(request)
      currentResult.value = result
      await refreshRuns()
      return result
    } catch (e: unknown) {
      const msg = e instanceof Error ? e.message : String(e)
      error.value = `Backtest failed: ${msg}`
      throw e
    } finally {
      loading.value = false
    }
  }

  /**
   * Load a specific run by ID.
   */
  async function loadRun(runId: string) {
    loading.value = true
    error.value = null
    try {
      const result = await getBacktest(runId)
      currentResult.value = result
      return result
    } catch (e) {
      error.value = `Failed to load run: ${e}`
      throw e
    } finally {
      loading.value = false
    }
  }

  /**
   * Delete a run.
   */
  async function removeRun(runId: string) {
    try {
      await deleteBacktest(runId)
      await refreshRuns()
      if (currentResult.value?.run_id === runId) {
        currentResult.value = null
      }
      selectedRuns.value = selectedRuns.value.filter(id => id !== runId)
    } catch (e) {
      error.value = `Failed to delete run: ${e}`
    }
  }

  /**
   * Toggle run selection for comparison.
   */
  function toggleRunSelection(runId: string) {
    const idx = selectedRuns.value.indexOf(runId)
    if (idx >= 0) {
      selectedRuns.value.splice(idx, 1)
    } else if (selectedRuns.value.length < 5) {
      selectedRuns.value.push(runId)
    }
  }

  /**
   * Clear all selections.
   */
  function clearSelections() {
    selectedRuns.value = []
  }

  return {
    // State
    strategies,
    symbols,
    symbolsByMarket,
    runs,
    currentResult,
    selectedRuns,
    loading,
    error,
    // Actions
    init,
    refreshRuns,
    executeBacktest,
    loadRun,
    removeRun,
    toggleRunSelection,
    clearSelections,
  }
}
