/*
 * @Author: XianKaiQun
 * @Date: 2020-07-15 14:24:02
 * @LastEditors  : WuWei
 * @LastEditTime : 2023-11-16 11:50:53
 * @Description: 
 */

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:intl/intl.dart' show DateFormat;
import 'package:get/get.dart';
import 'package:app_package/app_package.dart';
import 'package:flutter/material.dart';
import 'package:receipt_package/src/impl/receipt_service_impl.dart';
import 'package:receipt_package/src/models/advance.dart';
import 'package:receipt_package/src/models/community_config.dart';
import 'package:receipt_package/src/models/pay_type.dart';
import 'package:receipt_package/src/models/payer.dart';
import 'package:wisdom_cli/wisdom_cli.dart';
import 'package:image/image.dart' as ui;
import '../models/asset_list.dart';
import '../models/deposite_charge_item.dart';
import '../models/prefee_charge_item.dart';

class PrivateSubmintStore with ChangeNotifier {
  final BuildContext context, providerContext;
  late Map<String, dynamic> routingArgs;

  PrivateSubmintStore(this.context, this.providerContext) {
    routingArgs = (ModalRoute.of(context)?.settings.arguments ??
            new Map<String, dynamic>()) as Map<String, dynamic>? ??
        {};
    if (routingArgs['preAssetItem'] != null) {
      _preAssetItem = routingArgs['preAssetItem'];
    }
    if (routingArgs['depositeAssetItem'] != null) {
      _depositeAssetItem = routingArgs['depositeAssetItem'];
    }
    if (routingArgs['preFeeChargeItem'] != null) {
      _preFeeChargeItem = routingArgs['preFeeChargeItem'];
    }
    if (routingArgs['depositeChargeItem'] != null) {
      _depositeChargeItem = routingArgs['depositeChargeItem'];
    }
  }

  String? get ptype => routingArgs['type'];

  String? get title => routingArgs['title'];

  get total => routingArgs['total'];

  String? get assetId => routingArgs['assetId'];

  String? get assetName => routingArgs['assetName'];

  String? get chargeSubject => routingArgs['chargeSubject'];
  get bills => routingArgs['bills'];

  get liquidatedDamagesBills => routingArgs['liquidatedDamagesBills'];
  num? get liquidatedDamagesFee => routingArgs['liquidatedDamagesFee'];
  num? get preFee => _preFee ?? routingArgs['preFee'];
  num? _preFee;

  num? get depositeFee => _depositeFee ?? routingArgs['depositeFee'];
  num? _depositeFee;
  num? get payFee => routingArgs['payFee'];

  /// 预存款资产
  get preAssetItem => _preAssetItem;

  var _preAssetItem;

  /// 押金资产
  get depositeAssetItem => _depositeAssetItem;

  var _depositeAssetItem;

  /// 预存款收费项目
  get preFeeChargeItem => _preFeeChargeItem;
  var _preFeeChargeItem;

  /// 押金收费项目
  get depositeChargeItem => _depositeChargeItem;
  var _depositeChargeItem;

  final communityGlobalStore = GetIt.I.get<CommunityGlobalStore>();

  String? get communityId => communityGlobalStore.data.id;

  var certificate;

  onInit() async {
    await Future.wait([
      getConfig(),
      getPayTypeList(),
      // getAssetList(),
    ]);
    if (ptype == 'depositePay') {
      await getAssetList();
    }

    if (ptype == 'prePay') {
      await getAssetList();
    }
  }

  List<AssetListModel> assetList = [];
  List<AssetsOfAssetListModel> preChooseAssetList = [];
  List<AssetsOfAssetListModel> depositeChooseAssetList = [];

  /// 按资产id获取全部关联资产--------------------------------
  Future getAssetList() async {
    var res = await ReceiptServiceImpl.getAssetListByAssetId({
      'assetId': assetId,
      'treeSelection': chargeSubject,
    });
    List<AssetListModel> _list = [];
    List<AssetsOfAssetListModel> _list1 = [];
    List<AssetsOfAssetListModel> _list2 = [];
    var _asset = AssetsOfAssetListModel(
      code: assetId,
      name: assetName,
      type: chargeSubject,
    );

    if (ptype == 'prepay' && chargeSubject != 'owner') {
      _list1.add(_asset);
    }
    if (ptype == 'depositePay' && chargeSubject == 'house') {
      _list2.add(_asset);
    }
    res.data?.forEach((item) {
          // if ((item.type == 'owner' ||
          if ((item.type == 'house' ||
                  item.type == 'car' ||
                  item.type == 'parkingSpace' ||
                  item.type == 'waterMeter' ||
                  item.type == 'electricMeter') &&
              item.assets != null &&
              item.assets!.length > 0)
            {
              _list.add(item);
              item.assets?.forEach((element) {
                element.type = item.type;
                if (item.type != 'electricMeter' &&
                    item.type != 'waterMeter' &&
                    chargeSubject != 'parkingSpace' &&
                    chargeSubject != 'car') {
                  _list1.add(element);
                }
                if (item.type == 'house') {
                  _list2.add(element);
                }
              });
            };
        });
    assetList = _list;
    preChooseAssetList = _list1;
    depositeChooseAssetList = _list2;
    if (ptype == 'prePay' && chargeSubject != 'owner') {
      _preAssetItem = _asset;
      preFeeChargeList = [];
      notifyListeners();
      await getPreChargeItemList();
    }
    if (ptype == 'depositePay' && chargeSubject == 'house') {
      _depositeAssetItem = _asset;
      depositeChargeItemList = [];
      notifyListeners();
      await getDepositeChargeItemList();
    }
    notifyListeners();
  }

  /// 选择预存款资产--------------------------------
  choosePreAsset() async {
    var res = await WPickerUtil.single<AssetsOfAssetListModel>(
      Get.context!,
      title: WisText('选择预存款资产'),
      getData: () async => await preChooseAssetList,
      initialValue: preAssetItem,
    );
    if (res != null) {
      _preAssetItem = res;
      _preFeeChargeItem = PrefeeChargeItemModel();
      _preFee = 0;
      notifyListeners();
      await getPreChargeItemList();
    }
  }

  /// 选择押金资产--------------------------------
  chooseDepositeAsset() async {
    var res = await WPickerUtil.single<AssetsOfAssetListModel>(
      Get.context!,
      title: WisText('选择押金资产'),
      getData: () async => await depositeChooseAssetList,
      initialValue: depositeAssetItem,
    );
    if (res != null) {
      _depositeAssetItem = res;
      await getDepositeChargeItemList();
      notifyListeners();
    }
  }

  List<PrefeeChargeItemModel> preFeeChargeList = [];

  /// 获取预存款收费项目
  Future getPreChargeItemList() async {
    var res = await ReceiptServiceImpl.getPrefeeChargeItemList({
      'assetId': _preAssetItem?.code,
      'chargeSubject': _preAssetItem?.type,
    });
    res.data?.forEach((item) {
          if (item.prepay == true)
            {
              item.feeName = '${item.feeName}【按月预存】';
            };
          if (item.prePayFee != null)
            {
              item.feeName =
                  '${item.feeName}${item.prePayFee! > 0 ? '【余额：${item.prePayFee}】' : ''}';
            };
        });
    List<PrefeeChargeItemModel>? res1 = await getGeneralPrefee();
    if (res1 != null &&
        _preAssetItem?.type != 'parkingSpace' &&
        _preAssetItem?.type != 'car') {
      preFeeChargeList = [...res1, ...(res.data ?? [])];
    } else {
      preFeeChargeList = res.data ?? [];
    }
    notifyListeners();
  }

  /// 获取通用预存款是否可用--------------------------------
  Future getGeneralPrefee() async {
    var res = await ReceiptServiceImpl.getGeneralPrefee({
      'houseId': assetId,
      'communityId': communityId,
    });

    if (res.data?.prePayGeneralPay == true) {
      return [
        PrefeeChargeItemModel(
          identification: '',
          feeName: '通用预存款',
          type: 'general',
        )
      ];
    }

    return null;
  }

  /// 选择预存款项目--------------------------------
  choosePrefeeCharge() async {
    if (preAssetItem?.code == null) {
      WToastUtil.show('请先选择缴费预存资产');
      return;
    }
    var res = await WPickerUtil.single<PrefeeChargeItemModel>(
      Get.context!,
      title: WisText('选择预存款项目'),
      getData: () async => await preFeeChargeList,
      initialValue: preFeeChargeItem,
    );
    if (res != null) {
      _preFeeChargeItem = res;
      _preFee = 0;
      notifyListeners();
    }
  }

  List<DepositeChargeItemModel> depositeChargeItemList = [];

  /// 选择押金项目--------------------------------
  chooseDepositeCharge() async {
    if (depositeAssetItem?.code == null) {
      WToastUtil.show('请先选择缴费押金资产');
      return;
    }
    var res = await WPickerUtil.single<DepositeChargeItemModel>(
      Get.context!,
      title: WisText('选择押金项目'),
      getData: () async => await depositeChargeItemList,
      initialValue: depositeChargeItem,
    );
    if (res != null) {
      _depositeChargeItem = res;
      _depositeFee = depositeChargeItem?.fee ?? 0;
      notifyListeners();
    }
  }

  int month = 0;

  /// 月份输入--------------------------------
  inputPrefee(value) async {
    if (preFeeChargeItem.prepay == true) {
      if (value != null && value != '') {
        var _value = int.parse(value);
        _preFee = (preFeeChargeItem.receivableFeeDB ?? 0) * _value;
      } else {
        _preFee = 0;
      }
    } else {
      if (value != null && value != '') {
        var _value = double.parse(value);
        _preFee = _value;
      } else {
        _preFee = 0;
      }
    }
    notifyListeners();
  }

  /// 获取押金收费项目列表--------------------------------
  Future getDepositeChargeItemList() async {
    var res = await ReceiptServiceImpl.getDepositeChargeItemList({
      'communityId': communityId,
    });
    depositeChargeItemList = res.data ?? [];
    notifyListeners();
  }

  ///小区配置----------------------------------------
  ///
  CommunityConfigModel? config;
  Future getConfig() async {
    final res = await ReceiptServiceImpl.getCommunityConf({
      'communityId': communityId,
    });
    config = res.data!;
    notifyListeners();
  }

  ///超额缴纳----------------------------------------
  ///
  ///
  ///
  ///
  ///
  ///
  bool isAdvance = false;

  isAdvanceChange() {
    totalValueText = '';
    isAdvance = !isAdvance;
    notifyListeners();
  }

  ///总缴纳费用--------------------------------
  String totalValueText = '';
  num get totalValue => (double.tryParse(totalValueText) ?? 0);

  totalValueChange(v) {
    totalValueText = v;
    notifyListeners();
  }

  ///超额缴纳费用--------------------------------
  num get totalPrePayFee {
    if (totalValue == 0 || totalValue < total!) {
      return 0;
    } else {
      var str = (totalValue - total!).toStringAsFixed(2);
      return double.tryParse(str) ?? 0;
    }
  }

  ///超额金额--------------------------------
  List<AdvanceModel> advanceSelects = []; //选中的

  ///显示的文字--------------------------------
  String get advanceText => advanceSelects.length == 0
      ? ''
      : '${advanceSelects[0].assetFullName}-${advanceSelects[1].feeName}';

  Map<String, dynamic> get prePayBill => advanceSelects.length == 0
      ? {}
      : {
          'assetId': advanceSelects[0].assetId,
          'chargeSubject': advanceSelects[0].chargeSubject,
          'identification': advanceSelects[1].identification,
          'prePayType': advanceSelects[1].type,
        };

  ///请求--------------------------------
  Future<List<AdvanceModel>> getAdvance(List<AdvanceModel> list) async {
    final item = list.length == 0 ? null : list.last;
    if (item?.assetId == null) {
      final res = await ReceiptServiceImpl().getPrePayChoiceAsset(
        {
          'assetId': assetId,
          'chargeSubject': chargeSubject,
        },
      );
      return res.data!;
    } else {
      final res = await ReceiptServiceImpl().getChargeItem({
        'assetId': item?.assetId,
        'chargeSubject': item?.chargeSubject,
        'chargeItemType': 'prePay',
      });
      return res.data!;
    }
  }

  ///触发选择--------------------------------
  advancePicker() async {
    final res = await WPickerUtil.infinity<AdvanceModel>(
      context,
      title: Text('预存款项目'),
      initialValue: advanceSelects,
      getData: (list) => getAdvance(list).then((value) => value),
      isLast: (item) async => item.last.feeName != null,
    );
    if (res != null) {
      advanceSelects = res;
      notifyListeners();
    }
  }

  ///缴费人----------------------------------------
  ///
  ///
  ///
  ///
  PayerModel? payer;

  ///缓存
  List<PayerModel>? payerList;

  Future<List<PayerModel>?> getPayerList() async {
    if (payerList != null) return payerList;
    final res = await ReceiptServiceImpl().getPayerList({
      'assetId': assetId,
      'treeSelection': chargeSubject,
      'communityId': communityId,
    });
    payerList = res.data;
    return payerList;
  }

  payerPicker() async {
    final res = await WPickerUtil.single<PayerModel>(
      context,
      title: Text('缴费人'),
      getData: () => getPayerList().then((value) => value!),
    );
    if (res != null) {
      payer = res;
      notifyListeners();
    }
  }

  /// 缴费凭证选择--------------------------------
  imagePicker() async {
    final res = await WAssetPickerUtil.image(
      maxCount: 1,
      source: WImageSource.cameraAndGallery,
    );
    if (res.isNotEmpty) {
      final futures = onPostWaterMarkImg(res[0].file!);
      try {
        WLoadingUtil.show();
        final res = await futures;
        certificate = res;
        notifyListeners();
      } finally {
        WLoadingUtil.hide();
      }
    }
  }

  GlobalKey wmglkey = new GlobalKey();

  /// 添加水印
  Future<File?> addWaterMark(File file) async {
    /// 水印widget 转图片
    // if (currentAddress != null) {
    var tempMark = await capturePng(wmglkey);

    /// 水印
    ui.Image tempMarkImg = ui.decodeImage(tempMark!)!;

    /// 照片
    ui.Image fileImg = ui.decodeImage(file.readAsBytesSync())!;

    /// 照片上加上水印
    ui.Image img = ui.drawImage(fileImg, tempMarkImg);
    List<int> wmImage = ui.encodeJpg(img);

    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path;

    String picName = 'receipt_submit_${DateTime.now()}.jpg';

    ///拼接目录
    appDocPath = "$appDocPath/$picName";

    ///校验图片是否存在
    var _file = File(appDocPath);
    bool exist = await _file.exists();
    if (exist) {
      ///如果图片存在就进行删除替换
      ///如果新的图片加载失败，那么旧的图片也被删除了
      await file.delete();
    }
    await File(appDocPath).writeAsBytes(wmImage);
    return _file;
  }

  /// 上传水印照片
  Future onPostWaterMarkImg(File file) async {
    var res = await addWaterMark(file);
    if (res != null) {
      return await GlobalApi.postUploadImageObject(res);
    } else {
      WLoadingUtil.hide();
      return null;
    }
  }

  /// 预览详情图片
  void onShowImage(image) {
    List<ImageProvider> images = [];
    images.add(CachedNetworkImageProvider(AppParseUtil.image(image)));
    WisPhotoViewUtil.show(images, 0);
  }

  /// 删除图片
  Future<void> deleteImg() async {
    certificate = null;
    notifyListeners();
  }

  ///支付方式----------------------------------------
  ///
  ///
  ///
  ///

  SinglePickerEntity? payType;

  ///缓存--------------------------------
  List<SinglePickerEntity> payTypeList = [];
  List<PayTypeModel>? payTypeAllList;

  Future getPayTypeList() async {
    final res = await ReceiptServiceImpl.getPayTypeBankList({
      'communityId': communityId,
    });
    payTypeAllList = res.data ?? [];
    var data = jsonDecode(jsonEncode(res.data)) ?? [];
    payTypeList = await SinglePickerEntity.listMap2entity(data, 'name', 'id');
    notifyListeners();
  }

  payTypePicker() async {
    final res = await WPickerUtil.single<SinglePickerEntity>(
      context,
      title: Text('支付方式'),
      getData: () async => await payTypeList,
      initialValue: SinglePickerEntity(
        name: payType?.name,
        unique: payType?.unique,
      ),
    );
    if (res != null) {
      payType = res;
      curBank = null;
      getCurBankCountList();
      notifyListeners();
    }
  }

  List<SinglePickerEntity> bankList = [];
  List<RelationBankAccountsOfPayTypeModel> bankAllList = [];
  getCurBankCountList() {
    payTypeAllList!.forEach((item) async {
          if (item.id == payType?.unique)
            {
              bankAllList = item.relationBankAccounts ?? [];
              bankList = await SinglePickerEntity.listMap2entity(
                  decodeList(item.relationBankAccounts ?? []), 'bank', 'id');
              notifyListeners();
            };
        });
  }

  decodeList(item) {
    List data;
    item.forEach(
      (bank) => {bank.bank = '${bank.bank}-${bank.bankAccount}'},
    );
    data = jsonDecode(jsonEncode(item)) ?? [];
    return data;
  }

  SinglePickerEntity? curBank;

  ///银行账户----------------------------------------
  bankPicker() async {
    final res = await WPickerUtil.single<SinglePickerEntity>(
      context,
      title: Text('选择收款账户'),
      getData: () async => await bankList,
      initialValue: SinglePickerEntity(
        name: curBank?.name,
        unique: curBank?.unique,
      ),
    );
    if (res != null) {
      curBank = res;
      notifyListeners();
    }
  }

  ///缴费备注----------------------------------------
  ///
  ///
  ///
  ///
  ///
  String? remark = '';
  onReMarkChange(String v) {
    remark = v;
  }

  ///收据号、发票号----------------------------------------
  ///
  ///{[ticketNo],[ticketType] }
  ///[ticketType]	票据类型([receipt] 收据;[invoice] 发票)
  ///
  ///
  ///

  List<Map<String, dynamic>>? tickets = [];

  String? receiptText = '';
  String? invoiceText = '';
  onReceiptTextChange(v) {
    receiptText = v;
  }

  onInvoiceTextChange(v) {
    invoiceText = v;
  }

  onReceiptTextSave() {
    if (receiptText == '') return;
    addTickets(value: receiptText, isInvoice: false);
    receiptText = '';
    notifyListeners();
  }

  onInvoiceTextSave() {
    if (invoiceText == '') return;
    addTickets(value: invoiceText, isInvoice: true);
    invoiceText = '';
    notifyListeners();
  }

  bool addTickets({String? value, isInvoice = false}) {
    FocusScope.of(context).requestFocus(FocusNode());
    var item = {
      'ticketNo': value,
      'ticketType': isInvoice ? 'invoice' : 'receipt',
    };
    if (tickets!.indexOf(item) != -1) {
      WToastUtil.show('票据已存在');
      return false;
    } else {
      tickets!.add(item);
      return true;
    }
  }

  removeTickets(Map<String, dynamic> item) {
    tickets!.remove(item);
    notifyListeners();
  }

  ///提交---------------------------------
  ///
  ///
  ///
  ///
  ///
  submit() async {
    if (ptype == 'prePay' &&
        (preFee == null ||
            preFee == 0 ||
            _preAssetItem?.code == null ||
            _preFeeChargeItem?.identification == null)) {
      WToastUtil.show('请填写完预存款信息');
      return;
    }

    if (ptype == 'depositePay' &&
        (depositeFee == null ||
            depositeFee == 0 ||
            _depositeAssetItem?.code == null ||
            _depositeChargeItem?.identification == null)) {
      WToastUtil.show('请填写完押金信息');
      return;
    }
    if (chargeSubject != 'owner' &&
        (payType?.name == null || payType?.name == '')) {
      WToastUtil.show('请选择缴费渠道');
      return;
    }
    if (chargeSubject != 'owner' && payer?.payer == null) {
      WToastUtil.show('请选择缴费人');
      return;
    }
    if (totalPrePayFee == 0 && isAdvance) {
      WToastUtil.show('超额缴纳时请完整填写相对应的表单');
      return;
    }
    if (config!.notNullBankAccount == true &&
        bankAllList.length > 0 &&
        curBank?.unique == null) {
      WToastUtil.show('请选择收款账户');
      return;
    }

    List prePayBills = [];

    if (preFee != null && preFee! > 0) {
      prePayBills.add({
        'payFee': preFee,
        'assetId': _preAssetItem?.code,
        'chargeSubject': _preAssetItem?.type,
        'identification': _preFeeChargeItem?.identification,
        'prePayType': _preFeeChargeItem?.type,
      });
    }
    List depositeBills = [];
    if (depositeFee != null && depositeFee! > 0) {
      depositeBills.add({
        'payFee': depositeFee,
        'assetId': _depositeAssetItem?.code,
        'chargeSubject': _depositeAssetItem?.type,
        'identification': _depositeChargeItem?.identification,
      });
    }
    var params = {
      "bills": bills ?? [],
      "prePayBills": prePayBills,
      "depositeBills": depositeBills,
      "totalPayFee": payFee ?? 0,
      "totalDiscountFee": 0,
      "totalPrePayFee": preFee ?? 0,
      "payType": payType?.name,
      "payAt": DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
      "mobile": chargeSubject == 'owner'
          ? assetName?.split('').contains('/') == true
              ? assetName?.split('/')[1]
              : assetName?.split(' ')[1]
          : payer?.mobile,
      "payer": chargeSubject == 'owner'
          ? assetName?.split('').contains('/') == true
              ? assetName?.split('/')[0]
              : assetName?.split(' ')[0]
          : payer?.payer,
      "assetId": assetId,
      "treeSelection": chargeSubject,
      "liquidatedDamagesBills": liquidatedDamagesBills ?? [],
      "remark": remark,
      "ticketAddVos": tickets,
      "bankAccountId": curBank?.unique ?? null,
      "certificate": certificate != null ? certificate['id'] : null,
    };

    // return;

    ///超额缴纳
    if (isAdvance) {
      params['prePayBill'] = prePayBill;
    }
    var res = await ReceiptServiceImpl().postAcquire(params);
    if (res.code == '200') {
      await Navigator.pushNamed(context, 'receipt/success',
          arguments: res.data);
      Navigator.pop(context, {'isRefresh': true});
    }
  }
}
