import {
  ensureHealthPermissions,
  fetchTimeInDaylight,
  fetchTimeInDaylightHistory,
  SunlightHistoryPoint
} from '@/utils/health';
import { HealthKitUtils } from '@/utils/healthKit';
import { Ionicons } from '@expo/vector-icons';
import { useIsFocused } from '@react-navigation/native';
import dayjs from 'dayjs';
import { LinearGradient } from 'expo-linear-gradient';
import { BlurView } from 'expo-blur';
import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
  Dimensions,
  Modal,
  Platform,
  Pressable,
  StyleSheet,
  Text,
  View
} from 'react-native';
import Svg, {
  Defs,
  LinearGradient as SvgLinearGradient,
  Line,
  Rect,
  Stop,
  Text as SvgText
} from 'react-native-svg';
import HealthDataCard from './HealthDataCard';

interface SunlightCardProps {
  style?: object;
  selectedDate?: Date;
}

const screenWidth = Dimensions.get('window').width;
const INITIAL_CHART_WIDTH = screenWidth - 32;
const CHART_HEIGHT = 190;
const CHART_RIGHT_PADDING = 12;
const AXIS_COLUMN_WIDTH = 36;
const CHART_INNER_PADDING = 4;
const AXIS_LABEL_WIDTH = 48;
const Y_TICK_COUNT = 4;
const BAR_GAP = 6;
const MIN_BAR_HEIGHT = 4;

const SunlightCard: React.FC<SunlightCardProps> = ({
  style,
  selectedDate
}) => {
  const { t, i18n } = useTranslation();
  const locale = i18n.language;
  const isFocused = useIsFocused();
  const [sunlightMinutes, setSunlightMinutes] = useState<number | null>(null);
  const [comparisonText, setComparisonText] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const loadingRef = useRef(false);
  const [historyVisible, setHistoryVisible] = useState(false);
  const [historyLoading, setHistoryLoading] = useState(false);
  const [history, setHistory] = useState<SunlightHistoryPoint[]>([]);
  const historyLoadingRef = useRef(false);
  const [chartWidth, setChartWidth] = useState(INITIAL_CHART_WIDTH);

  const formatCompareDate = (date: Date) => {
    if (locale?.startsWith('zh')) {
      return dayjs(date).format('M月D日');
    }
    return dayjs(date).format('MMM D');
  };

  useEffect(() => {
    const loadSunlightData = async () => {
      const dateToUse = selectedDate || new Date();

      if (!isFocused) return;
      if (!HealthKitUtils.isAvailable()) {
        setSunlightMinutes(null);
        setComparisonText(null);
        return;
      }

      if (loadingRef.current) return;

      try {
        loadingRef.current = true;
        setLoading(true);
        setComparisonText(null);

        const hasPermission = await ensureHealthPermissions();
        if (!hasPermission) {
          setSunlightMinutes(null);
          setComparisonText(null);
          setLoading(false);
          return;
        }

        const options = {
          startDate: dayjs(dateToUse).startOf('day').toDate().toISOString(),
          endDate: dayjs(dateToUse).endOf('day').toDate().toISOString()
        };

        const totalMinutes = await fetchTimeInDaylight(options);
        setSunlightMinutes(totalMinutes);
        setLoading(false);

        if (totalMinutes !== null && totalMinutes !== undefined) {
          try {
            let previousMinutes: number | null = null;
            let previousDate: Date | null = null;

            for (let i = 1; i <= 30; i += 1) {
              const targetDate = dayjs(dateToUse).subtract(i, 'day');
              const previousOptions = {
                startDate: targetDate.startOf('day').toDate().toISOString(),
                endDate: targetDate.endOf('day').toDate().toISOString()
              };
              const candidateMinutes = await fetchTimeInDaylight(previousOptions);

              if (candidateMinutes !== null && candidateMinutes !== undefined && candidateMinutes > 0) {
                previousMinutes = candidateMinutes;
                previousDate = targetDate.toDate();
                break;
              }
            }

            if (previousMinutes !== null && previousDate) {
              const diff = Math.round(totalMinutes - previousMinutes);
              const dateLabel = formatCompareDate(previousDate);
              if (diff > 0) {
                setComparisonText(t('statistics.components.sunlight.compareIncrease', { date: dateLabel, diff }));
              } else if (diff < 0) {
                setComparisonText(t('statistics.components.sunlight.compareDecrease', { date: dateLabel, diff: Math.abs(diff) }));
              } else {
                setComparisonText(t('statistics.components.sunlight.compareSame', { date: dateLabel }));
              }
            } else {
              setComparisonText(t('statistics.components.sunlight.compareNone'));
            }
          } catch (error) {
            console.error('SunlightCard: Failed to compare time in daylight:', error);
            setComparisonText(t('statistics.components.sunlight.compareNone'));
          }
        } else {
          setComparisonText(null);
        }
      } catch (error) {
        console.error('SunlightCard: Failed to get time in daylight:', error);
        setSunlightMinutes(null);
        setComparisonText(null);
        setLoading(false);
      } finally {
        loadingRef.current = false;
      }
    };

    loadSunlightData();
  }, [isFocused, selectedDate, t, locale]);

  useEffect(() => {
    if (!historyVisible || !isFocused) return;

    const loadHistory = async () => {
      if (historyLoadingRef.current) return;
      if (!HealthKitUtils.isAvailable()) {
        setHistory([]);
        return;
      }

      try {
        historyLoadingRef.current = true;
        setHistoryLoading(true);

        const hasPermission = await ensureHealthPermissions();
        if (!hasPermission) {
          setHistory([]);
          return;
        }

        const end = dayjs(selectedDate || new Date()).endOf('day');
        const start = end.subtract(29, 'day').startOf('day');
        const options = {
          startDate: start.toDate().toISOString(),
          endDate: end.toDate().toISOString()
        };

        const historyData = await fetchTimeInDaylightHistory(options);
        const sorted = historyData
          .filter((item) => item && item.date)
          .sort((a, b) => dayjs(a.date).valueOf() - dayjs(b.date).valueOf());

        setHistory(sorted);
      } catch (error) {
        console.error('SunlightCard: Failed to get time in daylight history:', error);
        setHistory([]);
      } finally {
        historyLoadingRef.current = false;
        setHistoryLoading(false);
      }
    };

    loadHistory();
  }, [historyVisible, selectedDate, isFocused]);

  const displayValue = loading
    ? '--'
    : (sunlightMinutes !== null && sunlightMinutes !== undefined
      ? Math.max(0, Math.round(sunlightMinutes)).toString()
      : '--');

  const openHistory = () => setHistoryVisible(true);
  const closeHistory = () => setHistoryVisible(false);

  const maxValue = history.length ? Math.max(...history.map((item) => item.value), 10) : 10;
  const averageValue = history.length
    ? history.reduce((sum, item) => sum + item.value, 0) / history.length
    : null;
  const latestValue = history.length ? history[history.length - 1].value : null;
  const barCount = history.length || 1;
  const chartInnerWidth = Math.max(0, chartWidth - 24);
  const chartAreaWidth = Math.max(
    0,
    chartInnerWidth - AXIS_COLUMN_WIDTH - CHART_RIGHT_PADDING
  );
  const barWidth = Math.max(
    6,
    (chartAreaWidth - CHART_INNER_PADDING * 2 - BAR_GAP * (barCount - 1)) / barCount
  );

  const dateLabels = history.length
    ? [
      history[0],
      history[Math.floor(history.length / 2)],
      history[history.length - 1]
    ].filter(Boolean)
    : [];

  return (
    <>
      <HealthDataCard
        title={t('statistics.components.sunlight.title')}
        value={displayValue}
        unit={t('statistics.components.sunlight.unit')}
        style={style}
        icon={<Ionicons name="sunny-outline" size={16} color="#F59E0B" />}
        subtitle={loading ? undefined : comparisonText ?? undefined}
        onPress={openHistory}
      />

      <Modal
        visible={historyVisible}
        animationType="slide"
        presentationStyle={Platform.OS === 'ios' ? 'pageSheet' : 'fullScreen'}
        onRequestClose={closeHistory}
      >
        <View style={styles.modalSafeArea}>
          <LinearGradient
            colors={['#FFF7E8', '#FFFFFF']}
            start={{ x: 0, y: 0 }}
            end={{ x: 0, y: 1 }}
            style={StyleSheet.absoluteFill}
          />
          <View style={styles.modalContainer}>
            <View style={styles.modalHeader}>
              <View>
                <Text style={styles.modalTitle}>{t('statistics.components.sunlight.title')}</Text>
                <Text style={styles.modalSubtitle}>{t('statistics.components.sunlight.last30Days')}</Text>
              </View>
              <Pressable style={styles.closeButton} onPress={closeHistory} hitSlop={10}>
                <BlurView intensity={24} tint="light" style={StyleSheet.absoluteFill} />
                <View style={styles.closeButtonInner}>
                  <Ionicons name="close" size={18} color="#111827" />
                </View>
              </Pressable>
            </View>

            {historyLoading ? (
              <Text style={styles.hintText}>{t('statistics.components.sunlight.syncing')}</Text>
            ) : null}

            {history.length === 0 ? (
              <View style={styles.emptyState}>
                <Text style={styles.emptyText}>{t('statistics.components.sunlight.noData')}</Text>
              </View>
            ) : (
              <View
                style={styles.chartCard}
                onLayout={(event) => {
                  const nextWidth = event.nativeEvent.layout.width;
                  if (nextWidth > 120 && Math.abs(nextWidth - chartWidth) > 2) {
                    setChartWidth(nextWidth);
                  }
                }}
              >
                <View style={styles.chartHeaderRow}>
                  <Text style={styles.axisUnit}>{t('statistics.components.sunlight.unit')}</Text>
                </View>
                <View style={styles.chartContentRow}>
                  <View style={styles.axisColumn}>
                    {Array.from({ length: Y_TICK_COUNT + 1 }).map((_, index) => {
                      const value = (maxValue / Y_TICK_COUNT) * (Y_TICK_COUNT - index);
                      const y = (CHART_HEIGHT / Y_TICK_COUNT) * index;
                      return (
                        <Text key={`tick-${index}`} style={[styles.axisTick, { top: Math.max(0, y - 6) }]}>
                          {Math.round(value)}
                        </Text>
                      );
                    })}
                  </View>
                  <Svg width={chartAreaWidth} height={CHART_HEIGHT + 10}>
                  <Defs>
                    <SvgLinearGradient id="sunBar" x1="0%" y1="0%" x2="0%" y2="100%">
                      <Stop offset="0%" stopColor="#F59E0B" stopOpacity="0.95" />
                      <Stop offset="100%" stopColor="#FDE68A" stopOpacity="0.8" />
                    </SvgLinearGradient>
                  </Defs>

                  {Array.from({ length: Y_TICK_COUNT + 1 }).map((_, index) => {
                    const value = (maxValue / Y_TICK_COUNT) * index;
                    const y = CHART_HEIGHT - (value / maxValue) * CHART_HEIGHT;
                    return (
                      <React.Fragment key={`tick-${index}`}>
                        <Line
                          x1={0}
                          y1={y}
                          x2={chartAreaWidth}
                          y2={y}
                          stroke="#FEF3C7"
                          strokeWidth={1}
                        />
                      </React.Fragment>
                    );
                  })}

                  {history.map((item, index) => {
                    const value = item.value;
                    const barHeight = Math.max((value / maxValue) * CHART_HEIGHT, MIN_BAR_HEIGHT);
                    const x = CHART_INNER_PADDING + index * (barWidth + BAR_GAP);
                    const y = CHART_HEIGHT - barHeight;
                    return (
                      <Rect
                        key={item.date}
                        x={x}
                        y={y}
                        width={barWidth}
                        height={barHeight}
                        rx={barWidth > 8 ? 6 : 4}
                        fill="url(#sunBar)"
                      />
                    );
                  })}
                  </Svg>
                </View>
                <View style={[styles.labelRow, { width: chartAreaWidth }]}>
                  {dateLabels.map((item) => {
                    const index = history.findIndex((point) => point.date === item.date);
                    const x = CHART_INNER_PADDING + index * (barWidth + BAR_GAP) + barWidth / 2;
                    const label = dayjs(item.date).format(locale?.startsWith('zh') ? 'M.D' : 'MMM D');
                    const maxLeft = Math.max(0, chartAreaWidth - AXIS_LABEL_WIDTH);
                    const clampedLeft = Math.min(
                      Math.max(x - AXIS_LABEL_WIDTH / 2, 0),
                      maxLeft
                    );
                    return (
                      <Text key={item.date} style={[styles.axisLabel, { left: clampedLeft, width: AXIS_LABEL_WIDTH }]}>
                        {label}
                      </Text>
                    );
                  })}
                </View>
              </View>
            )}

            <View style={styles.metricsRow}>
              <View style={styles.metric}>
                <Text style={styles.metricLabel}>{t('statistics.components.sunlight.average')}</Text>
                <Text style={styles.metricValue}>
                  {averageValue !== null ? Math.round(averageValue) : '--'}
                  <Text style={styles.metricUnit}> {t('statistics.components.sunlight.unit')}</Text>
                </Text>
              </View>
              <View style={styles.metric}>
                <Text style={styles.metricLabel}>{t('statistics.components.sunlight.latest')}</Text>
                <Text style={styles.metricValue}>
                  {latestValue !== null ? Math.round(latestValue) : '--'}
                  <Text style={styles.metricUnit}> {t('statistics.components.sunlight.unit')}</Text>
                </Text>
              </View>
            </View>
          </View>
        </View>
      </Modal>
    </>
  );
};

export default SunlightCard;

const styles = StyleSheet.create({
  modalSafeArea: {
    flex: 1,
    backgroundColor: '#FFFFFF',
    paddingTop: Platform.OS === 'ios' ? 10 : 0
  },
  modalContainer: {
    flex: 1,
    paddingHorizontal: 20,
    paddingTop: 22
  },
  modalHeader: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginBottom: 14
  },
  modalTitle: {
    fontSize: 22,
    fontWeight: '700',
    color: '#1C1C28',
    fontFamily: 'AliBold'
  },
  modalSubtitle: {
    fontSize: 13,
    color: '#6B7280',
    marginTop: 4,
    fontFamily: 'AliRegular'
  },
  closeButton: {
    width: 36,
    height: 36,
    borderRadius: 18,
    backgroundColor: 'rgba(255,255,255,0.42)',
    alignItems: 'center',
    justifyContent: 'center',
    overflow: 'hidden',
    borderWidth: 0.5,
    borderColor: 'rgba(255,255,255,0.6)',
    shadowColor: '#0F172A',
    shadowOpacity: 0.08,
    shadowRadius: 8,
    shadowOffset: { width: 0, height: 4 },
    elevation: 2
  },
  closeButtonInner: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center'
  },
  chartCard: {
    backgroundColor: '#FFFFFF',
    borderRadius: 24,
    paddingVertical: 12,
    paddingHorizontal: 12,
    shadowColor: '#000',
    shadowOpacity: 0.05,
    shadowRadius: 14,
    shadowOffset: { width: 0, height: 12 },
    elevation: 4,
    marginTop: 8,
    marginBottom: 14,
    borderWidth: 1,
    borderColor: '#FEF3C7'
  },
  chartHeaderRow: {
    paddingLeft: AXIS_COLUMN_WIDTH,
    paddingBottom: 6
  },
  axisUnit: {
    fontSize: 10,
    color: '#B45309',
    fontFamily: 'AliRegular'
  },
  chartContentRow: {
    flexDirection: 'row',
    alignItems: 'flex-start'
  },
  axisColumn: {
    width: AXIS_COLUMN_WIDTH,
    height: CHART_HEIGHT,
    position: 'relative',
    justifyContent: 'space-between',
    paddingRight: 6
  },
  axisTick: {
    position: 'absolute',
    right: 6,
    fontSize: 10,
    color: '#B45309',
    fontFamily: 'AliRegular'
  },
  labelRow: {
    marginTop: 4,
    marginLeft: AXIS_COLUMN_WIDTH,
    height: 24,
    justifyContent: 'center'
  },
  axisLabel: {
    position: 'absolute',
    bottom: 0,
    fontSize: 11,
    color: '#9A6B2F',
    fontFamily: 'AliRegular',
    textAlign: 'center',
    width: 48
  },
  metricsRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    gap: 12,
    paddingVertical: 6
  },
  metric: {
    flex: 1,
    padding: 14,
    backgroundColor: 'rgba(255, 247, 237, 0.8)',
    borderRadius: 18,
    borderWidth: 1,
    borderColor: '#FED7AA'
  },
  metricLabel: {
    fontSize: 12,
    color: '#92400E',
    marginBottom: 8,
    fontFamily: 'AliRegular'
  },
  metricValue: {
    fontSize: 20,
    fontWeight: '700',
    color: '#7C2D12',
    fontFamily: 'AliBold'
  },
  metricUnit: {
    fontSize: 12,
    color: '#9A6B2F',
    fontWeight: '500',
    fontFamily: 'AliRegular'
  },
  emptyState: {
    marginTop: 32,
    padding: 20,
    borderRadius: 20,
    backgroundColor: 'rgba(255, 247, 237, 0.9)',
    borderWidth: 1,
    borderColor: '#FED7AA',
    alignItems: 'center'
  },
  emptyText: {
    fontSize: 14,
    color: '#9A3412',
    fontFamily: 'AliRegular'
  },
  hintText: {
    fontSize: 13,
    color: '#9CA3AF',
    fontFamily: 'AliRegular'
  }
});
