import { reactive } from 'vue'
import type { PageBase } from './PageBase'
import type { Message } from './Message'
import type { PrintContainer } from './PrintContainer'
import type { EvaluationRecord } from './EvaluationRecord'
import type { PaymentFeeArguments } from './PaymentFeeArguments'
import { PlatformLogger, TradeHandle } from './LogSystem'
import { ExamSystem } from './ExamSystem'
import { LoginUserInfo } from './UserInfo'

/**
 * 契约执行流程定义
 */
export class ContractManager {
    /**
     * 触发提交流程
     */
    public static RaiseSubmit(page: PageBase): boolean {
        if (page.isSubmitContract) {
            const authdata = new AuthDataHelper(page)
            authdata.ClearAuthData()
            const contract = page as ISubmitContract
            if (!contract || !contract.SubmitEntry) return false
            
            if (contract.SubmitEntry.Submitted) {
                TradeHandle.WriteTraceLog("ContractManager.RaiseSubmit:阻断错误的重复提交！", contract.SubmitEntry.MessageData.Fd16)
                return false
            }

            let message: Message | null = null
            if (!contract.PreviewSubmitting(out message)) return false
            if (!message || message.Fd16 !== page.TradeInfo.MainCode) {
                PlatformLogger.TradeErrorInfo("提交通讯错误：", new Error("提交报文与主交易码不一致，请检查..."))
            }

            const entry = contract.SubmitEntry
            if (!entry || !entry.LoadData(page, message)) return false
            
            if (!this.RaiseRecheck(page, message)) return false             
            if (!this.RaiseAuthorize(page, message)) return false
            if (!this.RaisePaymentFee(page, message)) return false
            if (!entry.RaiseSubmit()) return false
        }
        return true
    }

    /**
     * 触发授权流程
     */
    public static RaiseAuthorize(page: PageBase, message: Message, powerCode = "0"): boolean {
        if (page.isAuthorizeContract) {
            const contract = page as IAuthorizeContract
            if (!contract) return false
            
            if (ExamSystem.Instance.InExamMode) return true
            
            if (page.TradeAPIs.GetTradeMetadata("isAuth") !== "true") return true
            
            if (!contract.AuthorizeEntries || contract.AuthorizeEntries.length === 0) return false

            const entry = contract.AuthorizeEntries.find(x => x.PowerCode === powerCode)
            if (!entry) return false
            
            entry.LoadData(page, message)
            return entry.RaiseAuthorize()
        }
        return true
    }

    /**
     * 触发复核流程
     */
    public static RaiseRecheck(page: PageBase, message: Message, powerCode = "0"): boolean {
        if (page.isRecheckContract) {
            const contract = page as IRecheckContract
            if (!contract) return false
            
            if (ExamSystem.Instance.InExamMode) return true
            
            if (page.TradeAPIs.GetTradeMetadata("isRecheck") !== "true") return true
            
            if (!contract.RecheckEntries || contract.RecheckEntries.length === 0) return false

            const entry = contract.RecheckEntries.find(x => x.PowerCode === powerCode)
            if (!entry) return false
            
            entry.LoadData(page, message)
            return entry.RaiseRecheck()
        }
        return true
    }

    /**
     * 触发收费流程
     */
    public static RaisePaymentFee(page: PageBase, message: Message): boolean {
        if (page.isPaymentFeeContract) {
            const contract = page as IPaymentFeeContract
            if (!contract) return false
            
            if (page.TradeAPIs.GetTradeMetadata("isPaymentFee") !== "true") return true
            
            if (message.TransitNode === TransitType.CallGateway2CBS) {
                PlatformLogger.CommunicationInfo("核心前置通讯不支持收费（TransitType.CallGateway2CBS）")
                return true
            }

            const FLAG = TradeManagerHandle.TT_SYSCONFIG_GetConfigValueByConfigID("2ea3a7e6cfa04f89a335bf1e363295de")
            const filedata = message.FileData
            
            let isPaymentFee = false
            const args = new PaymentFeeArguments(message)
            if (!contract.CheckFee(args, out isPaymentFee)) return false
            
            if (isPaymentFee && !contract.RaisePaymentFee(args)) return false
            
            message.FileData = filedata
        }
        return true
    }

    /**
     * 触发评价流程
     */
    public static RaiseEvaluation(page: PageBase): void {
        const contract = page as IEvaluationContract
        if (!contract) return
        
        if (page.TradeAPIs.GetTradeMetadata("isEvaluation") !== "true") return
        
        const record = new EvaluationRecord()
        if (!contract.PreviewEvaluation(record)) {
            const list_accno = page.PositioningUI(["账／卡号", "账号", "卡    号", "账    号", "结算账号", "账/卡号", "贷款账号", "还款账号", "贷方账号", "记贷付款账号", "借据展示号", "记账账号", "收款人账号", "付款人账号", "签约账号", "账/卡 号", "本行账号", "申请人账号"])
                .filter(x => x[1] instanceof HTMLInputElement)
                .map(x => (x[1] as HTMLInputElement).value)
                .filter((value, index, self) => self.indexOf(value) === index)
                .reduce((acc, curr) => (acc[curr] = curr, acc), {} as Record<string, string>)
            
            const list_idno = page.PositioningUI(["证件号码"])
                .filter(x => x[1] instanceof HTMLInputElement)
                .map(x => (x[1] as HTMLInputElement).value)
                .filter((value, index, self) => self.indexOf(value) === index)
                .reduce((acc, curr) => (acc[curr] = curr, acc), {} as Record<string, string>)
            
            const list_name = page.PositioningUI(["户    名", "户　　名", "客户名称"])
                .filter(x => x[1] instanceof HTMLInputElement)
                .map(x => (x[1] as HTMLInputElement).value)
                .filter((value, index, self) => self.indexOf(value) === index)
                .reduce((acc, curr) => (acc[curr] = curr, acc), {} as Record<string, string>)
            
            const list_amt = page.PositioningUI(["交易金额", "开户金额", "支取金额"])
                .filter(x => x[1] instanceof HTMLInputElement)
                .map(x => (x[1] as HTMLInputElement).value)
                .filter((value, index, self) => self.indexOf(value) === index)
                .reduce((acc, curr) => (acc[curr] = curr, acc), {} as Record<string, string>)
            
            record.AccNo = Object.keys(list_accno).length === 1 ? list_accno[Object.keys(list_accno)[0]] : ''
            record.IdNo = Object.keys(list_idno).length === 1 ? list_idno[Object.keys(list_idno)[0]] : ''
            record.Name = Object.keys(list_name).length === 1 ? list_name[Object.keys(list_name)[0]] : ''
            record.Amt = Object.keys(list_amt).length === 1 ? list_amt[Object.keys(list_amt)[0]] : ''
            
            const gen = (title: string, dict: Record<string, string>): HTMLElement => {
                const line = document.createElement('div')
                line.style.display = 'flex'
                const titleEl = document.createElement('span')
                titleEl.textContent = title
                titleEl.style.width = '120px'
                line.appendChild(titleEl)
                
                const comboBox = document.createElement('select')
                comboBox.style.width = '300px'
                Object.keys(dict).forEach(key => {
                    const option = document.createElement('option')
                    option.value = key
                    option.textContent = dict[key]
                    comboBox.appendChild(option)
                })
                
                comboBox.addEventListener('change', () => {
                    if (dict === list_accno) record.AccNo = comboBox.value
                    else if (dict === list_idno) record.IdNo = comboBox.value
                    else if (dict === list_name) record.Name = comboBox.value
                    else if (dict === list_amt) record.Amt = comboBox.value
                })
                
                line.appendChild(comboBox)
                return line
            }

            do {
                if (Object.keys(list_accno).length >= 1 || Object.keys(list_idno).length >= 1) {
                    const content = document.createElement('div')
                    
                    if (Object.keys(list_accno).length > 0) content.appendChild(gen("银行账号", list_accno))
                    if (Object.keys(list_idno).length > 0) content.appendChild(gen("身份证号", list_idno))
                    if (Object.keys(list_name).length > 0) content.appendChild(gen("客户姓名", list_name))
                    if (Object.keys(list_amt).length > 0) content.appendChild(gen("发生金额", list_amt))
                    
                    if (confirm('请确认当前客户信息：')) {
                        if (Object.keys(list_accno).length > 0) record.AccNo = (content.querySelector('select') as HTMLSelectElement).value
                        if (Object.keys(list_idno).length > 0) record.IdNo = (content.querySelectorAll('select')[1] as HTMLSelectElement).value
                        if (Object.keys(list_name).length > 0) record.Name = (content.querySelectorAll('select')[2] as HTMLSelectElement).value
                        if (Object.keys(list_amt).length > 0) record.Amt = (content.querySelectorAll('select')[3] as HTMLSelectElement).value
                        break
                    }
                } else {
                    return
                }
            } while (true)
        }
        
        PlatformLogger.SystemInfo("RaiseEvaluation:数据=>" + record.toString())
        
        if (!record.IdNo.trim() && record.AccNo.trim()) {
            const ac = page.TradeAPIs.TF_Customer_QueryCustomerInformation({
                ZH: record.AccNo.trim()
            })
            if (!ac.IsFailed && ac.ZJHM.trim()) {
                record.IdNo = ac.ZJHM.trim()
            }
        }
        
        if (!record.Name) {
            if (record.IdNo.trim()) {
                const khInfo = page.TradeAPIs.TF_Customer_QueryCustomerInformation({
                    ZJLX: "1",
                    ZJHM: record.IdNo.trim(),
                })
                if (!khInfo.IsFailed && khInfo.HM.trim()) {
                    record.Name = khInfo.HM.trim()
                } else if (record.AccNo.trim()) {
                    const khInfo1 = page.TradeAPIs.TF_Customer_QueryCustomerInformation({
                        ZH: record.AccNo.trim()
                    })
                    if (!khInfo1.IsFailed && khInfo1.HM.trim()) {
                        record.Name = khInfo1.HM.trim()
                    } else {
                        page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！")
                        return
                    }
                } else {
                    page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！")
                    return
                }
            } else if (record.AccNo.trim()) {
                const khInfo1 = page.TradeAPIs.TF_Customer_QueryCustomerInformation({
                    ZH: record.AccNo.trim()
                })
                if (!khInfo1.IsFailed && khInfo1.HM.trim()) {
                    record.Name = khInfo1.HM.trim()
                } else {
                    page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！")
                    return
                }
            } else {
                page.TradeAPIs.ShowInfoMessageBox("户名抓取失败，微信评价推送失败！")
                return
            }
        }
        
        const msg1 = new Message(Message.BitMap.Agn)
        page.InitFd(msg1)
        page.CommSend(msg1)
        msg1.Fd16 = "2021"
        msg1.Fd20 = record.AccNo ? "2" : record.IdNo ? "1" : ""
        msg1.Fd30 = record.IdNo
        msg1.Fd31 = record.AccNo
        msg1.Fd28 = LoginUserInfo.TellerNo
        msg1.Fd32 = LoginUserInfo.TellerName
        msg1.Fd23 = "3"
        const ServerTime = TradeHandle.GetServerTime().replace(/-|:| /g, "")
        msg1.Fd33 = ServerTime
        msg1.Fd29 = LoginUserInfo.KinbrNo
        msg1.Fd25 = `${page.TradeModel.Name}(${page.TradeModel.Code})`
        msg1.Fd37 = record.Amt || "0.00"
        msg1.Fd26 = record.Name
        msg1.Fd24 = "1"
        msg1.Fd38 = page.TradeInfo.SerialNumber
        msg1.Fd27 = LoginUserInfo.KinbrName.includes("银行") 
            ? LoginUserInfo.KinbrName.split("银行")[1] 
            : LoginUserInfo.KinbrName
        
        page.CallAgn(msg1)
        if (msg1.Fd12 !== "0000") {
            page.TradeAPIs.ShowInfoMessageBox(`${page.GetError(msg1)}\n，微信评价推送失败！`)
        } else {
            page.TradeAPIs.ShowInfoMessageBox("微信评价推送成功！")
        }
    }

    /**
     * 触发通用的打印流程，包含检查和预处理
     */
    public static RaisePrint(page: PageBase, message: Message, printList: PrintContainer[]): boolean {
        if (!page || !message || !printList) return false
        
        const pl: PrintContainer[] = []
        const printAttr = page.GetPrintAttributes()
        
        if (message.Fd4) {
            printAttr.SerialNumber = page.CreateTellerSerialNumber(printAttr.SystemSerialNumber)
            printAttr.BusinessTransaction = message.Fd4
            
            if (printAttr.BusinessTransaction === "000000000" && message.CustomizeTransitEntry?.SerialNo) {
                printAttr.BusinessTransaction = message.CustomizeTransitEntry.SerialNo
            }
        }
        
        for (const item of printList) {
            PrintContainerExt.SetPrintElement(item, printAttr)
            
            const printfee = item as IPrintFeeContract
            const print = item as IPrintContract
            
            if (!print || !print.PrintData) {
                pl.push(item)
            } else {
                print.PrintData.LoadData(page, message)
                
                try {
                    if (item.DocumentId === "TellerSystem.Controls.Ext.PrintsHelper.Print_Fee") {
                        const 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 (ex) {
                    PlatformLogger.SystemErrorInfo("RaisePrintflow:调用LoadPrintData方法发生异常！", ex)
                }
                
                if (print.PrintData.IsBatchPrint) {
                    print.PrintData.BatchList.forEach(x => PrintContainerExt.SetPrintElement(x, printAttr))
                    pl.push(...print.PrintData.BatchList)
                } else {
                    pl.push(item)
                }
            }
        }
        
        const list = page.TradeAPIs.DoPrintLimit(page.TradeModel.Code, pl)
        page.PrintCertificate(list)
        return true
    }
}

// Vue组件封装
export const useContractManager = () => {
    return reactive({
        RaiseSubmit: ContractManager.RaiseSubmit,
        RaiseAuthorize: ContractManager.RaiseAuthorize,
        RaiseRecheck: ContractManager.RaiseRecheck,
        RaisePaymentFee: ContractManager.RaisePaymentFee,
        RaiseEvaluation: ContractManager.RaiseEvaluation,
        RaisePrint: ContractManager.RaisePrint
    })
}