import { reactive, ref } from 'vue'
import { PrintflowEntry } from './PrintflowEntry'
import type { PageBase } from '../ContractBase/PageBase'
import type { Message } from '../Communication/Message'
import type { PrintContainer } from '../../Platform/Print/PrintContainer'
import { LoginAuthentication } from '../Library/Ext/Function/LoginAuthentication'
import { ContractManager } from '../Contracts/ContractManager'
import { PlatformLogger } from '../../Platform/Common/LogSystem'
import { ExamSystem } from '../ServiceProxy/Ext/ServiceHelper/ExamSystem'
import { AuthDataHelper } from '../ContractBase/AuthDataHelper'
import { CheckDataHelper } from '../ContractBase/CheckDataHelper'
import { TradeHandle } from '../Library/Ext/TradeExtension/TradeHandle'
import { SocketManager } from '../Communication/SocketListener/SocketManager'
import { WorkFlowHandle } from '../ServiceProxy/Ext/ServiceHelper/WorkFlowHandle'
import { LoginUserInfo } from '../Models/UserInfo'

/**
 * 提交逻辑入口(抽象类)
 */
export abstract class SubmitEntry extends PrintflowEntry {
    private _submitted = ref(false)
    private _morePrintList: PrintContainer[] = []
    private _flag2Finally = false
    private static _counter = 0

    /**
     * 提交标识，当提交成功后将变为true
     */
    public get Submitted(): boolean {
        return this._submitted.value
    }
    private set Submitted(value: boolean) {
        this._submitted.value = value
    }

    /**
     * 是否自定义检测通讯返包
     */
    public IsCustomizeVerify = false

    /**
     * 更多的打印数据
     */
    public get MorePrintList(): PrintContainer[] {
        return this._morePrintList
    }

    /**
     * 执行提交流程
     */
    public RaiseSubmit(): boolean {
        if (!this.MessageData || !this.PageData || this.Submitted) return false

        const serialNumber = this.PageData.CreateSerialNumber()
        if (!serialNumber) return false

        if (serialNumber.length > 8) {
            this.MessageData.Fd96_Q = serialNumber.substring(8)
        }

        const authdata = new AuthDataHelper(this.PageData)
        const checkdata = new CheckDataHelper(this.PageData)

        if (checkdata.SuperTeller) {
            this.MessageData.Fd8 = checkdata.SuperTeller
        }

        if (authdata.AuthTeller) {
            this.MessageData.Fd9_1 = authdata.AuthTeller
        }

        this.MessageData.Fd14 = this.PageData.TradeModel.Code

        // 考试系统相关处理
        let sendMessage = ''
        if (ExamSystem.Instance.InExamMode) {
            sendMessage = ExamSystem.Instance.KGetMessageString(this.MessageData, "发送")
        }

        this.MessageData.SerialNumber = this.TradeInfo.SystemSerialNumber
        if (!this.StashPrintData()) return false

        const flag = this.PageData.DoTransit(this.MessageData)
        this.MessageData.SerialNumber = ''

        // 考试系统相关处理
        if (ExamSystem.Instance.InExamMode) {
            const receiveMessage = ExamSystem.Instance.KGetMessageString(this.MessageData, "返回")
            ExamSystem.Instance.SendExamData(
                sendMessage, 
                receiveMessage, 
                this.TradeInfo.TradeCode, 
                this.TradeInfo.SystemSerialNumber || ''
            )
        }

        if (this.IsCustomizeVerify) {
            if (!this.SubmitComplete()) return false
        } else {
            if (!flag) {
                this.TradeAPIs.ShowWarnMessageBox("提交交易不成功, 为了避免重复提交\n请查看该笔业务流程是否已经完成!")
                PlatformLogger.TradeInfo(`提交交易不成功,为了避免重复提交</n>请主动去查看该笔业务流程是否已经完成!\n前端流水号：${serialNumber}\n操作柜员:${this.MessageData.Fd7}`)
                TradeHandle.WriteImportantLog(
                    `${serialNumber}提交交易无法确认状态`, 
                    "通讯返回false，请检查网络", 
                    this.PageData.TradeModel.Code, 
                    "RaiseSubmit", 
                    "1", 
                    SocketManager.GetLocalIpAddressList().join(',')
                )
                this.PageData.Close()
                return false
            }
            if (!this.AutoVerify()) return false
            try {
                this.SubmitComplete()
            } catch (ex) {
                PlatformLogger.SystemErrorInfo("SubmitEntry.RaiseSubmit方法，执行SubmitComplete发生异常！", ex)
            }
        }

        try {
            if (!new RegExp(ServiceProxy.Ext.ServiceSettings.GetConfig("SkipFlagSubmitted", "none")).test(this.PageData.TradeInfo.TradeCode)) {
                this.Submitted = true
            }

            this.PageData.TradeBus.RecvMessage = this.MessageData
            this.PageData.TradeBus.PageAction = this.PageData.constructor.name

            this.UploadData()
            this.RaiseCallbackDescription()
            
            this.PageData.PagePrinted = this.PageData_PagePrinted
            this.RaisePrint()
        } catch (ex) {
            this.TradeAPIs.ShowInfoMessageBox(`提交交易成功，解析返回数据出错，错误信息:\n${ex.message}`)
            const msgLog = this.GetMessageString(this.MessageData)
            PlatformLogger.SystemErrorInfo(`提交交易成功，解析返回数据出错\n***************************************************\n${msgLog}\n`, ex)
            TradeHandle.WriteImportantLog(
                `${serialNumber}提交交易成功，解析返回数据出错`, 
                `${ex.message}\n${ex.stack}`, 
                this.PageData.TradeModel.Code, 
                "RaiseSubmit", 
                "1", 
                SocketManager.GetLocalIpAddressList().join(',')
            )
        }

        this.PageData_PagePrinted(null, null)
        this.TradeCompleted()
        
        authdata.AuthTeller = ''
        authdata.AuthTeller2 = ''
        checkdata.SuperTeller = ''
        this.PageData.ClearSerialNumber()
        TradeInfoData.GetTradeInfo(this.PageData).SerialNumber = ''
        
        return true
    }

    /**
     * 自动检测通讯返包
     */
    private AutoVerify(): boolean {
        if (this.MessageData.Fd12 !== "0000") {
            this.PageData.TradeAPIs.ShowErrorMessageBox(this.PageData.GetError(this.MessageData))
            return false
        }
        return true
    }

    /**
     * 执行打印流程
     */
    public RaisePrint(): boolean {
        if (this.PageData instanceof ISubmitContract) {
            return this.RaisePrintflow(false)
        }

        let printList: PrintContainer[] | null = null
        try {
            if (!this.CreatePrintList(printList)) {
                TradeHandle.WriteImportantLog(
                    "SubmitEntry.RaisePrint方法，调用CreatePrintList方法失败！", 
                    this.MessageData.FileData, 
                    this.PageData.TradeModel.Code, 
                    "RaiseSubmit", 
                    "5", 
                    SocketManager.GetLocalIpAddressList().join(',')
                )
            }
        } catch (ex) {
            PlatformLogger.SystemErrorInfo("SubmitEntry.RaisePrint方法，调用CreatePrintList方法发生异常！", ex)
            this.PageData.ShowErrorMessageBox("产生凭证打印清单失败！请检查完整性...")
            TradeHandle.WriteImportantLog(
                "SubmitEntry.RaisePrint方法，调用CreatePrintList方法发生异常！", 
                `${ex.message}\n${ex.stack}`, 
                this.PageData.TradeModel.Code, 
                "RaiseSubmit", 
                "5", 
                SocketManager.GetLocalIpAddressList().join(',')
            )
        }

        if (!printList) printList = []
        printList.push(...this.MorePrintList)
        if (printList.length === 0) return true
        
        return ContractManager.RaisePrint(this.PageData, this.MessageData, printList)
    }

    private PageData_PagePrinted(sender: any, e: any): void {
        this.PageData.Log2PagePrinted(`触发finally${this._flag2Finally}`)
        this.PageData.PagePrinted = null
        if (this._flag2Finally) return
        this._flag2Finally = true
        this.Finally()
    }

    private GetMessageString(msg: Message): string {
        const props = Object.getOwnPropertyNames(msg)
        let strText = ''
        
        props.filter(p => p.startsWith('Fd')).forEach(p => {
            const val = msg[p].toString().trim().replace(/\r|\n/g, '')
            if (val) {
                strText += `[${p}=${val}]\n`
            }
        })
        
        return strText
    }

    private UploadData(): void {
        try {
            const tradeInfo = {
                TellerNo: LoginUserInfo.TellerNo,
                TradeNo: this.PageData.TradeModel.Code,
                Tlrlvl: "",
                BrNo: LoginUserInfo.KinbrNo,
                Status: 1,
                BlackSerialNo2: this.MessageData.CustomizeTransitEntry?.SerialNo || this.MessageData.Fd126_1,
                BlackSerialNo: this.MessageData.Fd4,
                TradeFileName: this.constructor.name,
                BusinessDate: LoginUserInfo.TradeDate
            }

            const authdata = new AuthDataHelper(this.PageData)
            const checkdata = new CheckDataHelper(this.PageData)
            let pageData: Uint8Array = new Uint8Array()
            
            if (checkdata.SuperTeller || authdata.AuthTeller) {
                pageData = this.PageData.SaveTradePage(this.PageData.Content)
            }

            const tradeBus = TradeInfoData.GetTradeInfo(this.PageData).TradeBus.Serialize()
            const serialNumber = this.PageData.CreateSerialNumber()

            setTimeout(() => {
                try {
                    WorkFlowHandle.GetWorkFlowTradeSubmit(
                        tradeInfo,
                        pageData,
                        tradeBus,
                        "",
                        serialNumber,
                        false,
                        true
                    )
                } catch (e) {
                    TradeHandle.WriteImportantLog(
                        "UploadData",
                        `${e.message}\n${e.stack}`,
                        "GetWorkFlowTradeSubmitException",
                        "0",
                        SocketManager.GetLocalIpAddressList().join(',')
                    )
                }
            }, 0)
        } catch (ex) {
            PlatformLogger.SystemErrorInfo("SubmitEntry.UploadData方法，上载交易数据发生异常！", ex)
        }
    }

    private RaiseCallbackDescription(): void {
        let displayDesc: Record<string, string> | null = null
        
        try {
            displayDesc = this.CreateDisplayDescription()
        } catch (ex) {
            PlatformLogger.SystemErrorInfo("SubmitEntry.RaiseCallbackDescription方法，创建回显要素集合发生异常！", ex)
        }

        if (!displayDesc) {
            this.TradeAPIs.ShowSuccessMessageBox()
        } else {
            // Vue中实现类似WPF的WrapPanel和BulletDecorator效果
            // 这里需要根据实际UI框架实现对应组件
            const wrapper = document.createElement('div')
            wrapper.style.display = 'flex'
            wrapper.style.flexWrap = 'wrap'
            wrapper.style.gap = '10px'
            
            Object.entries(displayDesc).forEach(([key, value]) => {
                const item = document.createElement('div')
                item.style.display = 'flex'
                item.style.alignItems = 'center'
                item.style.minWidth = '350px'
                
                const bullet = document.createElement('span')
                bullet.textContent = `${key}:`
                bullet.style.marginRight = '5px'
                
                const content = document.createElement('span')
                content.textContent = value
                
                item.appendChild(bullet)
                item.appendChild(content)
                wrapper.appendChild(item)
            })

            this.TradeAPIs.ShowSuccessMessageBox(wrapper)
        }
    }

    public TradeCompleted(): boolean {
        SubmitEntry._counter++
        if (SubmitEntry._counter % ServiceSettings.GetConfig("PrinterLoop", 99999) === 0) {
            // 浏览器环境下无法直接操作进程，这里需要根据实际环境调整
            console.log('Printer process cleanup triggered')
        }

        if (this.PageData.TradeAPIs.GetTradeMetadata("isClosePage")?.toLowerCase() === "true") {
            this.PageData.OpenPage(this.PageData.TradeModel.Action, null)
        } else {
            this.PageData.Close()
        }

        return true
    }

    public override GeneratePrintList(): PrintContainer[] {
        let printList: PrintContainer[] | null = null
        
        try {
            if (!this.CreatePrintList(printList)) {
                TradeHandle.WriteImportantLog(
                    "SubmitEntry.RaisePrint方法，调用CreatePrintList方法失败！",
                    this.MessageData.FileData,
                    this.PageData.TradeModel.Code,
                    "RaiseSubmit",
                    "5",
                    SocketManager.GetLocalIpAddressList().join(',')
                )
            }
        } catch (ex) {
            PlatformLogger.SystemErrorInfo("SubmitEntry.RaisePrint方法，调用CreatePrintList方法发生异常！", ex)
            this.TradeAPIs.ShowErrorMessageBox("产生凭证打印清单失败！请检查完整性...")
            TradeHandle.WriteImportantLog(
                "SubmitEntry.RaisePrint方法，调用CreatePrintList方法发生异常！",
                `${ex.message}\n${ex.stack}`,
                this.PageData.TradeModel.Code,
                "RaiseSubmit",
                "5",
                SocketManager.GetLocalIpAddressList().join(',')
            )
        }

        if (!printList) printList = []
        printList.push(...this.MorePrintList)
        return printList
    }

    public override PreviewPrintflow(): boolean {
        return true
    }

    /**
     * 提交完毕，并验证结果
     */
    public abstract SubmitComplete(): boolean

    /**
     * 流程处理结束，执行后续操作
     */
    public abstract Finally(): boolean

    /**
     * 创建打印列表
     */
    public abstract CreatePrintList(outList: PrintContainer[] | null): boolean

    /**
     * 创建回显要素集合
     */
    public CreateDisplayDescription(): Record<string, string> | null {
        return null
    }
}

// Vue组合式API封装
export const useSubmitEntry = () => {
    return {
        SubmitEntry
    }
}