import { useRef, useCallback, useMemo, memo, useEffect, useState } from "react";
import { Dimensions, StyleSheet, ScrollView } from "react-native";
import { YStack, XStack, View } from "tamagui";
import {
  useCalendarStore,
  useStatisticsStore,
  useTeamAttendanceStore,
  useAppStore,
} from "@/stores";
//考勤统计、考勤详情数据映射配置、日历圆点特殊处理
import {
  ATTENDANCE_DATA_DEF,
  LEAVE_DOTS_DEFS,
} from "@/constants/attendanceStatus";
//引入考勤模块工具函数
import { buildStatisticsItems } from '@/utils/business/attendanceUtils';
//国际化
import { useTranslation } from "@/node_modules/react-i18next";

// 日历组件
import { CalendarList } from "react-native-calendars";
//加载中组件
import LoadingSpinner from "@/components/ui/LoadingSpinner";
// 审批记录组件
import ApplyInfoList from "@/components/attendance/applyInfoList";
//打卡记录组件
import AttendanceRecords from "@/components/attendance/attendanceRecords";
//最后更新时间组件
import LastUpdateView from "./lastUpdateView";
// 考勤统计组件
import AttendanceStatics from "./attendanceStatics";

// 引入屏幕适配工具
import { wp, sp } from '@/utils/ui/screenUtils';
import dayjs from 'dayjs';

// 固定日历宽度为常量，避免每次计算
const CALENDAR_WIDTH = Dimensions.get("window").width - 32;
const WEEK_ROW_HEIGHT = 50;
const DAY_NAMES_HEIGHT = 32;

const dayAttendanceStat = memo(() => {
  //获取主色
  const primaryColor = useAppStore((s) => s.primary);

  // 从全局 store 获取：可见年月、选中日期与动作
  // 日视图仅订阅“自然月”的可见年月（与周/月解耦合）
  const visibleYM = useCalendarStore((s) => s.dayVisibleYM);
  const selectedDate = useCalendarStore((s) => s.selectedDate);
  const dayJumpVersion = useCalendarStore((s) => s.dayJumpVersion);
  const setSelectedDate = useCalendarStore((s) => s.setSelectedDate);
  const setDayVisibleYM = useCalendarStore((s) => s.setDayVisibleYM);

  // 读取接口加载状态与更新时间
  const loadingCount = useStatisticsStore((s) => s.loadingCount);
  const lastUpdateTime = useStatisticsStore((s) => s.lastUpdateTime);
  const isLoading = (loadingCount || 0) > 0;

  // 计算可见月份键与选中日期键
  const visibleKey = useMemo(() => {
    const m = String(visibleYM.month).padStart(2, "0");
    return `${visibleYM.year}-${m}`;
  }, [visibleYM.year, visibleYM.month]);
  const selectedKey = useMemo(
    () => (selectedDate ? dayjs(selectedDate).format("YYYY-MM") : ""),
    [selectedDate]
  );

  // 当前月份 key（YYYY-MM）：仅用于“标记过滤”，不再依赖 providerDate
  const currentMonthKey = useMemo(() => visibleKey, [visibleKey]);

  //标记样式规则: dots 对象只创建一次（引用稳定）
  const dots = useMemo(
    () => ({
      //全天考勤正常
      normal: { key: "normal", color: "#1F80F0", selectedColor: "#1F80F0" },
      //当天存在异常：迟到、外勤迟到、早退、外勤早退、缺卡
      abnormal: { key: "abnormal", color: "#F09F1F", selectedColor: "#F09F1F" },
      //当天提交过：请假、加班、外勤、补卡、出差、外出、调休
      leave: { key: "leave", color: "#CF3050", selectedColor: "#CF3050" },
    }),
    []
  );

  // 日历 ref
  const calendarRef = useRef(null);
  // 一次性设置初始月份（仅首次挂载生效，避免出现“今天所在月”的中间态）
  const initialMonthRef = useRef(null);
  if (initialMonthRef.current == null) {
    const m = String(visibleYM.month).padStart(2, "0");
    initialMonthRef.current = `${visibleYM.year}-${m}-01`;
  }
  // 一次性“本日”跳转：当版本号变化时，滚动到当前可见月份
  useEffect(() => {
    if (!calendarRef.current) return;
    const m = String(visibleYM.month).padStart(2, "0");
    calendarRef.current.scrollToMonth(`${visibleYM.year}-${m}-01`);
  }, [dayJumpVersion]);

  //从考勤统计store获取统计详情数据
  const statisticsDetail = useStatisticsStore((s) => s.statisticsDetail);
  //国际化
  const { t, i18n } = useTranslation("attendance");
  // 映射国际化文案，仅在语言变化时重算
  const statsConfig = useMemo(
    () =>
      ATTENDANCE_DATA_DEF.map((d) => ({
        ...d,
        label: t(d.labelKey),
        countUnit: t(d.unitKey),
      })),
    // 依赖语言变化
    [i18n.language]
  );
  // 使用useMemo缓存统计项数据，避免重复计算
  const statisticsItems = useMemo(
    () => buildStatisticsItems(statisticsDetail, statsConfig),
    [statisticsDetail, statsConfig]
  );

  //根据考勤规则构建该月日历点数组，并建立"日期 → 打卡记录列表"的索引
  const { marksForMonth, recordsByDate } = useMemo(() => {
    const marks = {};
    const recordsMap = new Map();

    //后端已处理所有场景，因此这里直接使用接口返回结果即可
    const workDayData =
      statisticsItems.filter(
        (item) =>
          item.key === "workDay" &&
          Array.isArray(item.items) &&
          item.items.length > 0
      ) || [];
    if (workDayData.length > 0) {
      workDayData.forEach((data) => {
        const workDay = data?.items || [];
        if (workDay.length > 0) {
          workDay.forEach((item) => {
            const d = item.workDate;
            if (!d) return;

            // 构建日历标记
            //黄蓝点不共存
            marks[d] = item.abnormal
              ? { dots: [dots.abnormal] }
              : { dots: [dots.normal] };
            if (item.applyTypes?.length > 0 || item.actionTypes?.length > 0) {
              //增加红点，且顺序在后面
              //目前仅包括：请假、加班、外勤、补卡、出差、外出、调休（审批提交场景）和 外勤（打卡场景），可以同时处理
              const hasLeave = LEAVE_DOTS_DEFS.some(
                (dot) =>
                  item.applyTypes?.includes(dot.key) ||
                  item.actionTypes?.includes(dot.key)
              );
              if (hasLeave) {
                marks[d].dots.push(dots.leave);
              }
            }

            // 构建打卡记录索引
            if (Array.isArray(item?.records) && item.records.length) {
              const existed = recordsMap.get(d);
              if (existed) existed.push(...item.records);
              else recordsMap.set(d, [...item.records]);
            } else if (!recordsMap.has(d)) {
              // 保证该日期存在索引键，即使当天没有记录
              recordsMap.set(d, []);
            }
          });
        }
      });
    }

    return { marksForMonth: marks, recordsByDate: recordsMap };
  }, [statisticsItems, dots]);

  // 提取选中日期的打卡记录（默认今天）
  const attendanceRecords = useMemo(() => {
    const effectiveDate = selectedDate || dayjs().format("YYYY-MM-DD");
    return recordsByDate.get(effectiveDate) || [];
  }, [recordsByDate, selectedDate]);

  //自定义主题
  const customTheme = useMemo(
    () => ({
      calendarBackground: "#ffffff",
      "stylesheet.calendar.header": {
        dayHeader: {
          color: "#191919",
          fontSize: sp(14),
          fontFamily: "Bold",
          marginBottom: wp(16),
        },
      },
      "stylesheet.day.basic": {
        selected: {
          borderRadius: wp(6),
          // 中和默认选中态：与背景一致
          backgroundColor: "#ffffff",
        },
        selectedText: {
          // 中和默认选中文本色：与普通文本一致
          color: "#191919",
        },
        todayText: {
          color: primaryColor,
        },
      },
      "stylesheet.dot": {
        dot: {
          width: wp(4),
          height: wp(4),
          marginTop: wp(10),
          marginHorizontal: wp(1),
          borderRadius: wp(2),
          opacity: 0,
        },
      },
      "stylesheet.calendar-list.main": {
        placeholderText: {
          color: "transparent",
        },
      },
    }),
    [primaryColor]
  );

  //自定义头部
  const renderHeader = useCallback(() => {
    return null;
  }, []);
  //日期选择回调：仅更新全局 selectedDate（store 内部已做同值 no-op）
  const onDayPress = useCallback(
    (day) => {
      if (isLoading) return;
      const next = day?.dateString ?? "";
      setSelectedDate(next);
    },
    [setSelectedDate, isLoading]
  );

  //月份变化回调
  const onMonthChange = useCallback(
    (date) => {
      const d = dayjs(date.dateString);
      // 仅在年月发生变化时才写入，避免冗余更新
      if (visibleYM.year !== d.year() || visibleYM.month !== d.month() + 1) {
        setDayVisibleYM({ year: d.year(), month: d.month() + 1 });
      }
      // 同步根据该月的周数更新容器高度（分页完成后触发，避免滚动过程抖动）
      applyContainerHeightForYM(d.year(), d.month() + 1);
    },
    [setDayVisibleYM, visibleYM.year, visibleYM.month]
  );

  // 标记数据：仅包含“当前月的标记 + 选中态”，体量稳定；引用仅在当前月或选中变化时改变
  const markedDates = useMemo(() => {
    // 直接基于统计数据构建并过滤当前月，避免首次装载阶段的额外 setState 触发
    const allMarks = marksForMonth;
    const monthMarks = {};
    Object.keys(allMarks).forEach((key) => {
      if (key.startsWith(`${currentMonthKey}-`)) {
        monthMarks[key] = allMarks[key];
      }
    });

    let result = { ...monthMarks };
    // 仅当选中日期属于当前可见月时，合并选中态
    if (selectedDate && selectedKey === currentMonthKey) {
      const prev = result[selectedDate];
      result[selectedDate] = {
        ...(prev ?? {}),
        selected: true,
        selectedColor: primaryColor,
        selectedTextColor: "#ffffff",
        disableTouchEvent: true,
      };
    }
    return result;
  }, [currentMonthKey, selectedDate, selectedKey, primaryColor, marksForMonth]);

  // 动态容器高度：根据当前可见月的行数（不使用 showSixWeeks，按实际行数计算）
  const [containerHeight, setContainerHeight] = useState(
    DAY_NAMES_HEIGHT + 5 * WEEK_ROW_HEIGHT
  );
  const FIRST_DAY_OF_WEEK = 1;

  const computeWeekCount = useCallback((year, month) => {
    const firstOfMonth = dayjs(`${year}-${String(month).padStart(2, "0")}-01`);
    const firstDayIndex = (firstOfMonth.day() - FIRST_DAY_OF_WEEK + 7) % 7;
    const daysInMonth = firstOfMonth.daysInMonth();
    const rows = Math.ceil((firstDayIndex + daysInMonth) / 7);
    return rows;
  }, []);

  const applyContainerHeightForYM = useCallback(
    (year, month) => {
      const rows = computeWeekCount(year, month);
      const target = DAY_NAMES_HEIGHT + rows * WEEK_ROW_HEIGHT;
      setContainerHeight((prev) => (prev === target ? prev : target));
    },
    [computeWeekCount]
  );

  // 首次挂载：根据初始 current 月份设置一次容器高度
  useEffect(() => {
    const d = dayjs(initialMonthRef.current);
    applyContainerHeightForYM(d.year(), d.month() + 1);
  }, [applyContainerHeightForYM]);

  return (
    <YStack position="relative" flex={1}>
      <ScrollView
        flex={1}
        contentContainerStyle={styles.contentContainer}
        // 隐藏滚动条
        showsVerticalScrollIndicator={false}
        // 解决滚动冲突
        nestedScrollEnabled={true}
      >
        <YStack height={containerHeight} overflow="hidden">
          <CalendarList
            ref={calendarRef}
            // 首次可见月：稳定的初始值，仅在首次挂载生效
            current={initialMonthRef.current}
            //是否开启水平布局
            horizontal={true}
            //是否开启分页滚动
            pagingEnabled={true}
            //标记样式
            markingType={"multi-dot"}
            //日历宽度
            calendarWidth={CALENDAR_WIDTH}
            //是否隐藏额外天数
            hideExtraDays={false}
            //第一天从周几开始
            firstDay={1}
            //自定义头部
            renderHeader={renderHeader}
            //是否隐藏星期
            hideDayNames={false}
            //是否隐藏左右箭头
            hideArrows={true}
            //是否显示加载指示器
            displayLoadingIndicator={false}
            //日期选择回调
            onDayPress={onDayPress}
            //月份变化回调
            onMonthChange={onMonthChange}
            //自定义主题
            theme={customTheme}
            //标记数据
            markedDates={markedDates}
            //性能优化
            // 保留“伪无限”手感（按需调整范围），结合按月懒加载标记，避免大对象频繁更新
            // 使用大范围以覆盖跨多年场景，避免边界卡死
            pastScrollRange={240}
            futureScrollRange={36}
          />
        </YStack>
        {isLoading && (
          <YStack pointerEvents="none" style={styles.overlay}>
            <LoadingSpinner
              size={wp(20)}
              color={primaryColor}
              animating={isLoading}
            />
          </YStack>
        )}
        <View style={styles.separatorLine} />
        {attendanceRecords.length > 0 && (
          <YStack>
            <ApplyInfoList records={attendanceRecords} />
            <AttendanceRecords records={attendanceRecords} />
          </YStack>
        )}
        <LastUpdateView />
        <AttendanceStatics records={attendanceRecords} />
      </ScrollView>
    </YStack>
  );
});

const styles = StyleSheet.create({
  overlay: {
    position: "absolute",
    left: 0,
    right: 0,
    top: 0,
    bottom: 0,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "rgba(255,255,255,0.6)",
    zIndex: 100,
  },
  contentContainer: {
    paddingBottom: wp(12),
  },
  updateTextContainer: {
    alignItems: "center",
    justifyContent: "center",
  },
  updateText: {
    fontSize: sp(10),
    lineHeight: wp(14),
    color: "#bababa",
    marginTop: wp(6),
  },
  separatorLine: {
    height: wp(1),
    marginHorizontal: wp(8),
    marginTop: wp(10),
    backgroundColor: "#F8F8F8",
  },
});

export default dayAttendanceStat;
