/**
 * 模型参数配置端到端测试
 * 测试完整的用户操作流程：加载 → 修改 → 保存
 */

import { mount } from '@vue/test-utils'
import { expect } from 'chai'
import sinon from 'sinon'
import ModelParam from '@/views/ccdi/modelParam/index.vue'
import * as modelParamApi from '@/api/ccdi/modelParam'

describe('模型参数配置 - 端到端测试', () => {
  let wrapper
  let sandbox

  beforeEach(() => {
    sandbox = sinon.createSandbox()
  })

  afterEach(() => {
    sandbox.restore()
    if (wrapper) {
        wrapper.destroy()
    }
  })

  describe('场景1: 页面加载和显示', () => {
    it('应该显示加载状态', async () => {
        // 模拟API延迟
        const loadStub = sandbox.stub(modelParamApi, 'listAllParams')
            .returns(new Promise(resolve => setTimeout(resolve, 100)))

        wrapper = mount(ModelParam)

        // 验证loading状态
        expect(wrapper.vm.loading).to.be.true
        expect(wrapper.find('.el-loading-mask').exists()).to.be.true
    })

    it('应该成功加载所有模型参数', async () => {
        // Mock数据
        const mockData = {
            code: 200,
            data: {
                models: [
                    {
                        modelCode: 'LARGE_TRANSACTION',
                        modelName: '大额交易模型',
                        params: [
                            {
                                paramCode: 'THRESHOLD_AMOUNT',
                                paramName: '单笔交易金额阈值',
                                paramDesc: '单笔交易金额超过此值触发预警',
                                paramValue: '50000',
                                paramUnit: '元'
                            },
                            {
                                paramCode: 'DAILY_LIMIT',
                                paramName: '日累计金额阈值',
                                paramDesc: '单日累计金额超过此值触发预警',
                                paramValue: '100000',
                                paramUnit: '元'
                            }
                        ]
                    },
                    {
                        modelCode: 'SUSPICIOUS_FOREIGN_EXCHANGE',
                        modelName: '可疑外汇交易模型',
                        params: [
                            {
                                paramCode: 'FOREIGN_AMOUNT',
                                paramName: '外汇交易金额阈值',
                                paramDesc: '外汇交易金额超过此值触发预警',
                                paramValue: '10000',
                                paramUnit: '美元'
                            }
                        ]
                    }
                ]
            }
        }

        sandbox.stub(modelParamApi, 'listAllParams')
            .resolves(mockData)

        wrapper = mount(ModelParam)
        await wrapper.vm.$nextTick()

        // 等待加载完成
        await new Promise(resolve => setTimeout(resolve, 50))

        // 验证数据加载
        expect(wrapper.vm.loading).to.be.false
        expect(wrapper.vm.modelGroups).to.have.lengthOf(2)
        expect(wrapper.vm.modelGroups[0].modelCode).to.equal('LARGE_TRANSACTION')
        expect(wrapper.vm.modelGroups[1].modelCode).to.equal('SUSPICIOUS_FOREIGN_EXCHANGE')
    })

    it('应该显示空状态提示当无数据时', async () => {
        sandbox.stub(modelParamApi, 'listAllParams')
            .resolves({ code: 200, data: { models: [] } })

        wrapper = mount(ModelParam)
        await wrapper.vm.$nextTick()
        await new Promise(resolve => setTimeout(resolve, 50))

        // 验证空状态
        expect(wrapper.vm.modelGroups).to.have.lengthOf(0)
        expect(wrapper.find('.empty-state').exists()).to.be.true
        expect(wrapper.text()).to.include('暂无参数配置数据')
    })

    it('应该显示错误信息当加载失败时', async () => {
        const errorMsg = '网络请求失败'
        sandbox.stub(modelParamApi, 'listAllParams')
            .rejects(new Error(errorMsg))

        const messageSpy = sandbox.spy()

        wrapper = mount(ModelParam, {
            mocks: {
                $message: {
                    error: messageSpy
                }
            }
        })

        await wrapper.vm.$nextTick()
        await new Promise(resolve => setTimeout(resolve, 50))

        // 验证错误处理
        expect(messageSpy.calledOnce).to.be.true
        expect(messageSpy.firstCall.args[0]).to.include('加载参数失败')
    })
  })

  describe('场景2: 参数修改追踪', () => {
    beforeEach(async () => {
        const mockData = {
            code: 200,
            data: {
                models: [
                    {
                        modelCode: 'LARGE_TRANSACTION',
                        modelName: '大额交易模型',
                        params: [
                            {
                                paramCode: 'THRESHOLD_AMOUNT',
                                paramName: '单笔交易金额阈值',
                                paramValue: '50000',
                                paramUnit: '元'
                            }
                        ]
                    }
                ]
            }
        }

        sandbox.stub(modelParamApi, 'listAllParams')
            .resolves(mockData)

        wrapper = mount(ModelParam)
        await wrapper.vm.$nextTick()
        await new Promise(resolve => setTimeout(resolve, 50))
    })

    it('应该正确追踪单个参数修改', () => {
        const row = wrapper.vm.modelGroups[0].params[0]

        // 修改参数
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row)

        // 验证修改记录
        expect(wrapper.vm.modifiedParams['LARGE_TRANSACTION']).to.exist
        expect(wrapper.vm.modifiedParams['LARGE_TRANSACTION'].has('THRESHOLD_AMOUNT')).to.be.true
        expect(wrapper.vm.modifiedCount).to.equal(1)
    })

    it('应该正确追踪多个参数修改', () => {
        const row1 = wrapper.vm.modelGroups[0].params[0]

        // 修改参数多次
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row1)
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row1) // 重复修改

        // 验证只记录一次
        expect(wrapper.vm.modifiedCount).to.equal(1)
    })

    it('应该正确计算修改数量', async () => {
        // 添加第二个参数
        wrapper.vm.modelGroups[0].params.push({
            paramCode: 'DAILY_LIMIT',
            paramName: '日累计金额阈值',
            paramValue: '100000',
            paramUnit: '元'
        })

        const row1 = wrapper.vm.modelGroups[0].params[0]
        const row2 = wrapper.vm.modelGroups[0].params[1]

        // 修改两个不同参数
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row1)
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row2)

        // 验证修改数量
        expect(wrapper.vm.modifiedCount).to.equal(2)
    })
  })

  describe('场景3: 保存功能', () => {
    beforeEach(async () => {
        const mockData = {
            code: 200,
            data: {
                models: [
                    {
                        modelCode: 'LARGE_TRANSACTION',
                        modelName: '大额交易模型',
                        params: [
                            {
                                paramCode: 'THRESHOLD_AMOUNT',
                                paramName: '单笔交易金额阈值',
                                paramValue: '50000',
                                paramUnit: '元'
                            }
                        ]
                    }
                ]
            }
        }

        sandbox.stub(modelParamApi, 'listAllParams')
            .resolves(mockData)

        wrapper = mount(ModelParam)
        await wrapper.vm.$nextTick()
        await new Promise(resolve => setTimeout(resolve, 50))
    })

    it('应该拒绝保存当无修改时', async () => {
        const messageSpy = sandbox.spy()

        wrapper.vm.$message = {
            info: messageSpy
        }

        // 尝试保存（未修改）
        await wrapper.vm.handleSaveAll()

        // 验证提示
        expect(messageSpy.calledOnce).to.be.true
        expect(messageSpy.firstCall.args[0]).to.include('没有需要保存的修改')
    })

    it('应该成功保存修改', async () => {
        // Mock保存接口
        sandbox.stub(modelParamApi, 'saveAllParams')
            .resolves({ code: 200, msg: '操作成功' })

        const messageSpy = sandbox.spy()
        wrapper.vm.$message = { success: messageSpy }
        wrapper.vm.$modal = { msgSuccess: messageSpy }

        // 修改参数
        const row = wrapper.vm.modelGroups[0].params[0]
        row.paramValue = '60000'
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row)

        // 保存
        await wrapper.vm.handleSaveAll()

        // 验证保存成功
        expect(messageSpy.called).to.be.true
        expect(wrapper.vm.modifiedCount).to.equal(0) // 清空修改记录
    })

    it('应该显示错误当保存失败时', async () => {
        const errorMsg = '保存失败：参数值不能为空'
        sandbox.stub(modelParamApi, 'saveAllParams')
            .rejects({
                response: {
                    data: { msg: '参数值不能为空' }
                }
            })

        const messageSpy = sandbox.spy()
        wrapper.vm.$message = { error: messageSpy }

        // 修改参数
        const row = wrapper.vm.modelGroups[0].params[0]
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row)

        // 尝试保存
        await wrapper.vm.handleSaveAll()

        // 验证错误提示
        expect(messageSpy.calledOnce).to.be.true
        expect(messageSpy.firstCall.args[0]).to.include('保存失败')
    })

    it('应该设置saving状态当保存中', async () => {
        // Mock延迟保存
        sandbox.stub(modelParamApi, 'saveAllParams')
            .returns(new Promise(resolve => setTimeout(() => resolve({ code: 200 }), 100)))

        // 修改参数
        const row = wrapper.vm.modelGroups[0].params[0]
        wrapper.vm.markAsModified('LARGE_TRANSACTION', row)

        // 开始保存（不等待）
        const savePromise = wrapper.vm.handleSaveAll()

        // 验证saving状态
        expect(wrapper.vm.saving).to.be.true

        // 等待保存完成
        await savePromise

        // 验证saving状态恢复
        expect(wrapper.vm.saving).to.be.false
    })
  })

  describe('场景4: 边界情况', () => {
    it('应该处理空projectId', async () => {
        const loadStub = sandbox.stub(modelParamApi, 'listAllParams')
            .resolves({ code: 200, data: { models: [] } })

        wrapper = mount(ModelParam)
        await wrapper.vm.$nextTick()

        // 验证默认projectId为0
        expect(loadStub.firstCall.args[0]).to.deep.equal({ projectId: 0 })
    })

    it('应该处理API返回异常数据结构', async () => {
        sandbox.stub(modelParamApi, 'listAllParams')
            .resolves({ code: 200 }) // 缺少data字段

        wrapper = mount(ModelParam)
        await wrapper.vm.$nextTick()
        await new Promise(resolve => setTimeout(resolve, 50))

        // 验证容错处理
        expect(wrapper.vm.modelGroups).to.deep.equal([])
    })

    it('应该处理参数值为null或undefined', async () => {
        const mockData = {
            code: 200,
            data: {
                models: [
                    {
                        modelCode: 'TEST_MODEL',
                        modelName: '测试模型',
                        params: [
                            {
                                paramCode: 'TEST_PARAM',
                                paramName: '测试参数',
                                paramValue: null,
                                paramUnit: '个'
                            }
                        ]
                    }
                ]
            }
        }

        sandbox.stub(modelParamApi, 'listAllParams')
            .resolves(mockData)

        wrapper = mount(ModelParam)
        await wrapper.vm.$nextTick()
        await new Promise(resolve => setTimeout(resolve, 50))

        // 验证数据加载
        expect(wrapper.vm.modelGroups).to.have.lengthOf(1)
        expect(wrapper.vm.modelGroups[0].params[0].paramValue).to.be.null
    })
  })
})
