import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:fis_common/logger/logger.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:vitalapp/architecture/utils/prompt_box.dart';
import 'package:vitalapp/rpc.dart';
import 'package:vitalapp/store/store.dart';

/// 部分分段返回的结果
class PartFileResultInfo {
  /// 分片上传的文件地址
  String fileUrl;

  /// 分片上传的eTag
  String eTag;

  /// 分块的uploadId
  String uploadId;

  /// 分块的下标
  int partNumber;

  PartFileResultInfo({
    required this.fileUrl,
    required this.eTag,
    required this.uploadId,
    required this.partNumber,
  });
}

/// 分段上传文件
class PartUploadFileInfo {
  /// 分片的下标
  int partNumber;

  /// 初始化生成的uploadId
  String uploadId;

  /// 分片文件的二进制数据
  Uint8List fileBytes;

  PartUploadFileInfo({
    required this.partNumber,
    required this.uploadId,
    required this.fileBytes,
  });
}

///存储上传文件基本信息
class StorageUploadFileInfo {
  ///文件token
  String fileToken;

  ///文件的二进制数据
  Uint8List fileBytes;

  ///文件名
  String fileName;

  ///文件模拟类型
  String? mimeType;

  /// 文件大小
  int? fileSize;

  StorageUploadFileInfo({
    required this.fileToken,
    required this.fileBytes,
    required this.fileName,
    this.mimeType,
    this.fileSize,
  });
}

///存储上传请求
class StorageUploadRequest {
  StorageUploadFileInfo fileInfo;

  StorageUploadRequest({
    required this.fileInfo,
  });
}

///web的存储API
class StorageWebApi {
  Future<bool> testApi() async => false;
}

///存储服务扩展类
extension StorageServiceExt on StorageService {
  ///鉴权 TODO: fileName 为空则接口报错，所以此处设置一个默认值
  Future<StorageServiceSettingDTO> getAuth({
    String? fileName,
    bool? isRechristen,
    List<DataItemDTO>? urlParams,
    List<DataItemDTO>? headerParams,
    String? requestMethod,
  }) async {
    try {
      final result = await rpc.storage.getAuthorizationAsync(FileServiceRequest(
        token: Store.user.token,
        fileName: fileName ?? "dat",
        isRechristen: isRechristen ?? true,
        urlParams: urlParams,
        headerParams: headerParams,
        requestMethod: requestMethod,
      ));
      return result;
    } catch (e) {
      return StorageServiceSettingDTO();
    }
  }

  /// 图片上传
  Future<String?> upload(XFile xfile, {String? fileType}) async {
    try {
      final auth = await getAuth(fileName: fileType);
      final bytes = await xfile.readAsBytes();
      Map<String, String> params = {};
      params['Authorization'] = auth.authorization!;
      params['ContentType'] = auth.contentType!;

      final response = await http
          .put(
            Uri.parse(auth.storageUrl!),
            body: bytes,
            headers: params,
          )
          .timeout(
            const Duration(seconds: 30),
          );
      if (response.statusCode == 200) {
        return auth.storageUrl!;
      }
    } catch (e) {
      PromptBox.toast('上传失败');
      logger.e("file upload error", e);
      return null;
    }
    return null;
  }

  // 将字符串写入文件
  Future<File> writeStringToFile(String content) async {
    final tempDir = await getTemporaryDirectory();
    final tempFile = File('${tempDir.path}/temp.txt');
    await tempFile.writeAsString(content);
    return tempFile;
  }

  // 文件上传
  Future<String?> uploadFile(File file) async {
    try {
      final auth = await getAuth();
      final bytes = await file.readAsBytes();
      Map<String, String> params = {};
      params['Authorization'] = auth.authorization!;
      params['ContentType'] = auth.contentType!;

      final response = await http
          .put(
            Uri.parse(auth.storageUrl!),
            body: bytes,
            headers: params,
          )
          .timeout(
            const Duration(seconds: 30),
          );
      if (response.statusCode == 200) {
        return auth.storageUrl!;
      }
    } catch (e) {
      PromptBox.toast('上传失败');
      logger.e("file upload error", e);
      return null;
    }
    return null;
  }

  ///文件上传(base64)
  Future<String?> uploadBase64File(String base64Str, String name) async {
    try {
      var buffer = base64.decode(base64Str);
      return uploadUint8List(buffer, name);
    } catch (e) {
      logger.e("file upload error", e);
    }
    return null;
  }

  ///文件上传（UInt8List）
  Future<String?> uploadUint8List(Uint8List buffer, String name,
      [bool? isRechristen]) async {
    try {
      var nameInfos = name.split('.');
      final auth = await getAuth(
        fileName: nameInfos.last,
        isRechristen: isRechristen,
      );
      Map<String, String> params = {};
      params['Authorization'] = auth.authorization!;
      params['ContentType'] = auth.contentType!;
      final response = await http
          .put(
            Uri.parse(auth.storageUrl!),
            body: buffer,
            headers: params,
          )
          .timeout(
            const Duration(seconds: 30),
          );
      if (response.statusCode == 200) {
        return auth.storageUrl;
      }
    } catch (e) {
      logger.e('StorageServiceExt uploadUint8List ex:$e');
    }
    return null;
  }
}
