import React, { useEffect, useRef, 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,
  addDfuEventListener,
  DfuProgressEvent,
  DfuStateEvent,
} from "@systemic-games/react-native-nordic-nrf5-dfu";
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 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,
  };
};

const trace = (step: string, payload?: unknown) => {
  const timestamp = new Date().toISOString();
  if (payload === undefined) {
    console.log(`[DFU-TRACE ${timestamp}] ${step}`);
  } else {
    console.log(`[DFU-TRACE ${timestamp}] ${step}`, payload);
  }
};

export default function DfuScreen({ route, navigation }: Props) {
  const {
    deviceId,
    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 startedRef = useRef(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(() => {
    trace("screen mounted", {
      routeParams: {
        deviceId,
        name,
        deviceFirmware,
      },
    });

    return () => {
      trace("screen unmounted");
    };
  }, [deviceId, name, deviceFirmware]);

  useEffect(() => {
    const sub = addDfuEventListener("log", (ev) => {
      trace("dfu native log", ev);
    });

    return () => {
      sub.remove();
    };
  }, []);

  useEffect(() => {
    if (startedRef.current) {
      trace("runDfu duplicate effect skipped");
      return;
    }
    startedRef.current = true;

    const runDfu = async () => {
      try {
        trace("runDfu begin");
        setIsDfuRunning(true);
        setError(undefined);

        const rawDeviceId = String(deviceId ?? "").trim();
        const safeDeviceId = rawDeviceId;

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

        trace("resolved input", {
          rawDeviceId,
          safeDeviceId,
          firmwareText,
        });

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

        const currentFw = parseFirmwareVersion(firmwareText);
        trace("parsed current firmware", currentFw);

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

        trace("manifest fetch start", { manifestUrl, manifestPath });
        const manifestResp = await fetch(manifestUrl);
        trace("manifest fetch response", { status: manifestResp.status });

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

        const manifestText = await manifestResp.text();
        trace("manifest text loaded", { length: manifestText.length });

        await RNFS.writeFile(manifestPath, manifestText, "utf8");
        trace("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
        );

        trace("manifest device matched", { deviceInfo });

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

        setLatestVersion(deviceInfo.latestFirmware);

        const latestFw = parseFirmwareVersion(deviceInfo.latestFirmware);
        trace("parsed latest firmware", 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;
        }

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

        const localPath = RNFS.CachesDirectoryPath + "/firmware.zip";

        const oldFileExists = await RNFS.exists(localPath);
        if (oldFileExists) {
          await RNFS.unlink(localPath);
          trace("removed stale firmware zip", { localPath });
        }

        trace("firmware download start", {
          downloadUrl: deviceInfo.download,
          localPath,
        });

        const downloadResult = await RNFS.downloadFile({
          fromUrl: deviceInfo.download,
          toFile: localPath,
          background: false,
          discretionary: false,
        }).promise;

        trace("firmware download result", downloadResult);

        if (downloadResult.statusCode !== 200) {
          throw new Error(`固件包下载失败，HTTP ${downloadResult.statusCode}`);
        }

        const fileExists = await RNFS.exists(localPath);
        trace("firmware exists check", { fileExists });

        if (!fileExists) {
          throw new Error(`固件包下载后文件不存在: ${localPath}`);
        }

        const fileStat = await RNFS.stat(localPath);
        const fileSize = Number(fileStat.size ?? 0);
        trace("firmware stat", fileStat);

        if (!Number.isFinite(fileSize) || fileSize <= 0) {
          throw new Error(`固件包文件无效，大小为 ${fileStat.size}`);
        }

        const dfuFilePath = "file://" + localPath;
        let iosBootloaderName: string | undefined;
        if (Platform.OS === "ios") {
          if (name?.startsWith("PF-PM5-")) {
            iosBootloaderName = "PF-PM5-DFU";
          } else if (name?.startsWith("PF-STK-")) {
            iosBootloaderName = "PF-STK-DFU";
          }
        }

        trace("startDfu call", {
          safeDeviceId,
          dfuFilePath,
          localPath,
          fileSize,
          currentFirmware: currentFw.raw,
          latestFirmware: latestFw.raw,
          iosBootloaderName,
        });

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

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

    runDfu();
  }, [deviceId, name, 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,
  },
});
