import { useState, useEffect, useRef, useMemo } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '../utils/api'
import { useAuthStore } from '../hooks/useAuth'

function Section({ title, children }) {
  return (
    <div className="bg-gray-900 rounded-xl border border-gray-800 p-5 space-y-4">
      <h2 className="text-sm font-semibold text-gray-300">{title}</h2>
      {children}
    </div>
  )
}

function Field({ label, hint, children }) {
  return (
    <div>
      <label className="text-xs text-gray-400 block mb-1">{label}</label>
      {children}
      {hint && <p className="text-xs text-gray-600 mt-1">{hint}</p>}
    </div>
  )
}

function Input({ type = 'text', value, onChange, placeholder, min, max }) {
  return (
    <input type={type} value={value} onChange={onChange} placeholder={placeholder} min={min} max={max}
      className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-blue-500" />
  )
}

function SaveButton({ onClick, loading, saved, label = 'Save' }) {
  return (
    <div className="flex items-center gap-3 pt-1">
      <button onClick={onClick} disabled={loading}
        className="bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white text-sm font-medium px-4 py-2 rounded-lg transition-colors">
        {loading ? 'Saving…' : label}
      </button>
      {saved && <span className="text-green-400 text-sm">✓ Saved</span>}
    </div>
  )
}

export default function ProfilePage() {
  const qc = useQueryClient()
  const { user } = useAuthStore()

  const { data: profile } = useQuery({
    queryKey: ['profile'],
    queryFn: () => api.get('/profile/').then(r => r.data),
  })

  const { data: pocketidConfig } = useQuery({
    queryKey: ['pocketid-config'],
    queryFn: () => api.get('/profile/pocketid-config').then(r => r.data),
    enabled: !!user?.is_admin,
  })

  const { data: recentMetrics } = useQuery({
    queryKey: ['health-metrics-recent'],
    queryFn: () => api.get('/health-metrics/', { params: { limit: 7 } }).then(r => r.data),
  })

  const { data: healthSummary } = useQuery({
    queryKey: ['health-summary'],
    queryFn: () => api.get('/health-metrics/summary').then(r => r.data),
  })

  const avgRestingHr = useMemo(() => {
    if (!recentMetrics?.length) return null
    const vals = recentMetrics.filter(m => m.resting_hr != null).map(m => m.resting_hr)
    if (!vals.length) return null
    return Math.round(vals.reduce((s, v) => s + v, 0) / vals.length)
  }, [recentMetrics])

  // HR / measurements form
  const [hrForm, setHrForm] = useState({ max_heart_rate: '', birth_year: '', height_cm: '' })
  const [hrSaved, setHrSaved] = useState(false)
  const [hrZoneRecalc, setHrZoneRecalc] = useState(false)
  const maxHrChangedRef = useRef(false)
  useEffect(() => {
    if (profile) setHrForm({
      max_heart_rate: profile.max_heart_rate || '',
      birth_year: profile.birth_year || '',
      height_cm: profile.height_cm || '',
    })
  }, [profile])

  const updateProfile = useMutation({
    mutationFn: data => api.patch('/profile/', data).then(r => r.data),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['profile'] })
      setHrSaved(true)
      setTimeout(() => setHrSaved(false), 3000)
      if (maxHrChangedRef.current) {
        setHrZoneRecalc(true)
        setTimeout(() => setHrZoneRecalc(false), 6000)
        maxHrChangedRef.current = false
      }
    },
  })

  // Password change
  const [pwForm, setPwForm] = useState({ current_password: '', new_password: '', confirm: '' })
  const [pwError, setPwError] = useState('')
  const [pwSaved, setPwSaved] = useState(false)
  const changePassword = useMutation({
    mutationFn: data => api.post('/profile/change-password', data).then(r => r.data),
    onSuccess: () => { setPwSaved(true); setPwForm({ current_password: '', new_password: '', confirm: '' }); setTimeout(() => setPwSaved(false), 3000) },
    onError: e => setPwError(e.response?.data?.detail || 'Failed to change password'),
  })

  // Garmin Connect sync
  const { data: garminConfig, refetch: refetchGarmin } = useQuery({
    queryKey: ['garmin-config'],
    queryFn: () => api.get('/garmin-sync/config').then(r => r.data),
  })
  const [gcForm, setGcForm] = useState({ email: '', password: '', sync_enabled: true, sync_activities: true, sync_wellness: true, sync_lookback_days: 30 })
  const [gcSaved, setGcSaved] = useState(false)
  const [gcError, setGcError] = useState('')
  const [gcSyncing, setGcSyncing] = useState(false)
  const syncPollRef = useRef(null)
  useEffect(() => () => { if (syncPollRef.current) clearInterval(syncPollRef.current) }, [])
  useEffect(() => {
    if (garminConfig?.connected) {
      setGcForm(f => ({
        ...f,
        email: garminConfig.email || '',
        sync_enabled: garminConfig.sync_enabled,
        sync_activities: garminConfig.sync_activities,
        sync_wellness: garminConfig.sync_wellness,
        sync_lookback_days: garminConfig.sync_lookback_days ?? 30,
      }))
    }
  }, [garminConfig])
  const saveGarmin = useMutation({
    mutationFn: data => api.put('/garmin-sync/config', data).then(r => r.data),
    onSuccess: () => {
      refetchGarmin()
      setGcSaved(true)
      setGcError('')
      setGcForm(f => ({ ...f, password: '' }))
      setTimeout(() => setGcSaved(false), 3000)
    },
    onError: e => setGcError(e.response?.data?.detail || 'Failed to save'),
  })
  const deleteGarmin = useMutation({
    mutationFn: () => api.delete('/garmin-sync/config'),
    onSuccess: () => {
      refetchGarmin()
      setGcForm({ email: '', password: '', sync_enabled: true, sync_activities: true, sync_wellness: true, sync_lookback_days: 30 })
    },
  })
  const triggerGarminSync = async () => {
    setGcSyncing(true)
    try {
      await api.post('/garmin-sync/trigger')
      // Poll every 2s: wait until we've seen an in-progress status, then wait for terminal
      let seenInProgress = false
      syncPollRef.current = setInterval(async () => {
        const result = await refetchGarmin()
        const status = result.data?.last_sync_status ?? ''
        const terminal = status.startsWith('OK') || status.startsWith('Partial') || status.startsWith('Auth error')
        if (!terminal) seenInProgress = true
        if (seenInProgress && terminal) {
          clearInterval(syncPollRef.current)
          syncPollRef.current = null
          setGcSyncing(false)
        }
      }, 2000)
      // Safety: stop polling after 10 minutes regardless
      setTimeout(() => {
        if (syncPollRef.current) { clearInterval(syncPollRef.current); syncPollRef.current = null }
        setGcSyncing(false)
      }, 600000)
    } catch {
      setGcSyncing(false)
    }
  }

  const syncProgressPct = status => {
    if (!status) return 5
    if (status.startsWith('Connecting')) return 10
    if (status.startsWith('Syncing activities')) return 35
    if (status.startsWith('Syncing wellness')) return 70
    return 5
  }

  // PocketID config
  const [pidForm, setPidForm] = useState({ issuer: '', client_id: '', client_secret: '' })
  const [pidSaved, setPidSaved] = useState(false)
  useEffect(() => {
    if (pocketidConfig) setPidForm({ issuer: pocketidConfig.issuer || '', client_id: pocketidConfig.client_id || '', client_secret: '' })
  }, [pocketidConfig])
  const savePocketID = useMutation({
    mutationFn: data => api.post('/profile/pocketid-config', data).then(r => r.data),
    onSuccess: () => { qc.invalidateQueries({ queryKey: ['pocketid-config'] }); setPidSaved(true); setTimeout(() => setPidSaved(false), 3000) },
  })

  const effectiveMaxHr = profile?.max_heart_rate || profile?.estimated_max_hr

  return (
    <div className="p-6 max-w-2xl space-y-6">
      <h1 className="text-2xl font-bold text-white">Profile & Settings</h1>

      {/* HR & Measurements */}
      <Section title="Heart Rate & Measurements">
        <div className="bg-blue-950/30 border border-blue-900/40 rounded-lg p-3 text-xs text-gray-400">
          Max HR is used for accurate zone calculations. Set it from your hardest recorded effort or a lab test.
          {effectiveMaxHr && (
            <div className="mt-2 text-white">
              Effective max HR: <strong>{effectiveMaxHr} bpm</strong>
              {!profile?.max_heart_rate && ' (estimated from age)'}
              {' · '}Zones: Z1 &lt;{Math.round(effectiveMaxHr * 0.6)}, Z2 {Math.round(effectiveMaxHr * 0.6)}–{Math.round(effectiveMaxHr * 0.7)}, Z3 {Math.round(effectiveMaxHr * 0.7)}–{Math.round(effectiveMaxHr * 0.8)}, Z4 {Math.round(effectiveMaxHr * 0.8)}–{Math.round(effectiveMaxHr * 0.9)}, Z5 &gt;{Math.round(effectiveMaxHr * 0.9)}
            </div>
          )}
        </div>

        <div className="grid grid-cols-2 gap-4">
          <Field label="Max heart rate (bpm)" hint="Best from a sprint test or hard race">
            <Input type="number" value={hrForm.max_heart_rate} placeholder="e.g. 185" min={100} max={250}
              onChange={e => setHrForm(f => ({ ...f, max_heart_rate: e.target.value }))} />
          </Field>
          <Field label="Birth year" hint="Used to estimate max HR if not set above">
            <Input type="number" value={hrForm.birth_year} placeholder="e.g. 1988" min={1920} max={2010}
              onChange={e => setHrForm(f => ({ ...f, birth_year: e.target.value }))} />
          </Field>
          <Field label="Height (cm)">
            <Input type="number" value={hrForm.height_cm} placeholder="e.g. 178" min={50} max={300}
              onChange={e => setHrForm(f => ({ ...f, height_cm: e.target.value }))} />
          </Field>
        </div>

        {(avgRestingHr || healthSummary?.latest?.weight_kg) && (
          <div className="flex gap-6 pt-3 border-t border-gray-800">
            {avgRestingHr && (
              <div>
                <p className="text-xs text-gray-500 mb-0.5">Resting HR (7-day avg, from Garmin)</p>
                <span className="text-lg font-semibold text-rose-400">{avgRestingHr} bpm</span>
              </div>
            )}
            {healthSummary?.latest?.weight_kg && (
              <div>
                <p className="text-xs text-gray-500 mb-0.5">Weight (from Garmin)</p>
                <span className="text-lg font-semibold text-emerald-400">{healthSummary.latest.weight_kg.toFixed(1)} kg</span>
              </div>
            )}
          </div>
        )}

        <SaveButton
          onClick={() => {
            const data = Object.fromEntries(
              Object.entries(hrForm).filter(([,v]) => v !== '').map(([k,v]) => [k, parseFloat(v)])
            )
            maxHrChangedRef.current = data.max_heart_rate !== undefined && data.max_heart_rate !== profile?.max_heart_rate
            updateProfile.mutate(data)
          }}
          loading={updateProfile.isPending}
          saved={hrSaved}
        />
        {hrZoneRecalc && (
          <p className="text-xs text-blue-400 mt-1">HR zones are being recalculated for your existing activities.</p>
        )}
      </Section>

      {/* Password change */}
      <Section title="Change Password">
        <div className="space-y-3">
          <Field label="Current password">
            <Input type="password" value={pwForm.current_password}
              onChange={e => { setPwForm(f => ({ ...f, current_password: e.target.value })); setPwError('') }} />
          </Field>
          <Field label="New password (min 8 characters)">
            <Input type="password" value={pwForm.new_password}
              onChange={e => setPwForm(f => ({ ...f, new_password: e.target.value }))} />
          </Field>
          <Field label="Confirm new password">
            <Input type="password" value={pwForm.confirm}
              onChange={e => setPwForm(f => ({ ...f, confirm: e.target.value }))} />
          </Field>
          {pwError && <p className="text-red-400 text-xs">{pwError}</p>}
        </div>
        <SaveButton
          onClick={() => {
            if (pwForm.new_password !== pwForm.confirm) { setPwError('Passwords do not match'); return }
            changePassword.mutate({ current_password: pwForm.current_password, new_password: pwForm.new_password })
          }}
          loading={changePassword.isPending}
          saved={pwSaved}
          label="Change password"
        />
      </Section>

      {/* Garmin Connect Sync */}
      <Section title="⌚ Garmin Connect Sync">
        <p className="text-xs text-gray-500">
          Connect your Garmin account to automatically import new activities and wellness data every hour.
          Credentials are encrypted at rest.
        </p>

        {garminConfig?.connected && (
          <div className="flex items-center justify-between bg-green-900/20 border border-green-800/40 rounded-lg px-3 py-2 text-xs">
            <span className="text-green-400">✓ Connected as {garminConfig.email}</span>
            <div className="flex items-center gap-3">
              {garminConfig.last_sync_at && (
                <span className="text-gray-500">
                  Last sync: {new Date(garminConfig.last_sync_at).toLocaleString('en-GB', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })}
                </span>
              )}
              {garminConfig.last_sync_status && (
                <span className={garminConfig.last_sync_status.startsWith('OK') ? 'text-green-400' : garminConfig.last_sync_status.startsWith('Auth') ? 'text-red-400' : 'text-yellow-400'}>
                  {garminConfig.last_sync_status}
                </span>
              )}
            </div>
          </div>
        )}

        <div className="space-y-3">
          <Field label="Garmin Connect email">
            <Input value={gcForm.email} placeholder="you@example.com"
              onChange={e => setGcForm(f => ({ ...f, email: e.target.value }))} />
          </Field>
          <Field label={garminConfig?.connected ? 'Password (leave blank to keep existing)' : 'Password'}>
            <Input type="password" value={gcForm.password} placeholder="••••••••"
              onChange={e => setGcForm(f => ({ ...f, password: e.target.value }))} />
          </Field>

          <div className="flex flex-wrap gap-4 pt-1">
            {[
              ['sync_enabled',     'Enable hourly sync'],
              ['sync_activities',  'Sync activities (FIT download)'],
              ['sync_wellness',    'Sync wellness data'],
            ].map(([key, label]) => (
              <label key={key} className="flex items-center gap-2 cursor-pointer">
                <input type="checkbox" checked={gcForm[key]}
                  onChange={e => setGcForm(f => ({ ...f, [key]: e.target.checked }))}
                  className="w-4 h-4 accent-blue-500" />
                <span className="text-sm text-gray-300">{label}</span>
              </label>
            ))}
          </div>

          <Field label="Sync lookback days" hint="-1 syncs all available history (back to 2010). Leave at 30 for incremental syncs.">
            <Input type="number" value={gcForm.sync_lookback_days} min={-1}
              onChange={e => setGcForm(f => ({ ...f, sync_lookback_days: parseInt(e.target.value, 10) || 30 }))} />
            {gcForm.sync_lookback_days > 365 && gcForm.sync_lookback_days !== -1 && (
              <p className="text-yellow-400 text-xs mt-1">Warning: syncing more than 365 days at once may take a long time and could trigger Garmin rate limits.</p>
            )}
          </Field>
        </div>

        {gcError && <p className="text-red-400 text-xs">{gcError}</p>}

        <div className="flex items-center gap-3 flex-wrap pt-1">
          <SaveButton
            onClick={() => {
              if (!garminConfig?.connected && !gcForm.password) {
                setGcError('Password is required for first-time setup')
                return
              }
              const payload = { ...gcForm }
              if (!payload.password) delete payload.password
              saveGarmin.mutate(payload)
            }}
            loading={saveGarmin.isPending}
            saved={gcSaved}
            label={garminConfig?.connected ? 'Update' : 'Connect'}
          />
          {garminConfig?.connected && (
            <>
              <button
                onClick={triggerGarminSync}
                disabled={gcSyncing}
                className="bg-gray-700 hover:bg-gray-600 disabled:opacity-50 text-white text-sm font-medium px-4 py-2 rounded-lg transition-colors">
                {gcSyncing ? 'Syncing…' : '↻ Sync now'}
              </button>
              <button
                onClick={() => { if (confirm('Remove Garmin Connect credentials?')) deleteGarmin.mutate() }}
                className="text-red-400 hover:text-red-300 text-sm transition-colors">
                Disconnect
              </button>
            </>
          )}
        </div>

        {gcSyncing && (
          <div className="space-y-1.5">
            <div className="h-1.5 bg-gray-800 rounded-full overflow-hidden">
              <div
                className="h-full bg-blue-500 rounded-full transition-all duration-700"
                style={{ width: `${syncProgressPct(garminConfig?.last_sync_status)}%` }}
              />
            </div>
            <p className="text-xs text-blue-400">
              {garminConfig?.last_sync_status || 'Starting sync…'}
            </p>
          </div>
        )}
      </Section>

      {/* PocketID — admin only */}
      {user?.is_admin && (
        <Section title="🔑 PocketID Passkey Authentication (Admin)">
          <p className="text-xs text-gray-500">
            Configure passkey authentication via PocketID. Once set, a "Sign in with passkey" button appears on the login page.
          </p>
          <div className="space-y-3">
            <Field label="PocketID issuer URL" hint="e.g. https://auth.yourdomain.com">
              <Input value={pidForm.issuer} placeholder="https://auth.example.com"
                onChange={e => setPidForm(f => ({ ...f, issuer: e.target.value }))} />
            </Field>
            <Field label="Client ID">
              <Input value={pidForm.client_id} placeholder="milevault"
                onChange={e => setPidForm(f => ({ ...f, client_id: e.target.value }))} />
            </Field>
            <Field label="Client secret" hint="Leave blank to keep existing secret">
              <Input type="password" value={pidForm.client_secret} placeholder="••••••••"
                onChange={e => setPidForm(f => ({ ...f, client_secret: e.target.value }))} />
            </Field>
            {pocketidConfig?.enabled && (
              <p className="text-xs text-green-400">✓ PocketID is currently active</p>
            )}
          </div>
          <SaveButton
            onClick={() => savePocketID.mutate(pidForm)}
            loading={savePocketID.isPending}
            saved={pidSaved}
            label="Save PocketID config"
          />
        </Section>
      )}
    </div>
  )
}
