import 'package:get/get.dart';
import 'package:getx_scaffold/getx_scaffold.dart';
import 'package:getx_scaffold/getx_scaffold.dart' as dio;
import 'package:image_picker/image_picker.dart';
import 'package:image_picker_platform_interface/src/types/image_source.dart';
import 'package:ln_jq_app/common/model/base_model.dart';
import 'package:ln_jq_app/common/model/vehicle_info.dart';
import 'package:ln_jq_app/pages/c_page/car_info/attachment_viewer_page.dart';
import 'package:ln_jq_app/pages/qr_code/view.dart';
import 'package:ln_jq_app/storage_service.dart';
import 'package:path_provider/path_provider.dart';
import 'certificate_viewer_page.dart';
import 'dart:io';

class CarInfoController extends GetxController with BaseControllerMixin {
  @override
  String get builderId => 'car_info';

  // --- 车辆基本信息 ---
  String plateNumber = "";
  String vin = "-";
  String modelName = "-";
  String brandName = "-";

  // --- 证件附件列表 ---
  final RxList<String> drivingAttachments = <String>[].obs;
  final RxList<String> operationAttachments = <String>[].obs;
  final RxList<String> hydrogenationAttachments = <String>[].obs;
  final RxList<String> registerAttachments = <String>[].obs;
  String color = "";
  String hydrogenCapacity = "";
  String rentFromCompany = "";
  String address = "";
  bool isNotice = false;

  @override
  void onInit() {
    super.onInit();
    getUserBindCarInfo();
    msgNotice();
  }

  Future<void> msgNotice() async {
    final Map<String, dynamic> requestData = {
      'appFlag': 1,
      'isRead': 1,
      'pageNum': 1,
      'pageSize': 5,
    };
    final response = await HttpService.to.get(
      'appointment/unread_notice/page',
      params: requestData,
    );
    if (response != null) {
      final result = BaseModel.fromJson(response.data);
      if (result.code == 0 && result.data != null) {
        String total = result.data["total"].toString();
        isNotice = int.parse(total) > 0;
        updateUi();
      }
    }
  }

  @override
  void onReady() {
    super.onReady();
    // 如果未绑定车辆，且本次会话尚未提示过，则弹出提示
    if (!StorageService.to.hasShownBindVehicleDialog &&
        StorageService.to.isLoggedIn &&
        StorageService.to.loginChannel == LoginChannel.driver &&
        !StorageService.to.hasVehicleInfo) {
      Future.delayed(const Duration(milliseconds: 500), () {
        DialogX.to.showConfirmDialog(
          title: '当前尚未绑定车辆',
          confirmText: "去绑定",
          cancelText: "稍后",
          onConfirm: () {
            doQrCode();
          },
        );
        // 标记为已显示，本次会话不再提示
        StorageService.to.markBindVehicleDialogAsShown();
      });
    }
  }

  void doQrCode() async {
    var scanResult = await Get.to(() => const QrCodePage());
    if (scanResult == true) {
      getUserBindCarInfo();
      refreshAppui();
    }
  }

  //上传证件照
  void pickImage(String title, ImageSource source) async {
    if (source == ImageSource.camera) {
      takePhotoAndRecognize(title);
    } else if (source == ImageSource.gallery) {
      //相册选择逻辑
      var status = await Permission.photos.request();
      if (!status.isGranted) {
        if (status.isPermanentlyDenied) openAppSettings();
        showErrorToast("需要相册权限才能拍照上传");
        return;
      }
      final XFile? image = await ImagePicker().pickImage(
        source: ImageSource.gallery,
        imageQuality: 80,
      );
      if (image != null) {
        _uploadAndSaveCertificate(title, image.path);
      }
    }
  }

  void takePhotoAndRecognize(String title) async {
    var status = await Permission.camera.request();
    if (!status.isGranted) {
      if (status.isPermanentlyDenied) openAppSettings();
      showErrorToast("需要相机权限才能拍照上传");
      return;
    }

    final XFile? photo = await ImagePicker().pickImage(
      source: ImageSource.camera,
      imageQuality: 80, // 压缩图片质量以加快上传
    );
    if (photo == null) return;

    _uploadAndSaveCertificate(title, photo.path);
  }

  /// 提取共用的上传与关联证件逻辑
  void _uploadAndSaveCertificate(String title, String filePath) async {
    // 上传文件
    String? imageUrl = await uploadFile(filePath);
    if (imageUrl == null) return;

    // 根据标题映射业务类型
    String type = "";
    switch (title) {
      case "行驶证":
        type = "9";
        break;
      case "营运证":
        type = "10";
        break;
      case "加氢证":
        type = "12";
        break;
      case "登记证":
        type = "13";
        break;
      default:
        return;
    }

    // 调用后台接口关联证件
    var response = await HttpService.to.post(
      "appointment/truck/uploadCertificatePic",
      data: {
        "plateNumber": plateNumber,
        "imageUrl": imageUrl,
        "type": type,
      },
    );

    if (response != null) {
      final result = BaseModel.fromJson(response.data);
      if (result.code == 0) {
        showSuccessToast("上传成功");
        getUserBindCarInfo(); // 重新拉取数据更新UI
      } else {
        showErrorToast(result.error);
      }
    }
  }

  /// 上传图片
  Future<String?> uploadFile(String filePath) async {
    showLoading("正在上传...");
    try {
      dio.FormData formData = dio.FormData.fromMap({
        'file': await dio.MultipartFile.fromFile(filePath, filename: 'ocr_identity.jpg'),
      });

      var response = await HttpService.to.post("appointment/ocr/upload", data: formData);
      if (response != null) {
        final result = BaseModel.fromJson(response.data);
        if (result.code == 0) return result.data.toString();
        showErrorToast(result.error);
      }
    } catch (e) {
      showErrorToast("图片上传失败");
    } finally {
      dismissLoading();
    }
    return null;
  }

  void getUserBindCarInfo() async {
    if (StorageService.to.hasVehicleInfo) {
      VehicleInfo? bean = StorageService.to.vehicleInfo;
      if (bean == null) return;

      // 填充基本信息
      plateNumber = bean.plateNumber;
      vin = bean.vin;
      modelName = bean.modelName;
      brandName = bean.brandName;

      // 获取证件信息
      final response = await HttpService.to.get(
        'appointment/vehicle/getPicInfoByVin?vin=$vin&plateNumber=$plateNumber',
      );

      if (response != null && response.data != null) {
        final result = BaseModel.fromJson(response.data);
        if (result.code == 0 && result.data != null) {
          final data = result.data as Map<String, dynamic>;

          List<String> parseAttachments(dynamic list) {
            if (list is List) {
              // 确保列表中的每一项都是字符串
              return List<String>.from(list.map((item) => item.toString()));
            }
            return [];
          }

          // 将解析出的 URL 列表赋值给对应的 RxList
          drivingAttachments.assignAll(parseAttachments(data['drivingAttachment']));
          operationAttachments.assignAll(parseAttachments(data['operationAttachment']));
          hydrogenationAttachments.assignAll(
            parseAttachments(data['hydrogenationAttachment']),
          );
          registerAttachments.assignAll(parseAttachments(data['registerAttachment']));

          // 初始化时开始加载所有PDF
          attachments = [
            ...drivingAttachments,
            ...operationAttachments,
            ...hydrogenationAttachments,
            ...registerAttachments,
          ];

          color = data['color'].toString();
          hydrogenCapacity = data['hydrogenCapacity'].toString();
          rentFromCompany = data['rentFromCompany'].toString();
          address = data['address'].toString();

          loadAllPdfs();
        }
      }
      updateUi();
    }
  }

  /// 跳转到证件查看页面
  void navigateToCertificateViewer(String title, List<String> attachments) {
    if (!StorageService.to.hasVehicleInfo) {
      showToast('请先绑定车辆');
      return;
    }
    if (attachments.isEmpty) {
      showToast('暂无相关证件附件');
      return;
    }
    Get.to(
      () => const CertificateViewerPage(),
      arguments: {'title': title, 'attachments': attachments},
    );
  }

  /// 导航到通用的附件查看器页面
  void openAttachment(String url) {
    if (url.isEmpty) {
      showErrorToast('附件链接无效');
      return;
    }

    Get.to(() => const AttachmentViewerPage(), arguments: {'url': url});
  }

  /// 检查 URL 是否为 PDF
  bool isPdf(String url) {
    return url.toLowerCase().endsWith('.pdf');
  }

  List<String> attachments = [];

  // --- 新增: 状态管理 ---
  /// 用于存储网络PDF的本地路径，key是网络url，value是本地路径
  final RxMap<String, String> localPdfPaths = <String, String>{}.obs;

  /// 用于跟踪每个附件的加载状态，key是网络url
  final RxMap<String, bool> isLoading = <String, bool>{}.obs;

  /// 遍历所有附件，如果是PDF则进行下载
  void loadAllPdfs() {
    for (var url in attachments) {
      if (isPdf(url)) {
        _downloadPdf(url);
      }
    }
  }

  /// 下载单个PDF文件
  Future<void> _downloadPdf(String url) async {
    if (url.isEmpty) return;

    // 开始加载
    isLoading[url] = true;

    try {
      final dio = Dio();
      final Directory tempDir = await getTemporaryDirectory();
      final String savePath = '${tempDir.path}/${url.split('/').last}';

      // 检查文件是否已存在，避免重复下载
      if (await File(savePath).exists()) {
        localPdfPaths[url] = savePath;
        isLoading[url] = false;
        return;
      }

      await dio.download(url, savePath);

      // 下载成功后，更新本地路径
      localPdfPaths[url] = savePath;
    } catch (e) {
      print('PDF download error for $url: $e');
      // 出错时也可以更新状态，以便UI显示错误提示
    } finally {
      // 结束加载
      isLoading[url] = false;
    }
  }
}
