import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react';
import {
  View, Text, StyleSheet, ActivityIndicator, ScrollView,
  Modal, TextInput, TouchableOpacity, Pressable, Alert,
} from 'react-native';
import { useRoute, RouteProp, useNavigation } from '@react-navigation/native';
import { Map, Camera, GeoJSONSource, Layer } from '@maplibre/maplibre-react-native';
import type { LineLayerStyle } from '@maplibre/maplibre-react-native';
import { parseGpxFile } from '../services/gpx';
import { updateRecording } from '../services/db';
import { TrackPoint, RootStackParamList, SavedRecording } from '../types';
import {
  ALL_SPORTS, SPORT_ICONS, SPORT_LABELS, SPORT_SUBTYPES, SUB_SPORT_LABELS,
  type Sport, type SubSport,
} from '../sports';
import { colors } from '../theme';
import { useTheme } from '../ThemeContext';

const MAP_STYLE = 'https://tiles.openfreemap.org/styles/liberty';

type Route = RouteProp<RootStackParamList, 'ActivityDetail'>;

// ── Stats helpers ─────────────────────────────────────────────────────────────

interface Stats {
  elevationGainM: number;
  avgHr:      number | null;
  avgPower:   number | null;
  avgCadence: number | null;
}

function computeStats(points: TrackPoint[]): Stats {
  let elevationGainM = 0;
  const hrVals: number[] = [], powerVals: number[] = [], cadVals: number[] = [];
  for (let i = 1; i < points.length; i++) {
    const gain = points[i].ele - points[i - 1].ele;
    if (gain > 0) elevationGainM += gain;
  }
  for (const p of points) {
    if (p.hr    != null) hrVals.push(p.hr);
    if (p.power != null) powerVals.push(p.power);
    if (p.cad   != null) cadVals.push(p.cad);
  }
  const avg = (a: number[]) => a.length ? Math.round(a.reduce((s, v) => s + v, 0) / a.length) : null;
  return { elevationGainM, avgHr: avg(hrVals), avgPower: avg(powerVals), avgCadence: avg(cadVals) };
}

function formatDuration(secs: number) {
  const h = Math.floor(secs / 3600).toString().padStart(2, '0');
  const m = Math.floor((secs % 3600) / 60).toString().padStart(2, '00');
  const s = (secs % 60).toString().padStart(2, '0');
  return `${h}:${m}:${s}`;
}

// ── Screen ────────────────────────────────────────────────────────────────────

export function ActivityDetailScreen() {
  const nav = useNavigation();
  const { accent, accentDim } = useTheme();
  const route = useRoute<Route>();

  const [rec, setRec]       = useState<SavedRecording>(route.params.recording);
  const [points, setPoints] = useState<TrackPoint[] | null>(null);
  const [loadError, setLoadError] = useState<string | null>(null);

  // Edit modal state
  const [editVisible,  setEditVisible]  = useState(false);
  const [editTitle,    setEditTitle]    = useState(rec.title);
  const [editSport,    setEditSport]    = useState<Sport>(rec.sport as Sport);
  const [editSubSport, setEditSubSport] = useState<SubSport | null>(rec.subSport as SubSport | null);
  const [saving,       setSaving]       = useState(false);

  // Header "Edit" button
  useLayoutEffect(() => {
    nav.setOptions({
      headerTitle: rec.title,
      headerRight: () => (
        <TouchableOpacity onPress={() => setEditVisible(true)} style={{ marginRight: 16 }}>
          <Text style={{ color: accent, fontSize: 15, fontWeight: '600' }}>Edit</Text>
        </TouchableOpacity>
      ),
    });
  }, [nav, rec.title, accent]);

  useEffect(() => {
    parseGpxFile(rec.filePath)
      .then(setPoints)
      .catch((e) => setLoadError(e?.message ?? 'Failed to load track'));
  }, [rec.filePath]);

  const trackLineStyle = useMemo<LineLayerStyle>(() => ({
    lineColor: accent, lineWidth: 3, lineJoin: 'round', lineCap: 'round',
  }), [accent]);

  const trackGeoJSON = useMemo<GeoJSON.Feature<GeoJSON.LineString> | null>(() => {
    if (!points || points.length < 2) return null;
    return {
      type: 'Feature',
      geometry: { type: 'LineString', coordinates: points.map((p) => [p.lon, p.lat]) },
      properties: {},
    };
  }, [points]);

  const bounds = useMemo(() => {
    if (!points || points.length === 0) return null;
    const pad = 0.001;
    return [
      Math.min(...points.map((p) => p.lon)) - pad,
      Math.min(...points.map((p) => p.lat)) - pad,
      Math.max(...points.map((p) => p.lon)) + pad,
      Math.max(...points.map((p) => p.lat)) + pad,
    ] as [number, number, number, number];
  }, [points]);

  const stats = useMemo(() => points ? computeStats(points) : null, [points]);

  const avgSpeedKph = rec.durationSeconds > 0
    ? (rec.distanceMeters / 1000) / (rec.durationSeconds / 3600) : 0;

  const sportSummary = [
    SPORT_ICONS[rec.sport as Sport] ?? '⚡',
    SPORT_LABELS[rec.sport as Sport] ?? rec.sport,
    rec.subSport ? (SUB_SPORT_LABELS[rec.subSport as SubSport] ?? rec.subSport) : null,
  ].filter(Boolean).join(' · ');

  // ── Edit handlers ──────────────────────────────────────────────────────────

  function handleEditSport(s: Sport) { setEditSport(s); setEditSubSport(null); }

  async function handleSave() {
    if (!editTitle.trim()) { Alert.alert('Title required'); return; }
    setSaving(true);
    try {
      await updateRecording(rec.id, { title: editTitle.trim(), sport: editSport, subSport: editSubSport });
      setRec((prev) => ({ ...prev, title: editTitle.trim(), sport: editSport, subSport: editSubSport }));
      setEditVisible(false);
    } catch (e: any) {
      Alert.alert('Save failed', e?.message ?? 'Unknown error');
    } finally {
      setSaving(false);
    }
  }

  function handleCancelEdit() {
    // Reset edit fields to current rec values
    setEditTitle(rec.title);
    setEditSport(rec.sport as Sport);
    setEditSubSport(rec.subSport as SubSport | null);
    setEditVisible(false);
  }

  const editSubtypes = SPORT_SUBTYPES[editSport] ?? [];

  // ── Render ─────────────────────────────────────────────────────────────────

  if (loadError) {
    return <View style={styles.center}><Text style={styles.errorText}>{loadError}</Text></View>;
  }

  return (
    <View style={styles.container}>
      {/* Map */}
      <View style={styles.mapArea}>
        {points === null
          ? <View style={styles.center}><ActivityIndicator color={accent} /></View>
          : (
            <Map mapStyle={MAP_STYLE} style={StyleSheet.absoluteFill} logo={false} attribution={false}>
              {bounds && (
                <Camera
                  initialViewState={{ bounds, padding: { top: 32, bottom: 32, left: 32, right: 32 } }}
                />
              )}
              {trackGeoJSON && (
                <GeoJSONSource id="track" data={trackGeoJSON}>
                  <Layer id="track-line" type="line" style={trackLineStyle} />
                </GeoJSONSource>
              )}
            </Map>
          )}
      </View>

      {/* Stats */}
      <ScrollView style={styles.statsScroll} contentContainerStyle={styles.statsContent}>
        <Text style={styles.sportSummary}>{sportSummary}</Text>
        <Text style={styles.date}>{new Date(rec.date).toLocaleString()}</Text>

        <View style={styles.grid}>
          <StatBox label="Duration"    value={formatDuration(rec.durationSeconds)} />
          <StatBox label="Distance"    value={`${(rec.distanceMeters / 1000).toFixed(2)} km`} />
          <StatBox label="Avg Speed"   value={`${avgSpeedKph.toFixed(1)} km/h`} />
          <StatBox label="Elevation"   value={stats ? `+${stats.elevationGainM.toFixed(0)} m` : '…'} />
          <StatBox label="Avg HR"      value={stats?.avgHr      != null ? `${stats.avgHr} bpm`     : '—'} />
          <StatBox label="Avg Power"   value={stats?.avgPower   != null ? `${stats.avgPower} W`     : '—'} />
          <StatBox label="Avg Cadence" value={stats?.avgCadence != null ? `${stats.avgCadence} rpm` : '—'} />
          <StatBox label="Points"      value={points != null ? `${points.length}` : '…'} />
        </View>
      </ScrollView>

      {/* ── Edit modal ── */}
      <Modal visible={editVisible} animationType="slide" presentationStyle="pageSheet" onRequestClose={handleCancelEdit}>
        <View style={styles.editContainer}>
          <View style={styles.editHeader}>
            <TouchableOpacity onPress={handleCancelEdit}>
              <Text style={styles.editCancel}>Cancel</Text>
            </TouchableOpacity>
            <Text style={styles.editHeading}>Edit activity</Text>
            <TouchableOpacity onPress={handleSave} disabled={saving}>
              <Text style={[styles.editSave, { color: accent }, saving && { opacity: 0.5 }]}>
                {saving ? 'Saving…' : 'Save'}
              </Text>
            </TouchableOpacity>
          </View>

          <ScrollView contentContainerStyle={styles.editContent}>
            <Text style={styles.editSectionLabel}>Title</Text>
            <TextInput
              style={styles.editInput}
              value={editTitle}
              onChangeText={setEditTitle}
              placeholder="Activity title"
              placeholderTextColor={colors.placeholder}
              autoCorrect={false}
            />

            <Text style={styles.editSectionLabel}>Activity type</Text>
            <View style={styles.sportGrid}>
              {ALL_SPORTS.map((s) => {
                const active = editSport === s;
                return (
                  <TouchableOpacity
                    key={s}
                    style={[styles.sportPill, active && { borderColor: accent, backgroundColor: accentDim }]}
                    onPress={() => handleEditSport(s)}
                  >
                    <Text style={styles.sportIcon}>{SPORT_ICONS[s]}</Text>
                    <Text style={[styles.sportLabel, active && { color: accent }]}>{SPORT_LABELS[s]}</Text>
                  </TouchableOpacity>
                );
              })}
            </View>

            {editSubtypes.length > 0 && (
              <>
                <Text style={styles.editSectionLabel}>Subtype</Text>
                <View style={styles.subRow}>
                  {editSubtypes.map((sub) => {
                    const active = editSubSport === sub;
                    return (
                      <TouchableOpacity
                        key={sub}
                        style={[styles.subPill, active && { borderColor: accent, backgroundColor: accentDim }]}
                        onPress={() => setEditSubSport(active ? null : sub)}
                      >
                        <Text style={[styles.subLabel, active && { color: accent }]}>{SUB_SPORT_LABELS[sub]}</Text>
                      </TouchableOpacity>
                    );
                  })}
                </View>
              </>
            )}
          </ScrollView>
        </View>
      </Modal>
    </View>
  );
}

function StatBox({ label, value }: { label: string; value: string }) {
  return (
    <View style={styles.statBox}>
      <Text style={styles.statLabel}>{label}</Text>
      <Text style={styles.statValue}>{value}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container:        { flex: 1, backgroundColor: colors.bg },
  center:           { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.bg },
  errorText:        { color: colors.error, fontSize: 14 },
  mapArea:          { flex: 1 },
  statsScroll:      { maxHeight: 260, borderTopWidth: 1, borderTopColor: colors.border },
  statsContent:     { padding: 16, gap: 10 },
  sportSummary:     { color: colors.text, fontSize: 15, fontWeight: '600' },
  date:             { color: colors.textMuted, fontSize: 12 },
  grid:             { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
  statBox:          { width: '47%', backgroundColor: colors.surface, borderWidth: 1, borderColor: colors.border, borderRadius: 10, padding: 12 },
  statLabel:        { color: colors.textMuted, fontSize: 10, textTransform: 'uppercase', letterSpacing: 0.5 },
  statValue:        { color: colors.text, fontSize: 18, fontWeight: '600', marginTop: 4 },
  // Edit modal
  editContainer:    { flex: 1, backgroundColor: colors.bg },
  editHeader:       { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16, borderBottomWidth: 1, borderBottomColor: colors.border },
  editHeading:      { color: colors.text, fontSize: 16, fontWeight: '700' },
  editCancel:       { color: colors.textSub, fontSize: 15 },
  editSave:         { fontSize: 15, fontWeight: '700' },
  editContent:      { padding: 16, gap: 12 },
  editSectionLabel: { color: colors.textMuted, fontSize: 11, textTransform: 'uppercase', letterSpacing: 0.8 },
  editInput:        { backgroundColor: colors.surface, borderWidth: 1, borderColor: colors.border, color: colors.text, borderRadius: 10, padding: 14, fontSize: 16 },
  sportGrid:        { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
  sportPill:        { flexDirection: 'row', alignItems: 'center', gap: 6, paddingVertical: 9, paddingHorizontal: 14, borderRadius: 20, borderWidth: 1, borderColor: colors.borderStrong, backgroundColor: colors.surface },
  sportIcon:        { fontSize: 16 },
  sportLabel:       { color: colors.textSub, fontSize: 13, fontWeight: '500' },
  subRow:           { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
  subPill:          { paddingVertical: 7, paddingHorizontal: 14, borderRadius: 20, borderWidth: 1, borderColor: colors.borderStrong, backgroundColor: colors.surface },
  subLabel:         { color: colors.textSub, fontSize: 13, fontWeight: '500' },
});
