import * as ImagePicker from 'expo-image-picker';
import { useCallback, useEffect, useState } from 'react';
import { ActivityIndicator, Image, Pressable, ScrollView, StyleSheet, TextInput, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

import { Button } from '@/components/button';
import { Card } from '@/components/card';
import { ScreenBackground } from '@/components/screen-background';
import { ThemedText } from '@/components/themed-text';
import { Spacing, TopTabInset } from '@/constants/theme';
import { useTheme } from '@/hooks/use-theme';
import { useAuth } from '@/lib/auth-context';
import { getSignedReportUrl, uploadEvaluationReport } from '@/lib/evaluation-photos';
import { awardEvaluationPoints } from '@/lib/points';
import { errorMessage } from '@/lib/social';
import { supabase } from '@/lib/supabase';

type Evaluation = {
  id: number;
  measured_at: string;
  weight_kg: number | null;
  body_fat_pct: number | null;
  skeletal_muscle_kg: number | null;
  muscle_mass_kg: number | null;
  muscle_mass_pct: number | null;
  protein_kg: number | null;
  water_pct: number | null;
  bmi: number | null;
  visceral_fat_grade: number | null;
  bmr_kcal: number | null;
  body_age: number | null;
  whr: number | null;
  report_image_path: string | null;
};

const FIELDS: { key: keyof Evaluation; label: string }[] = [
  { key: 'weight_kg', label: 'Peso (kg)' },
  { key: 'body_fat_pct', label: 'Grasa corporal (%)' },
  { key: 'muscle_mass_kg', label: 'Masa muscular (kg)' },
  { key: 'muscle_mass_pct', label: 'Masa muscular (%)' },
  { key: 'skeletal_muscle_kg', label: 'Músculo esquelético (kg)' },
  { key: 'protein_kg', label: 'Proteína (kg)' },
  { key: 'water_pct', label: 'Agua corporal (%)' },
  { key: 'bmi', label: 'IMC' },
  { key: 'visceral_fat_grade', label: 'Grasa visceral' },
  { key: 'bmr_kcal', label: 'Tasa metabólica basal (kcal)' },
  { key: 'body_age', label: 'Edad corporal' },
  { key: 'whr', label: 'WHR' },
];

function todayISODate() {
  return new Date().toISOString().slice(0, 10);
}

function formatDelta(delta: number, goodWhenNegative: boolean) {
  const rounded = Math.round(delta * 10) / 10;
  const isGood = goodWhenNegative ? rounded < 0 : rounded > 0;
  const sign = rounded > 0 ? '+' : '';
  return { text: `${sign}${rounded}`, isGood: rounded === 0 ? null : isGood };
}

export default function EvaluationsScreen() {
  const { session } = useAuth();
  const theme = useTheme();
  const userId = session!.user.id;

  const [loading, setLoading] = useState(true);
  const [evaluations, setEvaluations] = useState<Evaluation[]>([]);
  const [photoUrls, setPhotoUrls] = useState<Record<number, string>>({});
  const [showForm, setShowForm] = useState(false);
  const [measuredAt, setMeasuredAt] = useState(todayISODate());
  const [draft, setDraft] = useState<Record<string, string>>({});
  const [reportImagePath, setReportImagePath] = useState<string | null>(null);
  const [uploadingPhoto, setUploadingPhoto] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    const { data, error } = await supabase
      .from('body_evaluations')
      .select('*')
      .eq('user_id', userId)
      .order('measured_at', { ascending: false });
    if (error) setError(error.message);
    const rows = data ?? [];
    setEvaluations(rows);

    const withPhotos = rows.filter((r) => r.report_image_path);
    const urls = await Promise.all(withPhotos.map((r) => getSignedReportUrl(r.report_image_path!)));
    setPhotoUrls(
      Object.fromEntries(withPhotos.map((r, i) => [r.id, urls[i]]).filter(([, url]) => url) as [number, string][])
    );

    setLoading(false);
  }, [userId]);

  useEffect(() => {
    load();
  }, [load]);

  async function takeReportPhoto() {
    const permission = await ImagePicker.requestCameraPermissionsAsync();
    if (!permission.granted) return setError('Necesitamos permiso de cámara para tomar la foto.');

    const result = await ImagePicker.launchCameraAsync({ quality: 0.7 });
    if (result.canceled) return;
    await uploadPhoto(result.assets[0].uri);
  }

  async function pickReportPhoto() {
    const permission = await ImagePicker.requestMediaLibraryPermissionsAsync();
    if (!permission.granted) return setError('Necesitamos permiso para acceder a tus fotos.');

    const result = await ImagePicker.launchImageLibraryAsync({ quality: 0.7 });
    if (result.canceled) return;
    await uploadPhoto(result.assets[0].uri);
  }

  async function uploadPhoto(uri: string) {
    setUploadingPhoto(true);
    setError(null);
    try {
      setReportImagePath(await uploadEvaluationReport(userId, uri));
    } catch (e) {
      setError(errorMessage(e));
    }
    setUploadingPhoto(false);
  }

  async function saveEvaluation() {
    setSaving(true);
    setError(null);

    const payload: Record<string, unknown> = {
      user_id: userId,
      measured_at: measuredAt,
      source: 'fitdays',
      report_image_path: reportImagePath,
    };
    for (const field of FIELDS) {
      const raw = draft[field.key];
      if (raw && raw.trim() !== '') payload[field.key] = parseFloat(raw);
    }

    const { data, error } = await supabase.from('body_evaluations').insert(payload).select().single();
    if (error) {
      setSaving(false);
      return setError(error.message);
    }
    await awardEvaluationPoints(userId, data.id);
    setSaving(false);

    setDraft({});
    setReportImagePath(null);
    setMeasuredAt(todayISODate());
    setShowForm(false);
    await load();
  }

  if (loading) {
    return (
      <ScreenBackground style={styles.centered}>
        <ActivityIndicator />
      </ScreenBackground>
    );
  }

  return (
    <ScreenBackground style={styles.container}>
      <SafeAreaView style={styles.safeArea}>
        <ScrollView contentContainerStyle={styles.scrollContent}>
          <View style={styles.headerRow}>
            <ThemedText type="title" style={styles.title}>
              Evaluaciones
            </ThemedText>
            <Pressable onPress={() => setShowForm((v) => !v)}>
              <ThemedText type="link" themeColor="tint">
                {showForm ? 'Cancelar' : '+ Nueva'}
              </ThemedText>
            </Pressable>
          </View>

          {error && (
            <ThemedText type="small" themeColor="error">
              {error}
            </ThemedText>
          )}

          {showForm && (
            <Card>
              <ThemedText type="small" themeColor="textSecondary">
                Fecha (YYYY-MM-DD)
              </ThemedText>
              <TextInput
                value={measuredAt}
                onChangeText={setMeasuredAt}
                style={[styles.input, { color: theme.text, borderColor: theme.text + '30' }]}
              />

              <ThemedText type="small" themeColor="textSecondary">
                Foto del reporte (el .jpeg que mandan por WhatsApp)
              </ThemedText>
              {reportImagePath && <ThemedText type="small">✅ Foto adjuntada</ThemedText>}
              <View style={styles.photoRow}>
                <Button
                  label="📷 Tomar foto"
                  onPress={takeReportPhoto}
                  disabled={uploadingPhoto}
                  style={styles.smallButton}
                />
                <Pressable onPress={pickReportPhoto} disabled={uploadingPhoto}>
                  <ThemedText type="link" themeColor="tint">
                    Elegir de galería
                  </ThemedText>
                </Pressable>
              </View>
              {uploadingPhoto && <ActivityIndicator />}

              {FIELDS.map((field) => (
                <View key={field.key}>
                  <ThemedText type="small" themeColor="textSecondary">
                    {field.label}
                  </ThemedText>
                  <TextInput
                    keyboardType="decimal-pad"
                    value={draft[field.key] ?? ''}
                    onChangeText={(text) => setDraft((prev) => ({ ...prev, [field.key]: text }))}
                    style={[styles.input, { color: theme.text, borderColor: theme.text + '30' }]}
                  />
                </View>
              ))}

              <Button label="Guardar evaluación" loading={saving} onPress={saveEvaluation} style={styles.button} />
            </Card>
          )}

          {evaluations.length === 0 && !showForm && (
            <ThemedText type="small" themeColor="textSecondary">
              Todavía no tienes evaluaciones registradas. Agrega la primera con el pesaje de este
              mes.
            </ThemedText>
          )}

          {evaluations.map((evaluation, index) => {
            const previous = evaluations[index + 1];
            const fatDelta =
              previous?.body_fat_pct != null && evaluation.body_fat_pct != null
                ? formatDelta(evaluation.body_fat_pct - previous.body_fat_pct, true)
                : null;
            const muscleDelta =
              previous?.muscle_mass_pct != null && evaluation.muscle_mass_pct != null
                ? formatDelta(evaluation.muscle_mass_pct - previous.muscle_mass_pct, false)
                : null;

            return (
              <Card key={evaluation.id}>
                <View style={styles.evaluationRow}>
                  {photoUrls[evaluation.id] && (
                    <Image source={{ uri: photoUrls[evaluation.id] }} style={styles.thumb} />
                  )}
                  <View style={{ flex: 1, gap: Spacing.half }}>
                    <ThemedText type="smallBold">{evaluation.measured_at.slice(0, 10)}</ThemedText>
                    <ThemedText type="small">
                      Peso: {evaluation.weight_kg ?? '–'}kg · IMC: {evaluation.bmi ?? '–'}
                    </ThemedText>
                    <ThemedText type="small">
                      Grasa: {evaluation.body_fat_pct ?? '–'}%{' '}
                      {fatDelta && (
                        <ThemedText
                          type="small"
                          themeColor={
                            fatDelta.isGood === null ? 'textSecondary' : fatDelta.isGood ? 'success' : 'error'
                          }>
                          ({fatDelta.text})
                        </ThemedText>
                      )}
                    </ThemedText>
                    <ThemedText type="small">
                      Músculo: {evaluation.muscle_mass_pct ?? '–'}%{' '}
                      {muscleDelta && (
                        <ThemedText
                          type="small"
                          themeColor={
                            muscleDelta.isGood === null ? 'textSecondary' : muscleDelta.isGood ? 'success' : 'error'
                          }>
                          ({muscleDelta.text})
                        </ThemedText>
                      )}
                    </ThemedText>
                  </View>
                </View>
              </Card>
            );
          })}
        </ScrollView>
      </SafeAreaView>
    </ScreenBackground>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  centered: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  safeArea: { flex: 1 },
  scrollContent: {
    paddingHorizontal: Spacing.four,
    paddingTop: Spacing.four + TopTabInset,
    paddingBottom: Spacing.six,
    gap: Spacing.three,
  },
  headerRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  title: { fontSize: 32, lineHeight: 40 },
  input: {
    borderWidth: 1,
    borderRadius: Spacing.two,
    paddingHorizontal: Spacing.three,
    paddingVertical: Spacing.two,
    fontSize: 16,
    marginBottom: Spacing.two,
  },
  button: { marginTop: Spacing.two },
  photoRow: { flexDirection: 'row', gap: Spacing.three, alignItems: 'center', marginBottom: Spacing.two },
  smallButton: {
    paddingHorizontal: Spacing.three,
    paddingVertical: Spacing.two,
  },
  evaluationRow: {
    flexDirection: 'row',
    gap: Spacing.two,
    alignItems: 'flex-start',
  },
  thumb: {
    width: 60,
    height: 84,
    borderRadius: Spacing.two,
  },
});
