using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TellerSystem.Contract.ContractBase;
using TellerSystem.Communication;
using TellerSystem.Library.Ext.TradeExtension;
using Platform.Common.LogSystem;
using TellerSystem.Library.Ext.Function;
using Platform.Presentation.Interfaces;
using Platform.Common.BasicFunctions;
using Platform.Presentation.PagesHelper;
using Platform.Print;
using TellerSystem.PrintTemplate.Extension;
using TellerSystem.ServiceProxy.Ext.TradeBusinessEntitys;
using TellerSystem.ServiceProxy.Ext.ServiceHelper;
using System.Windows;
using System.Windows.Controls;
using Platform.Common.RunningParameters;
using TellerSystem.Contract.Function;
using TellerSystem.Contract.Entry;

namespace TellerSystem.Contract.Contracts
{
    /// <summary>
    /// 契约执行流程定义
    /// </summary>
    public static class ContractManager
    {
        public static bool RaiseSubmit(this PageBase page)
        {
            if (page is ISubmitContract)
            {
                AuthDataHelper authdata = new AuthDataHelper(page);
                authdata.ClearAuthData();
                var contract = page as ISubmitContract;
                if (contract == null || contract.SubmitEntry == null) return false;
                //重复提交的情况
                if (contract.SubmitEntry.Submitted)
                {
                    TradeHandle.WriteTraceLog("ContractManager.RaiseSubmit:阻断错误的重复提交！", contract.SubmitEntry.MessageData.Fd16);
                    return false;
                }
                Message message = null;
                //组装提交数据失败或组装对象为null，流程失败
                if (!contract.PreviewSubmitting(out message)) return false;
                if (message == null || message.Fd16 != page.TradeInfo.MainCode)
                {
                    PlatformLogger.TradeErrorInfo("提交通讯错误：", new Exception("提交报文与主交易码不一致，请检查..."));
                }
                //初始化提交入口对象，执行提交流程
                var entry = contract.SubmitEntry;
                if (entry == null || !entry.LoadData(page, message)) return false;
                //检查复核
                if (!RaiseRecheck(page, message)) return false;
                //检查授权             
                if (!RaiseAuthorize(page, message)) return false;
                //检查收费
                if (!RaisePaymentFee(page, message)) return false;
                //触发提交
                if (!entry.RaiseSubmit()) return false;
            }
            return true;
        }

        /// <summary>
        /// 触发授权流程
        /// </summary>
        /// <param name="page"></param>
        /// <param name="message"></param>
        /// <param name="powerCode"></param>
        /// <returns></returns>
        public static bool RaiseAuthorize(this PageBase page, Message message, string powerCode = "0")
        {
            if (page is IAuthorizeContract)
            {
                var contract = page as IAuthorizeContract;
                if (contract == null) return false;
                //考试系统无需进行授权
                if (ExamSystem.Instance.InExamMode) return true;
                //若交易未启用授权标志，则认为无需进行授权
                if (string.Compare(page.TradeAPIs.GetTradeMetadata("isAuth"), "true", true) != 0)
                    return true;
                //if (string.IsNullOrWhiteSpace(powerCode)) return false;
                //获取授权入口
                if (contract.AuthorizeEntries == null || contract.AuthorizeEntries.Count == 0) return false;

                var entry = contract.AuthorizeEntries.Find(x => { return x.PowerCode == powerCode; });
                if (entry == null) return false;
                entry.LoadData(page, message);
                return entry.RaiseAuthorize();
            }
            return true;
        }

        /// <summary>
        /// 触发复核流程
        /// </summary>
        /// <param name="page"></param>
        /// <param name="message"></param>
        /// <param name="powerCode"></param>
        /// <returns></returns>
        public static bool RaiseRecheck(this PageBase page, Message message, string powerCode = "0")
        {
            if (page is IRecheckContract)
            {
                var contract = page as IRecheckContract;
                if (contract == null) return false;
                //考试系统无需进行复核
                if (ExamSystem.Instance.InExamMode) return true;
                //若交易未启用复核标志，则认为无需进行复核
                if (string.Compare(page.TradeAPIs.GetTradeMetadata("isRecheck"), "true", true) != 0)
                    return true;
                //if (string.IsNullOrWhiteSpace(powerCode)) return false;
                //获取授权入口
                if (contract.RecheckEntries == null || contract.RecheckEntries.Count == 0) return false;

                var entry = contract.RecheckEntries.Find(x => { return x.PowerCode == powerCode; });
                if (entry == null) return false;
                entry.LoadData(page, message);
                return entry.RaiseRecheck();
            }
            return true;
        }

        /// <summary>
        /// 触发收费流程
        /// </summary>
        /// <param name="page"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static bool RaisePaymentFee(this PageBase page, Message message)
        {
            if (page is IPaymentFeeContract)
            {
                var contract = page as IPaymentFeeContract;
                if (contract == null) return false;
                //若交易未启用收费检查标志，则认为无需进行收费检查
                if (string.Compare(page.TradeAPIs.GetTradeMetadata("isPaymentFee"), "true", true) != 0)
                    return true;
                //若交易通讯方式为核心前置CallGateway2CBS，则不触发收费
                if (message.TransitNode == TellerSystem.Communication.MessageHelper.TransitType.CallGateway2CBS)
                {
                    PlatformLogger.CommunicationInfo("核心前置通讯不支持收费（TransitType.CallGateway2CBS）");
                    return true;
                }
                //if (string.IsNullOrWhiteSpace(powerCode)) return false;
                string FLAG = TradeManagerHandle.TT_SYSCONFIG_GetConfigValueByConfigID("2ea3a7e6cfa04f89a335bf1e363295de");
                string filedata = string.Empty;
                filedata = message.FileData;
                //执行收费流程
                var isPaymentFee = false;
                //检查收费失败
                var args = new PaymentFeeArguments(message);
                if (!contract.CheckFee(args, out isPaymentFee)) return false;
                //需要收费且，执行收费决策失败
                if (isPaymentFee && !contract.RaisePaymentFee(args)) return false;
                message.FileData = filedata;
            }
            return true;
        }

        /// <summary>
        /// 触发评价流程
        /// </summary>
        /// <param name="page"></param>
        public static void RaiseEvaluation(this PageBase page)
        {
            var contract = page as IEvaluationContract;
            if (contract == null) return;
            //TODO:菜单开关控制，暂注释
            if (page.TradeAPIs.GetTradeMetadata("isEvaluation") != "true") return;
            //评价数据收集
            var record = new EvaluationRecord();
            if (!contract.PreviewEvaluation(record))
            {
                //采用默认提取//"扣划账号", "扣费账号", "账号/科目号","合同编号",
                var list_accno = page.PositioningUI(new List<string>() { "账／卡号", "账号", "卡    号", "账    号", "结算账号", "账/卡号", "贷款账号", "还款账号", "贷方账号", "记贷付款账号", "借据展示号", "记账账号", "收款人账号", "付款人账号", "签约账号", "账/卡 号", "本行账号", "申请人账号" }).Select(x => x.Item2).Where(x => x is TextBox).Select(x => (x as TextBox).Text).Distinct().ToDictionary(x => x);
                var list_idno = page.PositioningUI(new List<string>() { "证件号码" }).Select(x => x.Item2).Where(x => x is TextBox).Select(x => (x as TextBox).Text).Distinct().ToDictionary(x => x);
                var list_name = page.PositioningUI(new List<string>() { "户    名", "户　　名", "客户名称" }).Select(x => x.Item2).Where(x => x is TextBox).Select(x => (x as TextBox).Text).Distinct().ToDictionary(x => x);//一个是半角一个全角
                var list_amt = page.PositioningUI(new List<string>() { "交易金额", "开户金额", "支取金额" }).Select(x => x.Item2).Where(x => x is TextBox).Select(x => (x as TextBox).Text).Distinct().ToDictionary(x => x);
                //如存在分歧，则提醒客户选择
                record.AccNo = list_accno.Count == 1 ? list_accno.ElementAt(0).Value : string.Empty;
                record.IdNo = list_idno.Count == 1 ? list_idno.ElementAt(0).Value : string.Empty;
                record.Name = list_name.Count == 1 ? list_name.ElementAt(0).Value : string.Empty;
                record.Amt = list_amt.Count == 1 ? list_amt.ElementAt(0).Value : string.Empty;
                var gen = new Func<string, Dictionary<string, string>, UIElement>((title, dict) =>
                {
                    var line = new StackPanel { Orientation = Orientation.Horizontal };
                    line.Children.Add(new TextBlock { Text = title, Width = 120 });
                    var comboBox = new ComboBox { ItemsSource = dict, SelectedIndex = 0, Width = 300 };
                    comboBox.Loaded += (s, e) =>
                    {
                        comboBox.SelectedIndex = 0;
                        if (dict.Count < 2)
                            comboBox.IsEnabled = false;
                    };
                    line.Children.Add(comboBox);
                    return line;
                });
                do
                {
                    //TODO:是否每次都提示信息
                    if (list_accno.Count >= 1 || list_idno.Count >= 1)
                    {
                        var content = new StackPanel();
                        //组织页面
                        content.Children.Add(gen("银行账号", list_accno));
                        content.Children.Add(gen("身份证号", list_idno));
                        content.Children.Add(gen("客户姓名", list_name));
                        content.Children.Add(gen("发生金额", list_amt));
                        if (page.TradeAPIs.ShowQuestionMessageBox(content, "请确认当前客户信息：", MessageBoxResult.Yes) == MessageBoxResult.Yes)
                        {
                            content.FindVisualTreeChildren(x => x is ComboBox).ForEach(x =>
                            {
                                var comboBox = x as ComboBox;
                                if (comboBox.ItemsSource == list_accno)
                                    record.AccNo = comboBox.GetSelectedValue();
                                else if (comboBox.ItemsSource == list_idno)
                                    record.IdNo = comboBox.GetSelectedValue();
                                else if (comboBox.ItemsSource == list_name)
                                    record.Name = comboBox.GetSelectedValue();
                                else if (comboBox.ItemsSource == list_amt)
                                    record.Amt = comboBox.GetSelectedValue();
                            });
                            break;
                        }
                    }
                    else
                        return;

                } while (true);
            }
            PlatformLogger.SystemInfo("RaiseEvaluation:数据=>" + record.ToString());
            //处理账户喝证件问题，如果账户不为空，证件为空
            if (string.IsNullOrEmpty(record.IdNo.Trim()) && !string.IsNullOrEmpty(record.AccNo.Trim()))
            {
                //var ac = page.TradeAPIs.TF_Deposit_QueryDepositAccount(new QueryDepositAccount.Input()
                //{
                //    ZH = record.AccNo.Trim()
                //});
                //if (!ac.IsFailed)
                //    record.IdNo = ac.ZJH;
                var ac = page.TradeAPIs.TF_Customer_QueryCustomerInformation(new QueryCustomerInformation.Input()
                {
                    ZH = record.AccNo.Trim()
                });
                if (!ac.IsFailed && !string.IsNullOrEmpty(ac.ZJHM.Trim()))
                {
                    record.IdNo = ac.ZJHM.Trim();
                }
            }
            //处理户名问题
            //通过证件号或账号获取户名
            if (string.IsNullOrEmpty(record.Name))
            {
                if (!string.IsNullOrEmpty(record.IdNo.Trim()))//如果证件号不为空，则优先通过证件号去获取户名
                {
                    var khInfo = page.TradeAPIs.TF_Customer_QueryCustomerInformation(new QueryCustomerInformation.Input()
                    {
                        ZJLX = "1",
                        ZJHM = record.IdNo.Trim(),
                    });
                    if (!khInfo.IsFailed && !string.IsNullOrEmpty(khInfo.HM.Trim()))
                    {
                        record.Name = khInfo.HM.Trim();
                    }
                    else//如果通过证件号查询户名失败，则通过账号去获取户名
                    {
                        if (!string.IsNullOrEmpty(record.AccNo.Trim()))
                        {
                            var khInfo1 = page.TradeAPIs.TF_Customer_QueryCustomerInformation(new QueryCustomerInformation.Input()
                            {
                                ZH = record.AccNo.Trim()
                            });
                            if (!khInfo1.IsFailed && !string.IsNullOrEmpty(khInfo1.HM.Trim()))
                            {
                                record.Name = khInfo1.HM.Trim();
                            }
                            else
                            {
                                page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！");
                                return;//取不到户名就不推送
                            }
                        }
                        else
                        {
                            page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！");
                            return;//取不到户名就不推送
                        }
                    }
                }
                else//如果证件号为空，则通过账号去获取户名
                {
                    if (!string.IsNullOrEmpty(record.AccNo.Trim()))
                    {
                        var khInfo1 = page.TradeAPIs.TF_Customer_QueryCustomerInformation(new QueryCustomerInformation.Input()
                        {
                            ZH = record.AccNo.Trim()
                        });
                        if (!khInfo1.IsFailed && !string.IsNullOrEmpty(khInfo1.HM.Trim()))
                        {
                            record.Name = khInfo1.HM.Trim();
                        }
                        else
                        {
                            page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！");
                            return;//取不到户名就不推送
                        }
                    }
                    else
                    {
                        page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！");
                        return;//取不到户名就不推送
                    }
                }
            }
            //处理评价通讯
            Message msg1 = new Message(Message.BitMap.Agn);
            page.InitFd(msg1);
            page.CommSend(msg1);
            msg1.Fd16 = "2021";
            if (!string.IsNullOrEmpty(record.AccNo))
                msg1.Fd20 = "2";//类型 1身份证 2卡号
            else if (!string.IsNullOrEmpty(record.IdNo))
                msg1.Fd20 = "1";//类型 1身份证 2卡号

            msg1.Fd30 = record.IdNo;//身份证号
            msg1.Fd31 = record.AccNo;//卡号
            msg1.Fd28 = LoginUserInfo.TellerNo;//柜员号
            msg1.Fd32 = LoginUserInfo.TellerName;//柜员姓名
            msg1.Fd23 = "3"; //来源方式 1 柜面//应微信银行请求改成3，20210929
            StringBuilder ServerTime = new StringBuilder(TradeHandle.GetServerTime());
            msg1.Fd33 = ServerTime.ToString().Replace("-", "").Replace(":", "").Replace(" ", "");//14位时间
            msg1.Fd29 = LoginUserInfo.KinbrNo;//开户机构
            msg1.Fd25 = page.TradeModel.Name + "(" + page.TradeModel.Code + ")";//业务名称
            msg1.Fd37 = string.IsNullOrEmpty(record.Amt) ? "0.00" : record.Amt;//金额
            msg1.Fd26 = record.Name;///客户姓名
            msg1.Fd24 = "1";//联动礼品  1
            msg1.Fd38 = page.TradeInfo.SerialNumber;//TODO:流水
            //msg1.Fd27 = LoginUserInfo.KinbrName.Contains("前郭县阳光村镇银行") ? LoginUserInfo.KinbrName.Substring(9, LoginUserInfo.KinbrName.Length - 9).Trim() : LoginUserInfo.KinbrName;//机构名
            msg1.Fd27 = LoginUserInfo.KinbrName.Contains("银行") ? LoginUserInfo.KinbrName.Split(new String[] { "银行" }, StringSplitOptions.RemoveEmptyEntries)[1] : LoginUserInfo.KinbrName;
            page.CallAgn(msg1);
            if (msg1.Fd12 != "0000")
            {
                page.TradeAPIs.ShowInfoMessageBox(page.GetError(msg1) + "\n，微信评价推送失败！");

            }
            else
            {
                page.TradeAPIs.ShowInfoMessageBox("微信评价推送成功！");
            }
        }

        /// <summary>
        /// 触发通用的打印流程，包含检查和预处理
        /// </summary>
        /// <param name="page"></param>
        /// <param name="message"></param>
        /// <param name="printList"></param>
        /// <returns></returns>
        public static bool RaisePrint(this PageBase page, Message message, List<PrintContainer> printList)
        {
            //参数检查
            if (page == null || message == null || printList == null) return false;
            //拆解批量打印场景
            var pl = new List<PrintContainer>();
            //if (string.Compare(PageData.TradeAPIs.GetTradeMetadata("isPrintNumber"), "true", true) == 0)
            //    this.PageData.CreatePrintNum(this.PageData.GetTradeInfoData().SystemSerialNumber);
            var printAttr = page.GetPrintAttributes();
            //根据核心返回的是否存在流水  如果不下流水 前台也不创建柜员流水 add by jun 20150514
            if (!string.IsNullOrWhiteSpace(message.Fd4))
            {
                printAttr.SerialNumber = page.CreateTellerSerialNumber(printAttr.SystemSerialNumber);
                //获取PrintAttributes,抓取第四域作为业务流水号
                printAttr.BusinessTransaction = message.Fd4;
                //当业务流水号为无效值，且存在自定义流水号时加载
                if (printAttr.BusinessTransaction == "000000000" && message.CustomizeTransitEntry != null && !string.IsNullOrEmpty(message.CustomizeTransitEntry.SerialNo))
                    printAttr.BusinessTransaction = message.CustomizeTransitEntry.SerialNo;
            }
            //数据加载
            foreach (PrintContainer item in printList)
            {
                PrintContainerExt.SetPrintElement(item, printAttr);
                //采用接口方式的打印项需要进行数据加载
                var printfee = item as IPrintFeeContract;
                var print = item as IPrintContract;
                if (print == null || print.PrintData == null)
                {
                    pl.Add(item);
                }
                else
                {
                    print.PrintData.LoadData(page, message);
                    //此方法由交易定制，容易发生异常，故捕获
                    try
                    {
                        if (item.DocumentId == "TellerSystem.Controls.Ext.PrintsHelper.Print_Fee")
                        {
                            Message msg = new Message();
                            page.TradeAPIs.CommSend(msg);
                            msg.Fd16 = "9550";
                            msg.Fd4 = message.Fd4;
                            page.TradeAPIs.CallServer(msg);
                            printfee.LoadPrint(msg.FileData);
                        }
                        else
                        {
                            print.LoadPrintData();
                        }
                    }
                    catch (Exception ex)
                    {
                        PlatformLogger.SystemErrorInfo("RaisePrintflow:调用LoadPrintData方法发生异常！", ex);
                        //TradeHandle.WriteImportantLog("RaiseDefaultPrint:调用LoadPrintData方法发生异常！", ex.Message + "\n" + ex.StackTrace, this.TradeModel.Code, item.DocumentId, "6", string.Join(",", SocketManager.GetLocalIpAddressList()));
                    }
                    if (print.PrintData.IsBatchPrint)
                    {
                        //批量打印时，需要补充打印属性
                        print.PrintData.BatchList.ForEach(x => { PrintContainerExt.SetPrintElement(x, printAttr); });
                        pl.AddRange(print.PrintData.BatchList);
                    }
                    else
                    {
                        pl.Add(item);
                    }
                }
            }
            //解析打印规则
            var list = page.TradeAPIs.DoPrintLimit(page.TradeModel.Code, pl);
            page.PrintCertificate(list.ToArray());
            return true;
        }
    }
}
