import 'dart:convert';
import 'dart:typed_data';
import 'package:image/image.dart' as img;

class SteganographyUtil {
  static const String MAGIC_HEADER = 'SGWCMAID';

  /// 图片隐写：写入数据
  static Uint8List hideDataInImage(Uint8List imageBytes, String secretData) {
    // 1. 解码图片
    final image = img.decodeImage(imageBytes);
    if (image == null) throw Exception('图片解码失败');

    // 2. 准备数据：必须以 MAGIC_HEADER 开头，并以 \0 结尾
    final dataBytes = utf8.encode(secretData);
    final payload = Uint8List(dataBytes.length + 1);
    payload.setRange(0, dataBytes.length, dataBytes);
    payload[dataBytes.length] = 0; // 终止符

    // 检查容量
    if (payload.length * 8 > image.width * image.height) {
      throw Exception('图片像素不足以容纳数据');
    }

    int payloadIndex = 0;
    int bitIndex = 7; // MSB First (最高位优先)

    // ✅ 修复：必须严格按照 Java 的 (y, x) 顺序遍历，确保坐标对齐
    bool finished = false;
    for (int y = 0; y < image.height; y++) {
      for (int x = 0; x < image.width; x++) {
        if (payloadIndex >= payload.length) {
          finished = true;
          break;
        }

        // 获取当前坐标的像素
        final pixel = image.getPixel(x, y);

        // 取出当前字节的特定位
        int currentByte = payload[payloadIndex];
        int bit = (currentByte >> bitIndex) & 1;

        // ✅ 修复：通过 red 分量操作，屏蔽不同图片格式（RGBA/BGRA）的底层差异
        int r = pixel.r.toInt();
        int g = pixel.g.toInt();
        int b = pixel.b.toInt();
        int a = pixel.a.toInt();

        // 修改 R 通道最低位
        r = (r & 0xFE) | bit;

        // 写回像素（保持其他通道不变）
        image.setPixel(x, y, img.ColorRgba8(r, g, b, a));

        bitIndex--;
        if (bitIndex < 0) {
          bitIndex = 7;
          payloadIndex++;
        }
      }
      if (finished) break;
    }

    // ✅ 必须导出为 PNG，防止 JPEG 压缩破坏 LSB 位
    return Uint8List.fromList(img.encodePng(image));
  }

  /// 提取数据（本地调试用，逻辑需与写入完全对称）
  static String? extractDataFromImage(Uint8List imageBytes) {
    final image = img.decodeImage(imageBytes);
    if (image == null) return null;

    List<int> extractedBytes = [];
    int currentByte = 0;
    int bitCount = 0;

    outer:
    for (int y = 0; y < image.height; y++) {
      for (int x = 0; x < image.width; x++) {
        final pixel = image.getPixel(x, y);
        int bit = pixel.r.toInt() & 1;

        // MSB First 组装字节
        currentByte = (currentByte << 1) | bit;
        bitCount++;

        if (bitCount == 8) {
          if (currentByte == 0) break outer; // 结束符
          extractedBytes.add(currentByte);
          currentByte = 0;
          bitCount = 0;
        }
      }
    }

    if (extractedBytes.isEmpty) return null;
    try {
      return utf8.decode(extractedBytes);
    } catch (e) {
      return null;
    }
  }
}