import React, { useEffect, useState } from "react";
import { View, Text, StyleSheet, Alert, Platform } from "react-native";
import { NativeStackScreenProps } from "@react-navigation/native-stack";
import { RootStackParamList } from "../App";
import RNFS from "react-native-fs";
import {
  startDfu,
  getDfuTargetId,
  DfuProgressEvent,
  DfuStateEvent,
} from "@systemic-games/react-native-nordic-nrf5-dfu";
import { useTranslation } from "react-i18next";
import { encode as btoa } from "base-64";
import MyStatusbar from "./component/MyStatusbar";
import MyHeader from "./component/MyHeader";

type Props = NativeStackScreenProps<RootStackParamList, "Dfu">;

interface DeviceInfo {
  hardware: number;
  latestFirmware: string;
  download: string;
}

interface ParsedFirmware {
  hardware: number;
  iteration: number;
  build: string;
  raw: string;
}

const bytesToBase64 = (bytes: Uint8Array): string => {
  let binary = "";
  const chunkSize = 0x8000;

  for (let i = 0; i < bytes.length; i += chunkSize) {
    const chunk = bytes.subarray(i, i + chunkSize);
    binary += String.fromCharCode(...chunk);
  }

  return btoa(binary);
};

const parseFirmwareVersion = (text: string): ParsedFirmware => {
  const raw = String(text ?? "").trim();
  const parts = raw.split(".");

  if (parts.length < 2) {
    throw new Error(`固件版本格式不正确: ${raw}`);
  }

  const hardware = parseInt(parts[0], 10);
  const iteration = parseInt(parts[1], 10);
  const build = parts.length >= 3 ? parts[2] : "";

  if (Number.isNaN(hardware) || Number.isNaN(iteration)) {
    throw new Error(`固件版本无法解析: ${raw}`);
  }

  return {
    hardware,
    iteration,
    build,
    raw,
  };
};

export default function DfuScreen({ route, navigation }: Props) {
  const { t } = useTranslation();
  const {
    deviceId,
    systemId,
    address,
    name,
    firmware: deviceFirmware,
  } = route.params;

  const [progress, setProgress] = useState(0);
  const [state, setState] = useState("准备中...");
  const [error, setError] = useState<string>();
  const [latestVersion, setLatestVersion] = useState("读取中...");
  const [isDfuRunning, setIsDfuRunning] = useState(false);

  const mapDfuStateToChinese = (s: string): string => {
    switch (s) {
      case "connecting":
        return "连接中…";
      case "starting":
        return "初始化中…";
      case "enablingDfuMode":
        return "启用 DFU 模式…";
      case "uploading":
        return "上传固件中…";
      case "validating":
        return "校验固件…";
      case "disconnecting":
        return "断开连接…";
      case "completed":
        return "升级完成";
      case "aborted":
        return "已取消";
      case "failed":
      case "dfu_failed":
        return "升级失败";
      case "initializing":
        return "启动中…";
      case "errored":
        return "升级出错！";
      default:
        return s;
    }
  };

  useEffect(() => {
    const unsubscribe = navigation.addListener("beforeRemove", (e) => {
      if (!isDfuRunning) return;
      e.preventDefault();
      Alert.alert("请稍候", "正在升级，请勿返回或关闭应用！");
    });

    return unsubscribe;
  }, [navigation, isDfuRunning]);

  useEffect(() => {
    const runDfu = async () => {
      try {
        setIsDfuRunning(true);
        setError(undefined);

        const rawDeviceId = String(deviceId ?? "").trim();
        const rawSystemId = String(systemId ?? rawDeviceId).trim();
        const rawAddress =
          typeof address === "number"
            ? address
            : address !== undefined && address !== null
            ? Number(address)
            : undefined;

        const safeDeviceId = getDfuTargetId({
          systemId: rawSystemId,
          address: rawAddress,
        });

        const firmwareText = String(deviceFirmware ?? "").trim();

        console.log("🔥 rawDeviceId =", rawDeviceId);
        console.log("🔥 rawSystemId =", rawSystemId);
        console.log("🔥 rawAddress =", rawAddress);
        console.log("🔥 safeDeviceId =", safeDeviceId);
        console.log("🔥 firmwareText =", JSON.stringify(firmwareText));

        if (!safeDeviceId) {
          throw new Error("无法生成 DFU 目标设备 ID");
        }

        const currentFw = parseFirmwareVersion(firmwareText);
        console.log("🔥 currentFw =", currentFw);

        const manifestUrl =
          "https://powerfun.oss-cn-shanghai.aliyuncs.com/yecongdfu/latest.json";
        const manifestPath = RNFS.CachesDirectoryPath + "/latest.json";

        console.log("🔥 before fetch manifest");
        const manifestResp = await fetch(manifestUrl);
        console.log("🔥 manifest status =", manifestResp.status);

        if (!manifestResp.ok) {
          throw new Error(`manifest 下载失败，HTTP ${manifestResp.status}`);
        }

        const manifestText = await manifestResp.text();
        console.log("🔥 manifest text =", manifestText);

        await RNFS.writeFile(manifestPath, manifestText, "utf8");
        console.log("🔥 manifest saved =", manifestPath);

        let manifest: { devices: DeviceInfo[] };

        try {
          manifest = JSON.parse(manifestText) as { devices: DeviceInfo[] };
        } catch (e) {
          throw new Error("manifest 不是合法 JSON: " + manifestText.slice(0, 200));
        }

        const deviceInfo = manifest.devices.find(
          (d) => d.hardware === currentFw.hardware
        );

        console.log("🔥 matched deviceInfo =", deviceInfo);

        if (!deviceInfo) {
          setIsDfuRunning(false);
          Alert.alert(
            "无法升级",
            `未找到 hardware=${currentFw.hardware} 的固件`,
            [{ text: "确认", onPress: () => navigation.goBack() }]
          );
          return;
        }

        setLatestVersion(deviceInfo.latestFirmware);

        const latestFw = parseFirmwareVersion(deviceInfo.latestFirmware);
        console.log("🔥 latestFw =", latestFw);

        if (latestFw.hardware !== currentFw.hardware) {
          throw new Error(
            `服务器固件硬件号不匹配：当前 ${currentFw.hardware}，服务器 ${latestFw.hardware}`
          );
        }

        if (latestFw.iteration <= currentFw.iteration) {
          setIsDfuRunning(false);
          Alert.alert("无需升级", "已是最新固件，无需升级", [
            { text: "确认", onPress: () => navigation.goBack() },
          ]);
          return;
        }

        console.log("🔥 upgrade allowed", {
          currentIteration: currentFw.iteration,
          latestIteration: latestFw.iteration,
        });

        const zipResp = await fetch(deviceInfo.download);
        console.log("🔥 zip status =", zipResp.status);

        if (!zipResp.ok) {
          throw new Error(`固件包下载失败，HTTP ${zipResp.status}`);
        }

        const zipArrayBuffer = await zipResp.arrayBuffer();
        const zipBytes = new Uint8Array(zipArrayBuffer);
        console.log("🔥 zip bytes =", zipBytes.length);

        const zipBase64 = bytesToBase64(zipBytes);
        const localPath = RNFS.CachesDirectoryPath + "/firmware.zip";

        await RNFS.writeFile(localPath, zipBase64, "base64");
        console.log("🔥 zip saved =", localPath);

        const dfuFilePath =
          Platform.OS === "android" ? "file://" + localPath : localPath;

        console.log("🔥 before startDfu =", {
          safeDeviceId,
          dfuFilePath,
          currentFirmware: currentFw.raw,
          latestFirmware: latestFw.raw,
        });

        await startDfu(safeDeviceId, dfuFilePath, {
          dfuStateListener: (ev: DfuStateEvent) => {
            console.log("🔥 dfu state =", ev.state);
            setState(ev.state);
          },
          dfuProgressListener: (ev: DfuProgressEvent) => {
            console.log("🔥 dfu progress =", ev.percent);
            setProgress(ev.percent);
          },
        });

        setIsDfuRunning(false);
        Alert.alert("升级成功", "升级成功，请重连设备", [
  {
    text: "确认",
    onPress: () => {
      navigation.reset({
        index: 0,
        routes: [{ name: "Home" }],
      });
    },
  },
]);
      } catch (err: any) {
        console.log("❌ runDfu error =", err);
        setIsDfuRunning(false);
        setError(err?.message || "DFU失败");
        Alert.alert("升级失败", err?.message || "DFU失败", [
          { text: "确认", onPress: () => navigation.goBack() },
        ]);
      }
    };

    runDfu();
  }, [deviceId, systemId, address, deviceFirmware, navigation]);

  return (
    <View style={styles.container}>
      <MyStatusbar backgroundColor="#FFFFFF" dark />
      <MyHeader
        title="固件升级"
        textColor="#333"
        backgroundColor="#FFFFFF"
        navigation={navigation}
      />

      <View style={styles.content}>
        <View style={styles.row}>
          <Text style={styles.titleText}>蓝牙名称: {name || "--"}</Text>
        </View>

        <View style={styles.row}>
          <Text style={styles.normalText}>最新版本: {latestVersion}</Text>
        </View>

        <View style={styles.row}>
          <Text style={styles.normalText}>当前版本: {deviceFirmware || "--"}</Text>
        </View>

        <View style={styles.row}>
          <Text style={styles.normalText}>
            升级状态: {mapDfuStateToChinese(state)}
          </Text>
        </View>

        <View style={styles.progressContainer}>
          <View style={[styles.progressBar, { width: `${progress}%` }]} />
          <Text style={styles.progressText}>{progress}%</Text>
        </View>

        {!!error && <Text style={styles.errorText}>{error}</Text>}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#FFFFFF",
  },
  content: {
    flex: 1,
    padding: 20,
    backgroundColor: "#FFFFFF",
  },
  row: {
    borderBottomWidth: 1,
    borderBottomColor: "#E7141E",
    paddingBottom: 6,
    marginBottom: 12,
  },
  titleText: {
    fontSize: 18,
    color: "#111111",
    fontWeight: "600",
  },
  normalText: {
    fontSize: 16,
    color: "#222222",
  },
  progressContainer: {
    height: 30,
    backgroundColor: "#EEEEEE",
    borderRadius: 15,
    overflow: "hidden",
    marginTop: 40,
    justifyContent: "center",
  },
  progressBar: {
    height: "100%",
    backgroundColor: "#E7141E",
  },
  progressText: {
    position: "absolute",
    alignSelf: "center",
    fontWeight: "bold",
    color: "#000000",
  },
  errorText: {
    color: "red",
    marginTop: 20,
    fontSize: 14,
  },
});