import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { ErrBox, Loading, Panel, Screen, Sec, SrcNote, Tile, TileGrid } from '../components/ui';
import { load } from '../lib/api';
import { fmtD, fmtDY, num } from '../lib/format';
import { C } from '../lib/theme';
import type { DexaIndex, DexaResponse } from '../lib/types';
import { useLoad } from '../lib/use-load';

function delta(
  curV: number | null | undefined,
  prevV: number | null | undefined,
  goodDir: -1 | 0 | 1,
  unit: string,
  prevDate: string,
  dp = 1,
): { text: string; tone: 'good' | 'bad' | 'neutral' } | undefined {
  if (prevV == null || curV == null) return undefined;
  const d = curV - prevV;
  if (Math.abs(d) < 1e-9) return { text: 'unchanged', tone: 'neutral' };
  const good = goodDir === 0 ? null : (d > 0) === (goodDir > 0);
  return {
    text: `${d > 0 ? '▲' : '▼'} ${Math.abs(d).toFixed(dp)}${unit} vs ${fmtD(prevDate)}`,
    tone: good == null ? 'neutral' : good ? 'good' : 'bad',
  };
}

function IdxTable({ title, arr }: { title: string; arr?: DexaIndex[] }) {
  if (!Array.isArray(arr) || !arr.length) return null;
  return (
    <>
      <Sec title={title} />
      <Panel>
        <View style={s.tr}>
          <Text style={[s.th, { flex: 2 }]}>MEASURE</Text>
          <Text style={s.th}>RESULT</Text>
          <Text style={s.th}>%ILE (YN)</Text>
        </View>
        {arr.map((r) => (
          <View key={r.measure} style={s.tr}>
            <Text style={[s.td, { flex: 2, color: C.muted }]}>{r.measure}</Text>
            <Text style={s.td}>
              {r.result}
              {r.unit ? ` ${r.unit}` : ''}
            </Text>
            <Text style={s.td}>{r.percentile_yn != null ? `${r.percentile_yn}%` : '—'}</Text>
          </View>
        ))}
      </Panel>
    </>
  );
}

export default function Body() {
  const { data, err, loading, refresh } = useLoad(() => load<DexaResponse>('dexa'));

  let body: React.ReactNode = null;
  if (loading && !data) body = <Loading />;
  else if (err) body = <ErrBox msg={err} />;
  else if (data) {
    const scans = data.scans;
    const cur = scans[scans.length - 1];
    const prev = scans.length > 1 ? scans[scans.length - 2] : null;
    const sm = cur.summary;
    const p = prev?.summary;
    const pd = prev?.scan_date ?? '';
    const reg = cur.body_composition_by_region;

    body = (
      <>
        <TileGrid>
          <Tile label="Body fat" value={String(sm.total_body_fat_pct)} unit="%"
            {...toDelta(delta(sm.total_body_fat_pct, p?.total_body_fat_pct, -1, ' pp', pd))} />
          <Tile label="Lean mass" value={String(sm.total_lean_mass_kg)} unit="kg"
            {...toDelta(delta(sm.total_lean_mass_kg, p?.total_lean_mass_kg, 1, ' kg', pd))} />
          <Tile label="Fat mass" value={String(sm.total_fat_mass_kg)} unit="kg"
            {...toDelta(delta(sm.total_fat_mass_kg, p?.total_fat_mass_kg, 0, ' kg', pd))} />
          <Tile label="Total mass" value={String(sm.total_mass_kg)} unit="kg"
            {...toDelta(delta(sm.total_mass_kg, p?.total_mass_kg, 0, ' kg', pd))} />
          <Tile label="Visceral fat (VAT)" value={String(sm.est_vat_area_cm2)} unit="cm²"
            sub={sm.est_vat_risk}
            {...toDelta(delta(sm.est_vat_area_cm2, p?.est_vat_area_cm2, -1, ' cm²', pd))} />
          <Tile label="ALMI" value={String(sm.appendicular_lean_mass_to_height2_kg_m2)} unit="kg/m²"
            sub={`threshold ${sm.appendicular_lean_mass_normal_threshold_kg_m2}`}
            {...toDelta(delta(
              sm.appendicular_lean_mass_to_height2_kg_m2,
              p?.appendicular_lean_mass_to_height2_kg_m2, 1, '', pd, 2,
            ))} />
          <Tile label="Bone density" value={String(sm.total_body_bmd_g_cm2)} unit="g/cm²"
            {...toDelta(delta(sm.total_body_bmd_g_cm2, p?.total_body_bmd_g_cm2, 1, '', pd, 3))} />
          <Tile label="Est. RMR" value={num(sm.resting_metabolic_rate_kcal_day)} unit="kcal"
            {...toDelta(delta(
              sm.resting_metabolic_rate_kcal_day, p?.resting_metabolic_rate_kcal_day, 0, ' kcal', pd, 0,
            ))} />
        </TileGrid>
        <SrcNote>
          DXA scan {fmtDY(cur.scan_date)} — {cur.provider}, {cur.model || 'Hologic Horizon'}.
          {prev ? ` Deltas vs ${fmtDY(prev.scan_date)}.` : ''}
        </SrcNote>

        {Array.isArray(reg) && reg.length ? (
          <>
            <Sec title="By region" />
            <Panel>
              <View style={s.tr}>
                <Text style={[s.th, { flex: 2 }]}>REGION</Text>
                <Text style={s.th}>FAT %</Text>
                <Text style={s.th}>LEAN KG</Text>
                <Text style={s.th}>FAT KG</Text>
              </View>
              {reg.map((r) => (
                <View key={r.region} style={s.tr}>
                  <Text style={[s.td, { flex: 2, color: C.muted }]}>{r.region}</Text>
                  <Text style={s.td}>{r.fat_pct ?? '—'}</Text>
                  <Text style={s.td}>{r.lean_mass_g ? (r.lean_mass_g / 1000).toFixed(1) : '—'}</Text>
                  <Text style={s.td}>{r.fat_mass_g ? (r.fat_mass_g / 1000).toFixed(1) : '—'}</Text>
                </View>
              ))}
            </Panel>
          </>
        ) : null}

        <IdxTable title="Adipose indices" arr={cur.adipose_indices} />
        <IdxTable title="Lean indices" arr={cur.lean_indices} />
      </>
    );
  }

  return <Screen onRefresh={refresh}>{body}</Screen>;
}

function toDelta(d?: { text: string; tone: 'good' | 'bad' | 'neutral' }) {
  return d ? { delta: d.text, deltaTone: d.tone } : {};
}

const s = StyleSheet.create({
  tr: {
    flexDirection: 'row', gap: 8, paddingVertical: 6,
    borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: '#1e1e23',
  },
  th: { flex: 1, fontSize: 10, letterSpacing: 0.5, color: C.muted, fontWeight: '600' },
  td: { flex: 1, fontSize: 12, color: C.text, fontVariant: ['tabular-nums'] },
});
