import React, { useEffect, useMemo, useRef, useState } from "react";
import {
  ActivityIndicator,
  Alert,
  ScrollView,
  StyleSheet,
  TouchableOpacity,
  View,
  Text as RNText,
} from "react-native";
import { NativeStackScreenProps } from "@react-navigation/native-stack";
import {
  Central,
  ConnectionStatus,
  ScannedPeripheral,
} from "@systemic-games/react-native-bluetooth-le";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { RootStackParamList } from "../App";
import MyHeader from "./component/MyHeader";
import MyStatusbar from "./component/MyStatusbar";
import { useTranslation } from "react-i18next";
import { observeFtmsIndoorBikeData } from "./helper/ftmsIndoorBikeDataBus";

type Props = NativeStackScreenProps<RootStackParamList, "Spindown">;
type Phase = "reach36" | "wait18" | "calibrating" | "completed" | "error";

const powerServiceUuid = "fff1";
const powerWriteUuid = "fff2";
const powerNotifyUuid = "fff3";

const fullUUID = (uuid: string) =>
  uuid.length === 4
    ? `0000${uuid}-0000-1000-8000-00805f9b34fb`
    : uuid;

const Text = ({ children, style, ...props }: any) => {
  return (
    <RNText style={[{ color: "black", fontSize: 16 }, style]} {...props}>
      {children}
    </RNText>
  );
};

export default function SpindownScreen({ route, navigation }: Props) {
  const { peripheral } = route.params;
  const { t } = useTranslation();

  const deviceKey = useMemo(
    () => peripheral.address || peripheral.systemId,
    [peripheral.address, peripheral.systemId]
  );

  const [speedKph, setSpeedKph] = useState<number>(0);
  const [isConnected, setIsConnected] = useState(false);
  const [isFff3Ready, setIsFff3Ready] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [phase, setPhase] = useState<Phase>("reach36");
  const [step1Done, setStep1Done] = useState(false);
  const [step2Done, setStep2Done] = useState(false);
  const [statusText, setStatusText] = useState(
    t("spindown.statusReach36", { speed: 36 })
  );
  const [spindownSeconds, setSpindownSeconds] = useState<number | null>(null);

  const notifySubscribedRef = useRef(false);
  const spindownStartedRef = useRef(false);
  const spindownModeEnabledRef = useRef(false);
  const resolverRef = useRef<((value: Uint8Array) => void) | null>(null);
  const rejecterRef = useRef<((reason?: any) => void) | null>(null);
  const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const mountedRef = useRef(true);
  const hasConnectedOnceRef = useRef(false);
  const hasNavigatedBackRef = useRef(false);
  const skipDisconnectOnLeaveRef = useRef(false);
  const isConnectedRef = useRef(false);
  const isFff3ReadyRef = useRef(false);
  const spindownResultPromiseRef = useRef<Promise<number> | null>(null);
  const DEBUG = false;
  const phaseRef = useRef<Phase>("reach36");
const lastUiUpdateRef = useRef(0);
  
useEffect(() => {
  phaseRef.current = phase;
}, [phase]);

  useEffect(() => {
    isConnectedRef.current = isConnected;
  }, [isConnected]);

  useEffect(() => {
    isFff3ReadyRef.current = isFff3Ready;
  }, [isFff3Ready]);

  // 新增：缓存最近收到的 0x09 消旋结果，避免结果包先到、waiter 后挂导致丢包
  const lastSpindownPacketRef = useRef<Uint8Array | null>(null);

  const bytesToHex = (bytes: Uint8Array) =>
    Array.from(bytes)
      .map((b) => b.toString(16).padStart(2, "0").toUpperCase())
      .join("");

  const clearWaiter = () => {
    resolverRef.current = null;
    rejecterRef.current = null;
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = null;
    }
  };

  const formatSpindownSeconds = (seconds: number) => {
    return seconds.toFixed(2).replace(/\.?0+$/, "");
  };

const subscribeFff3IfNeeded = async () => {
  if (notifySubscribedRef.current) return;

  try {
    await Central.unsubscribeCharacteristic(
      peripheral,
      fullUUID(powerServiceUuid),
      fullUUID(powerNotifyUuid)
    ).catch(() => {});

    await Central.subscribeCharacteristic(
      peripheral,
      fullUUID(powerServiceUuid),
      fullUUID(powerNotifyUuid),
      (notifyEv) => {
        try {
          const raw = notifyEv.value;
          if (!raw) return;

          const bytes = new Uint8Array(raw);

          if (DEBUG) {
            console.log("[BLE] FFF3 =", bytes.length);
          }

          if (bytes.length >= 3 && bytes[0] === 0x09) {
            lastSpindownPacketRef.current = bytes;
          }

          resolverRef.current?.(bytes);
        } catch (err) {
          rejecterRef.current?.(err);
          clearWaiter();
        }
      }
    );

    notifySubscribedRef.current = true;
    isFff3ReadyRef.current = true;
    setIsFff3Ready(true);
  } catch {
    isFff3ReadyRef.current = false;
    setIsFff3Ready(false);
  }
};


  const waitForSpindownTime = (timeout = 5000) => {
    return new Promise<number>((resolve, reject) => {
      clearWaiter();

      // 先吃缓存，防止 0x09 结果包在 runSpindown 前就已经到了
      const cached = lastSpindownPacketRef.current;
      if (cached && cached.length >= 3 && cached[0] === 0x09) {
        console.log("[BLE] use cached spindown packet =", bytesToHex(cached));

        const rawSeconds = cached[1] | (cached[2] << 8);
        lastSpindownPacketRef.current = null;

        if (rawSeconds === 0xffff) {
          reject(new Error(t("spindown.failedRetry")));
          return;
        }

        resolve(rawSeconds / 100);
        return;
      }

      resolverRef.current = (value: Uint8Array) => {
        if (value.length < 3 || value[0] !== 0x09) {
          console.log("[BLE] ignore unrelated FFF3(spindown):", bytesToHex(value));
          return;
        }

        lastSpindownPacketRef.current = null;

        const rawSeconds = value[1] | (value[2] << 8);
        if (rawSeconds === 0xffff) {
          clearWaiter();
          reject(new Error(t("spindown.failedRetry")));
          return;
        }

        const displaySeconds = rawSeconds / 100;
        clearWaiter();
        resolve(displaySeconds);
      };

      rejecterRef.current = reject;
      timeoutRef.current = setTimeout(() => {
        clearWaiter();
        reject(new Error(t("spindown.timeout")));
      }, timeout);
    });
  };

  const prepareSpindownResultWait = (timeout = 45000) => {
    if (spindownResultPromiseRef.current) {
      return spindownResultPromiseRef.current;
    }

    const promise = waitForSpindownTime(timeout);
    spindownResultPromiseRef.current = promise;
    void promise.catch(() => {});
    return promise;
  };

  const writeFff2 = async (bytes: number[]) => {
    await Central.writeCharacteristic(
      peripheral,
      fullUUID(powerServiceUuid),
      fullUUID(powerWriteUuid),
      new Uint8Array(bytes).buffer,
      { withoutResponse: false }
    );
  };

  const enableSpindownMode = async () => {
    if (spindownModeEnabledRef.current) return;
    if (!isConnectedRef.current || !isFff3ReadyRef.current) return;

    // 开始一轮新的消旋前清掉旧缓存，避免上一次结果污染
    lastSpindownPacketRef.current = null;

    console.log("[BLE] write FFF2 1001");
    await writeFff2([0x10, 0x01]);
    spindownModeEnabledRef.current = true;
  };

  const disableSpindownMode = async () => {
    if (!spindownModeEnabledRef.current) return;

    try {
      console.log("[BLE] write FFF2 1000");
      await writeFff2([0x10, 0x00]);
    } finally {
      spindownModeEnabledRef.current = false;
    }
  };

  const runSpindown = async () => {
    if (spindownStartedRef.current) return;
    spindownStartedRef.current = true;

    try {
      if (!isConnectedRef.current || !isFff3ReadyRef.current) {
        throw new Error(t("spindown.deviceNotReady"));
      }

      setStatusText(t("spindown.statusCalibrating"));
      const seconds = await prepareSpindownResultWait(5000);
      setSpindownSeconds(seconds);
      setPhase("completed");
      phaseRef.current = "completed";
      setStatusText(t("spindown.statusCompleted"));
    } catch (err: any) {
      console.warn("消旋失败:", err);
      setPhase("error");
      phaseRef.current = "error";
      setStatusText("消旋失败，请重新消旋");
      Alert.alert(
        "消旋失败",
        err?.message || "本次消旋未完成，请检查速度是否符合要求后重新尝试。",
        [{ text: "确定" }]
      );
    } finally {
      spindownResultPromiseRef.current = null;
    }
  };

  useEffect(() => {
    mountedRef.current = true;

    const connectionHandler = async (ev: {
      peripheral: ScannedPeripheral;
      connectionStatus: ConnectionStatus;
    }) => {
      const addr = ev.peripheral.address || ev.peripheral.systemId;
      if (addr !== deviceKey) return;

      const connected =
        ev.connectionStatus === "connected" || ev.connectionStatus === "ready";

      isConnectedRef.current = connected;
      setIsConnected(connected);

      if (connected) {
        hasConnectedOnceRef.current = true;
      }

      if (ev.connectionStatus !== "ready") {
        isFff3ReadyRef.current = false;
        setIsFff3Ready(false);
        notifySubscribedRef.current = false;
      }

      if (ev.connectionStatus === "ready" && !notifySubscribedRef.current) {
        await subscribeFff3IfNeeded();
      }

      if (
        !connected &&
        hasConnectedOnceRef.current &&
        mountedRef.current &&
        !hasNavigatedBackRef.current
      ) {
        hasNavigatedBackRef.current = true;
        skipDisconnectOnLeaveRef.current = true;

        Alert.alert(t("common.notice"), t("info2.disconnectedNeedReconnect"), [
          {
            text: t("info.confirm"),
            onPress: () => {
              navigation.reset({
                index: 0,
                routes: [{ name: "ScanScreen3" }],
              });
            },
          },
        ]);
      }
    };

    Central.addListener("peripheralConnectionStatus", connectionHandler);
    return () => {
      mountedRef.current = false;
      Central.removeListener("peripheralConnectionStatus", connectionHandler);
      notifySubscribedRef.current = false;
      setIsFff3Ready(false);
      clearWaiter();
    };
  }, [deviceKey, navigation, peripheral, t]);

  useEffect(() => {
    let cancelled = false;

    (async () => {
      setIsLoading(true);
      try {
        // 进入页面时清一次缓存，避免旧结果残留
        lastSpindownPacketRef.current = null;
        spindownResultPromiseRef.current = null;
        spindownStartedRef.current = false;
        phaseRef.current = "reach36";

        // Reuse existing connection from Info3 instead of reconnecting here.
        isConnectedRef.current = true;
        setIsConnected(true);
        await subscribeFff3IfNeeded();
      } catch (err) {
        console.warn("连接设备失败:", err);
        isConnectedRef.current = false;
        setIsConnected(false);
        if (!cancelled) {
          Alert.alert(t("common.notice"), t("spindown.connectFailed"));
        }
      } finally {
        if (!cancelled) {
          setIsLoading(false);
        }
      }
    })();

    return () => {
      cancelled = true;
      if (skipDisconnectOnLeaveRef.current) return;
      disableSpindownMode().catch((err) => {
        console.warn("关闭消旋模式失败:", err);
      });
    };
  }, [peripheral, t]);

  useEffect(() => {
    if (!isConnected || !isFff3Ready) return;

    enableSpindownMode().catch((err) => {
      console.warn("启用消旋模式失败:", err);
      spindownModeEnabledRef.current = false;
    });
  }, [isConnected, isFff3Ready]);

  useEffect(() => {
  if (!peripheral) return;

  let cancelled = false;
  let cleanup: (() => void) | null = null;

  observeFtmsIndoorBikeData(peripheral, (data) => {
    if (cancelled) return;

    const speed = data.speedKph;
    const now = Date.now();

    // ✅ UI 限速 10Hz
    if (now - lastUiUpdateRef.current > 100) {
      lastUiUpdateRef.current = now;
      setSpeedKph(speed);
    }

    // ===== ⭐ 实时状态机（不再依赖 React state） =====
    const currentPhase = phaseRef.current;

    // step1：到 36
    if (currentPhase === "reach36" && speed >= 36) {
      phaseRef.current = "wait18";
      setPhase("wait18");
      setStep1Done(true);
      setStatusText(t("spindown.statusReached36", { high: 36, low: 18 }));
      prepareSpindownResultWait();
      return;
    }

    // step2：降到 18
    if (currentPhase === "wait18" && speed <= 18) {
      phaseRef.current = "calibrating";
      setPhase("calibrating");
      setStep2Done(true);
      setStatusText(t("spindown.statusCalibrating"));

      runSpindown();
      return;
    }
  })
    .then((unsubscribe) => {
      if (cancelled) {
        unsubscribe();
        return;
      }
      cleanup = unsubscribe;
    })
    .catch(() => {});

  return () => {
    cancelled = true;
    cleanup?.();
  };
}, [peripheral, t]);

  const renderStepState = (done: boolean, active: boolean) => {
    if (done) {
      return <Icon name="check-circle" size={28} color="#19a15f" />;
    }

    if (active) {
      return <ActivityIndicator size="small" color="#eb3b3b" />;
    }

    return <Icon name="circle-outline" size={26} color="#c6c6c6" />;
  };

  const isDeviceReady = isConnected || isFff3Ready;
  const connectionLabel = isDeviceReady
    ? t("spindown.connected")
    : t("spindown.connecting");
  const connectionColor = isDeviceReady ? "#19a15f" : "#eb3b3b";

  return (
    <View style={styles.screen}>
      <MyStatusbar backgroundColor="#ffffff" dark={true} />
      <MyHeader
        backgroundColor="#ffffff"
        title={t("spindown.title")}
        textColor="#eb3b3b"
        navigation={navigation}
      />

      <ScrollView contentContainerStyle={styles.scrollContent}>
        <View style={styles.heroCard}>
          <View style={styles.connectionRow}>
            <View
              style={[
                styles.connectionBadge,
                { backgroundColor: `${connectionColor}16` },
              ]}
            >
              <View
                style={[styles.connectionDot, { backgroundColor: connectionColor }]}
              />
              <Text style={[styles.connectionText, { color: connectionColor }]}>
                {connectionLabel}
              </Text>
            </View>
          </View>

          <Text style={styles.heroTitle}>{t("spindown.headerTitle")}</Text>
          <Text style={styles.heroHint}>{statusText}</Text>

          <View style={styles.targetCard}>
            <Text style={styles.targetLabel}>{t("spindown.targetLabel")}</Text>
            <Text style={styles.targetValue}>36 km/h</Text>
            <Text style={styles.targetHint}>{t("spindown.targetHint")}</Text>
          </View>

          <View style={styles.speedCard}>
            <Text style={styles.speedLabel}>{t("spindown.currentSpeed")}</Text>
            <Text style={styles.speedValue}>{speedKph.toFixed(1)} km/h</Text>
          </View>
        </View>

        <View style={styles.stepCard}>
          <View style={styles.stepRow}>
            <View style={styles.stepIndexWrap}>
              <Text style={styles.stepIndex}>1</Text>
            </View>
            <View style={styles.stepTextWrap}>
              <Text style={styles.stepTitle}>
                {t("spindown.step1Title", { speed: 36 })}
              </Text>
              <Text style={styles.stepDesc}>{t("spindown.step1Desc")}</Text>
            </View>
            {renderStepState(step1Done, phase === "reach36")}
          </View>

          <View style={styles.divider} />

          <View style={styles.stepRow}>
            <View style={styles.stepIndexWrap}>
              <Text style={styles.stepIndex}>2</Text>
            </View>
            <View style={styles.stepTextWrap}>
              <Text style={styles.stepTitle}>{t("spindown.step2Title")}</Text>
              <Text style={styles.stepDesc}>
                {t("spindown.step2Desc", { speed: 18 })}
              </Text>
            </View>
            {renderStepState(step2Done, phase === "wait18" || phase === "calibrating")}
          </View>

          <View style={styles.divider} />

          <View style={styles.stepRow}>
            <View style={styles.stepIndexWrap}>
              <Text style={styles.stepIndex}>3</Text>
            </View>
            <View style={styles.stepTextWrap}>
              <Text style={styles.stepTitle}>{t("spindown.step3Title")}</Text>
              <Text style={styles.stepDesc}>
                {phase === "error"
                  ? "消旋失败，请重新消旋"
                  : spindownSeconds === null
                  ? phase === "calibrating"
                    ? t("spindown.step3Loading")
                    : t("spindown.step3Pending")
                  : `${formatSpindownSeconds(spindownSeconds)}s`}
              </Text>
            </View>
            {phase === "error" ? (
              <Icon name="close-circle" size={28} color="#eb3b3b" />
            ) : (
              renderStepState(phase === "completed", phase === "calibrating")
            )}
          </View>
        </View>

        {isLoading && (
          <View style={styles.loadingWrap}>
            <ActivityIndicator size={28} color="#eb3b3b" />
            <Text style={styles.loadingText}>{t("spindown.loading")}</Text>
          </View>
        )}

        {phase === "completed" && (
          <View style={styles.resultCard}>
            <Icon name="check-decagram" size={24} color="#19a15f" />
            <Text style={styles.resultText}>
              {t("spindown.result", {
                seconds: formatSpindownSeconds(spindownSeconds ?? 0),
              })}
            </Text>
          </View>
        )}

        {phase === "error" && (
          <TouchableOpacity
            activeOpacity={0.85}
            style={styles.retryButton}
            onPress={() => navigation.replace("Spindown", { peripheral })}
          >
            <Text style={styles.retryButtonText}>{t("spindown.retry")}</Text>
          </TouchableOpacity>
        )}
      </ScrollView>
    </View>
  );
}

const RED = "#eb3b3b";
const BG = "#f6f7fb";
const DARK = "#242424";

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    backgroundColor: BG,
  },
  scrollContent: {
    paddingHorizontal: 18,
    paddingTop: 10,
    paddingBottom: 28,
  },
  heroCard: {
    backgroundColor: "#ffffff",
    borderRadius: 24,
    paddingHorizontal: 18,
    paddingVertical: 18,
    shadowColor: "#000",
    shadowOpacity: 0.06,
    shadowRadius: 12,
    shadowOffset: { width: 0, height: 6 },
    elevation: 3,
  },
  connectionRow: {
    flexDirection: "row",
    justifyContent: "flex-end",
  },
  connectionBadge: {
    flexDirection: "row",
    alignItems: "center",
    paddingHorizontal: 10,
    paddingVertical: 6,
    borderRadius: 999,
  },
  connectionDot: {
    width: 8,
    height: 8,
    borderRadius: 4,
    marginRight: 6,
  },
  connectionText: {
    fontSize: 13,
    fontWeight: "600",
  },
  heroTitle: {
    fontSize: 18,
    fontWeight: "800",
    color: DARK,
    marginTop: 10,
  },
  heroHint: {
    fontSize: 15,
    color: "#666666",
    lineHeight: 22,
    marginTop: 8,
    minHeight: 26,
  },
  targetCard: {
    marginTop: 12,
    borderRadius: 18,
    backgroundColor: "#fff0f0",
    borderWidth: 1,
    borderColor: "#ffd4d4",
    paddingVertical: 14,
    paddingHorizontal: 14,
    alignItems: "center",
  },
  targetLabel: {
    fontSize: 14,
    color: "#8a5555",
    fontWeight: "600",
  },
  targetValue: {
    marginTop: 4,
    fontSize: 36,
    color: RED,
    fontWeight: "900",
    lineHeight: 40,
  },
  targetHint: {
    marginTop: 4,
    fontSize: 13,
    color: "#9b6c6c",
  },
  speedCard: {
    marginTop: 18,
    borderRadius: 22,
    backgroundColor: "#fff5f5",
    borderWidth: 1,
    borderColor: "#ffdede",
    paddingVertical: 20,
    alignItems: "center",
  },
  speedLabel: {
    fontSize: 15,
    color: "#666666",
  },
  speedValue: {
    fontSize: 34,
    fontWeight: "800",
    color: RED,
    marginTop: 8,
  },
  stepCard: {
    marginTop: 16,
    backgroundColor: "#ffffff",
    borderRadius: 24,
    paddingHorizontal: 16,
    paddingVertical: 10,
    shadowColor: "#000",
    shadowOpacity: 0.05,
    shadowRadius: 10,
    shadowOffset: { width: 0, height: 6 },
    elevation: 3,
  },
  stepRow: {
    flexDirection: "row",
    alignItems: "center",
    paddingVertical: 18,
  },
  stepIndexWrap: {
    width: 34,
    height: 34,
    borderRadius: 17,
    backgroundColor: "#fff1f1",
    alignItems: "center",
    justifyContent: "center",
    marginRight: 12,
  },
  stepIndex: {
    fontSize: 17,
    color: RED,
    fontWeight: "800",
  },
  stepTextWrap: {
    flex: 1,
    paddingRight: 12,
  },
  stepTitle: {
    fontSize: 17,
    color: DARK,
    fontWeight: "700",
    lineHeight: 24,
  },
  stepDesc: {
    fontSize: 14,
    color: "#777777",
    lineHeight: 20,
    marginTop: 4,
  },
  divider: {
    height: 1,
    backgroundColor: "#f0f0f0",
  },
  loadingWrap: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    marginTop: 18,
  },
  loadingText: {
    marginLeft: 10,
    fontSize: 14,
    color: "#666666",
  },
  resultCard: {
    marginTop: 16,
    backgroundColor: "#edf9f2",
    borderRadius: 18,
    paddingVertical: 14,
    paddingHorizontal: 16,
    flexDirection: "row",
    alignItems: "center",
  },
  resultText: {
    marginLeft: 10,
    color: "#156d45",
    fontSize: 15,
    fontWeight: "700",
  },
  retryButton: {
    marginTop: 18,
    height: 46,
    borderRadius: 14,
    backgroundColor: RED,
    alignItems: "center",
    justifyContent: "center",
  },
  retryButtonText: {
    color: "#ffffff",
    fontSize: 16,
    fontWeight: "700",
  },
});
