<script setup lang="ts">
import { onMounted, ref, computed, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useActivitiesStore } from '../stores/activities'
import type { Activity, DataPoint, ZonesResponse, PowerCurveResponse, DiaryEntry } from '../types/models'
import Card from 'primevue/card'
import Tag from 'primevue/tag'
import DataTable from 'primevue/datatable'
import Column from 'primevue/column'
import Button from 'primevue/button'
import Textarea from 'primevue/textarea'
import Select from 'primevue/select'
import InputNumber from 'primevue/inputnumber'
import ProgressSpinner from 'primevue/progressspinner'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart, BarChart } from 'echarts/charts'
import {
  TitleComponent, TooltipComponent, LegendComponent, GridComponent, DataZoomComponent, MarkLineComponent,
} from 'echarts/components'
import VChart from 'vue-echarts'
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'

use([CanvasRenderer, LineChart, BarChart, TitleComponent, TooltipComponent, LegendComponent, GridComponent, DataZoomComponent, MarkLineComponent])

const route = useRoute()
const router = useRouter()
const store = useActivitiesStore()

const activity = ref<Activity | null>(null)
const stream = ref<DataPoint[]>([])
const zones = ref<ZonesResponse | null>(null)
const powerCurve = ref<PowerCurveResponse | null>(null)
const loading = ref(true)
const aiSummary = ref('')
const aiLoading = ref(false)

// Diary
const diary = ref<DiaryEntry>({ rider_notes: null, mood: null, rpe: null, sleep_hours: null })
const diarySaving = ref(false)
const diarySaved = ref(false)

const moods = [
  { label: 'Great', value: 'great' },
  { label: 'Good', value: 'good' },
  { label: 'OK', value: 'ok' },
  { label: 'Tired', value: 'tired' },
  { label: 'Bad', value: 'bad' },
]

const hasGps = computed(() => stream.value.some(dp => dp.latitude && dp.longitude))
const hasAltitude = computed(() => stream.value.some(dp => dp.altitude != null))
const hasSpeed = computed(() => stream.value.some(dp => dp.speed != null && dp.speed > 0))
const hasPower = computed(() => stream.value.some(dp => dp.power != null))
const hasStream = computed(() => stream.value.length > 0)
const isStrength = computed(() => {
  const t = activity.value?.activity_type?.toLowerCase() || ''
  return t.includes('strength') || t.includes('training') || (activity.value?.exercise_sets?.length ?? 0) > 0
})
const groupedExercises = computed(() => {
  const sets = activity.value?.exercise_sets
  if (!sets?.length) return []
  const groups: Record<string, typeof sets> = {}
  for (const s of sets) {
    const name = s.exercise_name || 'Unknown'
    ;(groups[name] ??= []).push(s)
  }
  return Object.entries(groups).map(([name, sets]) => ({ name, sets }))
})

function formatDuration(seconds: number): string {
  const h = Math.floor(seconds / 3600)
  const m = Math.floor((seconds % 3600) / 60)
  const s = seconds % 60
  return h > 0 ? `${h}h ${m}m` : `${m}m ${s}s`
}

function formatDistance(meters: number | null): string {
  if (!meters) return '—'
  return `${(meters / 1000).toFixed(1)} km`
}

function buildStreamChart() {
  const times = stream.value.map(dp => new Date(dp.timestamp).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit' }))
  const powers = stream.value.map(dp => dp.power)
  const hrs = stream.value.map(dp => dp.heart_rate)
  const cadences = stream.value.map(dp => dp.cadence)

  return {
    backgroundColor: 'transparent',
    tooltip: { trigger: 'axis' },
    legend: { data: ['Power', 'HR', 'Cadence'], top: 0, textStyle: { color: '#6b7280' } },
    grid: { left: 50, right: 30, top: 45, bottom: 60 },
    dataZoom: [{ type: 'inside' }, { type: 'slider', height: 20, bottom: 10 }],
    xAxis: { type: 'category', data: times, axisLabel: { color: '#666', fontSize: 10 }, show: false },
    yAxis: [
      { type: 'value', name: 'Watts', nameTextStyle: { color: '#6b7280' }, axisLabel: { color: '#6b7280' }, splitLine: { lineStyle: { color: '#e5e7eb' } } },
      { type: 'value', name: 'bpm', nameTextStyle: { color: '#6b7280' }, axisLabel: { color: '#6b7280' }, splitLine: { show: false } },
    ],
    series: [
      { name: 'Power', type: 'line', data: powers, showSymbol: false, lineStyle: { width: 1 }, itemStyle: { color: '#3b82f6' }, areaStyle: { color: 'rgba(59,130,246,0.08)' } },
      { name: 'HR', type: 'line', yAxisIndex: 1, data: hrs, showSymbol: false, lineStyle: { width: 1 }, itemStyle: { color: '#ef4444' } },
      { name: 'Cadence', type: 'line', yAxisIndex: 1, data: cadences, showSymbol: false, lineStyle: { width: 1, type: 'dashed' }, itemStyle: { color: '#10b981' } },
    ],
  }
}

function buildElevationChart() {
  const distances: number[] = []
  let totalDist = 0
  for (let i = 0; i < stream.value.length; i++) {
    if (i > 0 && stream.value[i].speed != null) {
      totalDist += (stream.value[i].speed || 0)
    }
    distances.push(totalDist / 1000)
  }

  const altitudes = stream.value.map(dp => dp.altitude)

  return {
    backgroundColor: 'transparent',
    tooltip: { trigger: 'axis', formatter: (p: any) => `${p[0].name} km: ${p[0].value?.toFixed(0) ?? '—'}m` },
    grid: { left: 50, right: 20, top: 10, bottom: 25 },
    xAxis: {
      type: 'category',
      data: distances.map(d => d.toFixed(1)),
      axisLabel: { color: '#6b7280', fontSize: 10, formatter: (v: string) => `${v}` },
      boundaryGap: false,
    },
    yAxis: {
      type: 'value', name: 'm',
      nameTextStyle: { color: '#6b7280' },
      axisLabel: { color: '#6b7280' },
      splitLine: { lineStyle: { color: '#e5e7eb' } },
    },
    series: [{
      type: 'line',
      data: altitudes,
      showSymbol: false,
      lineStyle: { width: 1.5, color: '#8b5cf6' },
      areaStyle: {
        color: {
          type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
          colorStops: [
            { offset: 0, color: 'rgba(139,92,246,0.25)' },
            { offset: 1, color: 'rgba(139,92,246,0.02)' },
          ],
        },
      },
    }],
  }
}

function buildSpeedChart() {
  const times = stream.value.map(dp => new Date(dp.timestamp).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit' }))
  const speeds = stream.value.map(dp => dp.speed != null ? +(dp.speed * 3.6).toFixed(1) : null)

  return {
    backgroundColor: 'transparent',
    tooltip: { trigger: 'axis', formatter: (p: any) => `${p[0].value?.toFixed(1) ?? '—'} km/h` },
    grid: { left: 50, right: 20, top: 10, bottom: 50 },
    dataZoom: [{ type: 'inside' }, { type: 'slider', height: 20, bottom: 10 }],
    xAxis: { type: 'category', data: times, show: false },
    yAxis: {
      type: 'value', name: 'km/h',
      nameTextStyle: { color: '#6b7280' },
      axisLabel: { color: '#6b7280' },
      splitLine: { lineStyle: { color: '#e5e7eb' } },
    },
    series: [{
      type: 'line',
      data: speeds,
      showSymbol: false,
      lineStyle: { width: 1, color: '#f59e0b' },
      areaStyle: { color: 'rgba(245,158,11,0.08)' },
    }],
  }
}

function buildZonesChart() {
  if (!zones.value?.power_zones?.length) return null
  const z = zones.value.power_zones
  return {
    backgroundColor: 'transparent',
    tooltip: { trigger: 'axis' },
    grid: { left: 110, right: 30, top: 10, bottom: 10 },
    xAxis: { type: 'value', axisLabel: { color: '#6b7280', formatter: (v: number) => `${v}%` }, splitLine: { lineStyle: { color: '#e5e7eb' } } },
    yAxis: { type: 'category', data: z.map(i => `Z${i.zone} ${i.name}`).reverse(), axisLabel: { color: '#6b7280', fontSize: 11 } },
    series: [{
      type: 'bar',
      data: z.map(i => i.percentage).reverse(),
      itemStyle: {
        color: (params: any) => {
          const colors = ['#22c55e', '#3b82f6', '#a855f7', '#f59e0b', '#ef4444', '#dc2626', '#991b1b']
          return colors[z.length - 1 - params.dataIndex] || '#666'
        },
      },
    }],
  }
}

function buildHrZonesChart() {
  if (!zones.value?.hr_zones?.length) return null
  const z = zones.value.hr_zones
  const hrColors = ['#22c55e', '#3b82f6', '#f59e0b', '#ef4444', '#dc2626']
  return {
    backgroundColor: 'transparent',
    tooltip: { trigger: 'axis' },
    grid: { left: 110, right: 30, top: 10, bottom: 10 },
    xAxis: { type: 'value', axisLabel: { color: '#6b7280', formatter: (v: number) => `${v}%` }, splitLine: { lineStyle: { color: '#e5e7eb' } } },
    yAxis: { type: 'category', data: z.map(i => `Z${i.zone} ${i.name}`).reverse(), axisLabel: { color: '#6b7280', fontSize: 11 } },
    series: [{
      type: 'bar',
      data: z.map(i => i.percentage).reverse(),
      itemStyle: {
        color: (params: any) => hrColors[z.length - 1 - params.dataIndex] || '#666',
      },
    }],
  }
}

function buildPowerCurveChart() {
  if (!powerCurve.value?.curve) return null
  const entries = Object.entries(powerCurve.value.curve)
    .map(([dur, pow]) => [Number(dur), pow] as [number, number])
    .sort((a, b) => a[0] - b[0])

  const labels = entries.map(([d]) => {
    if (d < 60) return `${d}s`
    if (d < 3600) return `${d / 60}m`
    return `${d / 3600}h`
  })

  return {
    backgroundColor: 'transparent',
    tooltip: { trigger: 'axis', formatter: (p: any) => `${p[0].name}: ${p[0].value}W` },
    grid: { left: 50, right: 30, top: 10, bottom: 30 },
    xAxis: { type: 'category', data: labels, axisLabel: { color: '#6b7280' } },
    yAxis: { type: 'value', name: 'W', nameTextStyle: { color: '#6b7280' }, axisLabel: { color: '#6b7280' }, splitLine: { lineStyle: { color: '#e5e7eb' } } },
    series: [{
      type: 'line',
      data: entries.map(([, p]) => p),
      showSymbol: true,
      symbolSize: 6,
      areaStyle: { color: 'rgba(168,85,247,0.12)' },
      itemStyle: { color: '#a855f7' },
      lineStyle: { width: 2 },
    }],
  }
}

function initMap() {
  const gpsPoints = stream.value.filter(dp => dp.latitude && dp.longitude)
  if (gpsPoints.length < 2) return

  const map = L.map('route-map')
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; OpenStreetMap',
    maxZoom: 18,
  }).addTo(map)

  const coords: L.LatLngExpression[] = gpsPoints.map(dp => [dp.latitude!, dp.longitude!])
  const polyline = L.polyline(coords, { color: '#3b82f6', weight: 3, opacity: 0.8 }).addTo(map)

  L.circleMarker(coords[0] as L.LatLngExpression, { radius: 6, color: '#22c55e', fillColor: '#22c55e', fillOpacity: 1 }).addTo(map)
  L.circleMarker(coords[coords.length - 1] as L.LatLngExpression, { radius: 6, color: '#ef4444', fillColor: '#ef4444', fillOpacity: 1 }).addTo(map)

  map.fitBounds(polyline.getBounds(), { padding: [20, 20] })
}

async function loadAiSummary() {
  if (!activity.value || aiSummary.value) return
  aiLoading.value = true
  try {
    aiSummary.value = await store.fetchAiSummary(activity.value.id)
  } catch {
    aiSummary.value = 'Failed to generate summary. Check your Gemini API key.'
  } finally {
    aiLoading.value = false
  }
}

async function saveDiary() {
  if (!activity.value) return
  diarySaving.value = true
  diarySaved.value = false
  try {
    diary.value = await store.updateDiary(activity.value.id, diary.value)
    diarySaved.value = true
    setTimeout(() => { diarySaved.value = false }, 2000)
  } finally {
    diarySaving.value = false
  }
}

async function handleDelete() {
  if (!activity.value) return
  if (!confirm('Delete this activity? This cannot be undone.')) return
  await store.deleteActivity(activity.value.id)
  router.push({ name: 'activities' })
}

onMounted(async () => {
  const id = route.params.id as string
  try {
    const [act, str, zn, pc, di] = await Promise.all([
      store.fetchActivity(id),
      store.fetchStream(id),
      store.fetchZones(id),
      store.fetchPowerCurve(id),
      store.fetchDiary(id),
    ])
    activity.value = act
    stream.value = str
    zones.value = zn
    powerCurve.value = pc
    diary.value = di
  } finally {
    loading.value = false
  }

  // Init map after loading=false triggers DOM render of #route-map
  if (stream.value.some(dp => dp.latitude && dp.longitude)) {
    await nextTick()
    initMap()
  }
})
</script>

<template>
  <div>
    <div v-if="loading" class="flex justify-center py-20">
      <ProgressSpinner style="width: 50px; height: 50px" />
    </div>

    <div v-else-if="activity">
      <!-- Header -->
      <div class="flex items-center justify-between mb-6">
        <div class="flex items-center gap-4">
          <h1 class="text-2xl font-semibold">{{ activity.name || 'Ride' }}</h1>
          <Tag :value="activity.activity_type" severity="info" />
        </div>
        <Button icon="pi pi-trash" severity="danger" text rounded size="small" @click="handleDelete" />
      </div>

      <!-- Key metrics -->
      <div class="grid grid-cols-3 md:grid-cols-6 gap-2 md:gap-3 mb-6">
        <Card>
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Duration</p>
            <p class="text-lg font-bold">{{ formatDuration(activity.duration) }}</p>
          </template>
        </Card>
        <Card v-if="activity.distance">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Distance</p>
            <p class="text-lg font-bold">{{ formatDistance(activity.distance) }}</p>
          </template>
        </Card>
        <Card v-if="activity.metrics?.avg_power">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Avg / NP</p>
            <p class="text-lg font-bold">{{ activity.metrics.avg_power }} / {{ activity.metrics.normalized_power }}W</p>
          </template>
        </Card>
        <Card v-if="activity.metrics?.tss">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">TSS / IF</p>
            <p class="text-lg font-bold">{{ activity.metrics.tss }} / {{ activity.metrics.intensity_factor }}</p>
          </template>
        </Card>
        <Card v-if="activity.metrics?.avg_hr">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Avg / Max HR</p>
            <p class="text-lg font-bold">{{ activity.metrics.avg_hr }} / {{ activity.metrics.max_hr }}</p>
          </template>
        </Card>
        <Card v-if="activity.elevation_gain">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Elevation</p>
            <p class="text-lg font-bold">{{ activity.elevation_gain }}m</p>
          </template>
        </Card>
        <Card v-if="activity.metrics?.calories">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Calories</p>
            <p class="text-lg font-bold">{{ activity.metrics.calories }} kcal</p>
          </template>
        </Card>
        <Card v-if="isStrength && groupedExercises.length">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Exercises</p>
            <p class="text-lg font-bold">{{ groupedExercises.length }}</p>
          </template>
        </Card>
        <Card v-if="isStrength && activity.exercise_sets?.length">
          <template #content>
            <p class="text-surface-500 text-xs uppercase">Sets</p>
            <p class="text-lg font-bold">{{ activity.exercise_sets.length }}</p>
          </template>
        </Card>
      </div>

      <!-- Exercise Sets (Strength) -->
      <Card v-if="groupedExercises.length > 0" class="mb-6">
        <template #title>
          <div class="flex items-center gap-2">
            <i class="pi pi-list text-primary"></i>
            Exercises
          </div>
        </template>
        <template #content>
          <div class="space-y-4">
            <div v-for="group in groupedExercises" :key="group.name">
              <h4 class="font-semibold text-surface-800 mb-2">{{ group.name }}</h4>
              <div class="flex flex-wrap gap-2">
                <div
                  v-for="(set, i) in group.sets"
                  :key="i"
                  class="bg-surface-50 border border-surface-200 rounded-lg px-3 py-2 text-sm"
                >
                  <span class="text-surface-400 text-xs mr-1">Set {{ i + 1 }}</span>
                  <span v-if="set.repetitions" class="font-semibold">{{ set.repetitions }} reps</span>
                  <span v-if="set.weight" class="text-surface-500"> x {{ set.weight }} kg</span>
                  <span v-if="set.duration && !set.repetitions" class="font-semibold">{{ Math.round(set.duration) }}s</span>
                </div>
              </div>
            </div>
          </div>
        </template>
      </Card>

      <!-- AI Summary -->
      <Card class="mb-6">
        <template #title>
          <div class="flex items-center gap-2">
            <i class="pi pi-sparkles text-primary"></i>
            AI Coach Summary
          </div>
        </template>
        <template #content>
          <div v-if="aiSummary" v-html="aiSummary" class="text-surface-700 leading-relaxed whitespace-pre-line"></div>
          <div v-else-if="aiLoading" class="flex items-center gap-3">
            <ProgressSpinner style="width: 20px; height: 20px" />
            <span class="text-surface-500 text-sm">Analyzing your ride...</span>
          </div>
          <div v-else>
            <Button label="Generate AI Analysis" icon="pi pi-sparkles" severity="secondary" outlined size="small" @click="loadAiSummary" />
          </div>
        </template>
      </Card>

      <!-- Route Map -->
      <Card v-if="hasGps" class="mb-6">
        <template #title>Route</template>
        <template #content>
          <div id="route-map" style="height: 350px; border-radius: 8px;"></div>
        </template>
      </Card>

      <!-- Elevation Profile -->
      <Card v-if="hasAltitude" class="mb-6">
        <template #title>Elevation Profile</template>
        <template #content>
          <VChart :option="buildElevationChart()" style="height: 200px" autoresize />
        </template>
      </Card>

      <!-- Speed Profile -->
      <Card v-if="hasSpeed" class="mb-6">
        <template #title>Speed</template>
        <template #content>
          <VChart :option="buildSpeedChart()" style="height: 200px" autoresize />
        </template>
      </Card>

      <!-- Power/HR/Cadence chart -->
      <Card v-if="hasStream && (hasPower || stream.some(dp => dp.heart_rate != null))" class="mb-6">
        <template #title>{{ hasPower ? 'Power / HR / Cadence' : 'Heart Rate' }}</template>
        <template #content>
          <VChart :option="buildStreamChart()" style="height: 300px" autoresize />
        </template>
      </Card>

      <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
        <!-- Power zones -->
        <Card v-if="zones?.power_zones?.length">
          <template #title>Power Zones</template>
          <template #content>
            <VChart :option="buildZonesChart() ?? undefined" style="height: 250px" autoresize />
          </template>
        </Card>

        <!-- HR zones -->
        <Card v-if="zones?.hr_zones?.length">
          <template #title>Heart Rate Zones</template>
          <template #content>
            <VChart :option="buildHrZonesChart() ?? undefined" style="height: 200px" autoresize />
          </template>
        </Card>

        <!-- Power curve -->
        <Card v-if="powerCurve?.curve && Object.keys(powerCurve.curve).length > 0">
          <template #title>Power Curve</template>
          <template #content>
            <VChart :option="buildPowerCurveChart() ?? undefined" style="height: 250px" autoresize />
          </template>
        </Card>
      </div>

      <!-- Intervals table -->
      <Card v-if="activity.intervals?.length" class="mb-6">
        <template #title>Intervals</template>
        <template #content>
          <DataTable :value="activity.intervals" size="small" stripedRows>
            <Column field="interval_type" header="Type">
              <template #body="{ data }">
                <Tag :value="data.interval_type" :severity="data.interval_type === 'work' ? 'danger' : 'success'" />
              </template>
            </Column>
            <Column header="Duration">
              <template #body="{ data }">{{ formatDuration(data.duration || 0) }}</template>
            </Column>
            <Column field="avg_power" header="Avg Power">
              <template #body="{ data }">{{ data.avg_power ? `${data.avg_power}W` : '—' }}</template>
            </Column>
            <Column field="avg_hr" header="Avg HR">
              <template #body="{ data }">{{ data.avg_hr ? `${data.avg_hr}bpm` : '—' }}</template>
            </Column>
          </DataTable>
        </template>
      </Card>

      <!-- Training Diary -->
      <Card class="mb-6">
        <template #title>
          <div class="flex items-center gap-2">
            <i class="pi pi-book text-primary"></i>
            Training Diary
          </div>
        </template>
        <template #content>
          <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
            <div>
              <label class="text-surface-500 text-xs uppercase font-medium mb-1 block">Mood</label>
              <Select
                v-model="diary.mood"
                :options="moods"
                option-label="label"
                option-value="value"
                placeholder="How did you feel?"
                class="w-full"
              />
            </div>
            <div>
              <label class="text-surface-500 text-xs uppercase font-medium mb-1 block">RPE (1-10)</label>
              <InputNumber v-model="diary.rpe" :min="1" :max="10" class="w-full" placeholder="Rate of Perceived Exertion" />
            </div>
            <div>
              <label class="text-surface-500 text-xs uppercase font-medium mb-1 block">Sleep (hours)</label>
              <InputNumber v-model="diary.sleep_hours" :min="0" :max="24" :max-fraction-digits="1" class="w-full" placeholder="Hours slept" />
            </div>
          </div>
          <div class="mb-4">
            <label class="text-surface-500 text-xs uppercase font-medium mb-1 block">Notes</label>
            <Textarea v-model="diary.rider_notes" rows="3" class="w-full" placeholder="How was the ride? Any observations..." />
          </div>
          <div class="flex items-center gap-3">
            <Button label="Save" icon="pi pi-check" size="small" :loading="diarySaving" @click="saveDiary" />
            <span v-if="diarySaved" class="text-green-600 text-sm">Saved!</span>
          </div>
        </template>
      </Card>
    </div>
  </div>
</template>
