package com.cretin.webservices.service.api.v2.impl

import com.alibaba.excel.EasyExcel
import com.alibaba.excel.context.AnalysisContext
import com.alibaba.excel.metadata.data.ReadCellData
import com.alibaba.excel.read.listener.ReadListener
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.cretin.webcore.exception.WholeException
import com.cretin.webcore.redis.RedisHelper
import com.cretin.webcore.sms.SMSHelper
import com.cretin.webcore.utils.*
import com.cretin.webdb.common.CommonPageResp
import com.cretin.webdb.entity.*
import com.cretin.webdb.mapper.CustomHomeService
import com.cretin.webdb.request.v2.*
import com.cretin.webdb.resp.AdminTranslateListResp
import com.cretin.webdb.self.LocationModel
import com.cretin.webdb.self.ModuleConfigModel
import com.cretin.webdb.service.*
import com.cretin.webservices.helper.*
import com.cretin.webservices.helper.excel.ExcelHelper
import com.cretin.webservices.helper.translate.TranslateNetworkHelper
import com.cretin.webservices.interceptor.UserContextHolder
import com.cretin.webservices.service.api.v2.V2TranslateService
import com.google.gson.reflect.TypeToken
import org.apache.http.util.TextUtils
import org.joda.time.DateTime
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.client.RestTemplate
import org.springframework.web.multipart.MultipartFile
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardCopyOption
import java.time.LocalDateTime
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse


/**
 * Copyright (C), 2015-2021, 电点科技有限公司
 * FileName: AdminExcessServiceImpl
 * Author: cretin
 * Date: 2021/8/23 5:53 下午
 * Description:
 */
@Service
class V2TranslateServiceImpl : V2TranslateService {

    @Autowired
    private var tbV2StrTranslateProjectService: ITbV2StrTranslateProjectService? = null

    @Autowired
    private var tbV2StrTranslateItemService: ITbV2StrTranslateItemService? = null


    @Autowired
    private var tbGlobalConfigService: ITbGlobalConfigService? = null

    @Autowired
    private var redisHelper: RedisHelper? = null

    @Autowired
    private var smsHelper: SMSHelper? = null

    @Autowired
    private var restTemplate: RestTemplate? = null

    @Autowired
    private var tbStrTranslateLogService: ITbStrTranslateLogService? = null

    @Autowired
    private var customHomeService: CustomHomeService? = null

    @Autowired
    private var tbStrTranslateModuleService: ITbStrTranslateModuleService? = null

    @Autowired
    private var globalConfigService: ITbGlobalConfigService? = null

    @Autowired
    private var strTranslateUserService: ITbStrTranslateUserService? = null

    @Transactional
    override fun upload(data: DesktopTranslateAddRequest, httpServletRequest: HttpServletRequest): Any {
        //根据token获取到app_id
        val userId = UserContextHolder.getUserId()
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException(102, "项目不存在")
        if (project.userId != userId) throw WholeException(102, "项目不存在")

        //更新project
        project.projectChannel = data.currentChannel
        project.lastUploadTime = LocalDateTime.now()
        project.channelConfig = GsonGet.getGson().toJson(data.channels)
        val typeV2 = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        val typeV3 = object : TypeToken<MutableList<ModuleConfigModel>?>() {}.type
        val channelConfigNameList = GsonGet.getGson()
            .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(project.channelConfigName, typeV2)
        data.channels?.forEach { channel ->
            if (channelConfigNameList.find { it.channel == channel } == null) {
                channelConfigNameList.add(TranslateChannelUpdateRequest.Item(channel, ""))
            }
        }
        project.channelConfigName = GsonGet.getGson().toJson(channelConfigNameList)
        tbV2StrTranslateProjectService?.updateById(project)

        val deleteWrapper = QueryWrapper<TbV2StrTranslateItem>()
        deleteWrapper.eq("app_id", data.appId)
        deleteWrapper.eq("item_channel", data.currentChannel)
        tbV2StrTranslateItemService?.remove(deleteWrapper)

        //组装数据进行插入
        val items = mutableListOf<TbV2StrTranslateItem>()
        data.items?.forEach {
            val item = TbV2StrTranslateItem()
            item.itemChannel = data.currentChannel
            item.appId = data.appId
            item.itemKey = it.name
            item.itemSource = it.text
            item.itemModule = it.from
            item.addTime = LocalDateTime.now()
            item.updateTime = LocalDateTime.now()
            item.deleteFlag = false
            items.add(item)
        }
        if (data.moduleList == null || data.moduleList?.isEmpty() == true) {
            val moduleConfigList =
                GsonGet.getGson().fromJson<MutableList<ModuleConfigModel>>(project.projectModuleConfig, typeV3)
            if (moduleConfigList.isEmpty()) {
                //直接生成
                val modules =
                    items.filter { it.itemChannel == project.projectChannel }.toMutableList().map { it.itemModule }
                        .toMutableSet()
                project.projectModuleConfig =
                    GsonGet.getGson().toJson(modules.map { ModuleConfigModel(it, true) }.toMutableList())
                tbV2StrTranslateProjectService?.updateById(project)
            } else {
                //有数据了
                val modules =
                    items.filter { it.itemChannel == project.projectChannel }.toMutableList().map { it.itemModule }
                        .toMutableSet()
                modules.forEach {
                    if (moduleConfigList.find { item -> item.module == it } == null) {
                        //新module
                        moduleConfigList.add(ModuleConfigModel(it, true))
                    }
                }
                project.projectModuleConfig = GsonGet.getGson().toJson(moduleConfigList)
                tbV2StrTranslateProjectService?.updateById(project)
            }
        } else {
            moduleConfig(TranslateModuleConfigRequest(project.id, data.moduleList), httpServletRequest)
        }
        tbV2StrTranslateItemService?.saveOrUpdateBatch(items)
        return mutableMapOf<String, String>()
    }

    override fun init(data: DesktopTranslateInitRequest, httpServletRequest: HttpServletRequest): Any {
        val user = UserContextHolder.getUserInfo()
        val it = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        val typeV3 = object : TypeToken<MutableList<LocationModel>?>() {}.type
        val projectLocationConfig =
            GsonGet.getGson().fromJson<MutableList<LocationModel>>(it.projectLocationConfig, typeV3)
        val projectBackupConfig = GsonGet.getGson().fromJson<MutableList<LocationModel>>(it.projectBackupConfig, typeV3)
        val projectLocation = projectLocationConfig?.find { it.uniqueId == data.uniqueId }
        val projectBack = projectBackupConfig?.find { it.uniqueId == data.uniqueId }
        if (projectLocation == null) {
            projectLocationConfig.add(LocationModel().apply {
                location = data.location
                uniqueId = data.uniqueId
            })
        } else {
            projectLocation.location = data.location
        }

        if (projectBack == null) {
            projectBackupConfig.add(LocationModel().apply {
                location = data.backup
                uniqueId = data.uniqueId
            })
        } else {
            projectBack.location = data.backup
        }
        it.projectLocationConfig = GsonGet.getGson().toJson(projectLocationConfig)
        it.projectBackupConfig = GsonGet.getGson().toJson(projectBackupConfig)
        tbV2StrTranslateProjectService?.updateById(it)
        val type = object : TypeToken<MutableList<String>?>() {}.type
        val typeV2 = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        return mutableMapOf<String, Any>().apply {
            put("appId", it.id)
            put("appName", it.projectName)
            put("appMainChannel", it.projectChannel ?: "")
            put("appDesc", it.shortDesc ?: "")
            put("appCreator", user?.nickname ?: "")
            put("appProjectPath", getRealPath(data.uniqueId ?: "", it.projectLocationConfig))
            put("appBackupPath", getRealPath(data.uniqueId ?: "", it.projectBackupConfig))
            put("appPlatform", PlatformHelper.platformMap.get(it.projectPlatform)?.name ?: "")
            put("appPlatformKey", it.projectPlatform ?: "")
            put(
                "appChannelCount", try {
                    GsonGet.getGson().fromJson<MutableList<String>>(it.channelConfig, type).size
                } catch (e: Throwable) {
                    0
                }
            )
            put(
                "channelsName", try {
                    GsonGet.getGson()
                        .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(it.channelConfigName, typeV2)
                } catch (e: Throwable) {
                    mutableListOf()
                }
            )
            put("addTime", DateTime(it.addTime.getMillis()).toString("yyyy-MM-dd HH:mm:ss"))
        }
    }

    override fun list(data: AdminTranslateListRequest, httpServletRequest: HttpServletRequest): Any {
        //获取所有的包列表
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        val type = object : TypeToken<MutableList<String>?>() {}.type
        //项目所有渠道
        val projectChannels = mutableSetOf<String>(project.projectChannel)
        //获取已经隐藏的渠道
        val hideChannels = mutableListOf<String>()
        if (!TextUtils.isEmpty(project.channelConfig)) {
            projectChannels.addAll(GsonGet.getGson().fromJson<MutableList<String>>(project.channelConfig, type))
        }
        if (!TextUtils.isEmpty(project.channelHideConfig)) {
            hideChannels.addAll(GsonGet.getGson().fromJson<MutableList<String>>(project.channelHideConfig, type))
        }

        //所有tab 用于筛选的 需要返回是否可用
        //获取语言配置
        val typeV2 = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        val channelNames = GsonGet.getGson()
            .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(project.channelConfigName, typeV2)
        val allTabs = mutableListOf<AdminTranslateListResp.Tab>()
        //ui上需要展示的所有tab
        val tabs = mutableListOf<AdminTranslateListResp.Tab>()
        tabs.add(AdminTranslateListResp.Tab("item_key", "唯一KEY", true))

        fun getChannelName(channel: String): String {
            val channelModel = channelNames.find { it.channel == channel }
            if (channelModel != null && !TextUtils.isEmpty(channelModel.name)) {
                return channel + "(${channelModel.name})"
            } else {
                return channel
            }
        }

        tabs.add(AdminTranslateListResp.Tab(project.projectChannel, getChannelName(project.projectChannel), true))
        projectChannels.forEach {
            if (it != project.projectChannel) {
                if (!hideChannels.contains(it)) {
                    tabs.add(AdminTranslateListResp.Tab(it, getChannelName(it), true))
                }
                allTabs.add(AdminTranslateListResp.Tab(it, getChannelName(it), !hideChannels.contains(it)))
            }
        }

        //开始查询数据
        fun getQueryConfig(): QueryWrapper<TbV2StrTranslateItem>? {
            val query = QueryWrapper<TbV2StrTranslateItem>()
            query.eq("app_id", data.appId)
            query.eq("delete_flag", false)
            query.orderByDesc("id")

            if (data.translateStatus != 0) {
                //要查询未翻译或者部分翻译的
                //这个key是有部分翻译的
                val allKeysModelList = customHomeService?.getTranslatedKey(
                    data.appId, projectChannels.toMutableList()
                )
                val allKeys = mutableListOf<String>()
                if (data.translateStatus == 1) {
                    //部分翻译
                    allKeys.addAll(allKeysModelList?.filter {
                        val count = it["cnum"].toString().toInt()
                        count > 1 && count < projectChannels.size
                    }?.map { it["item_key"].toString() }?.toMutableList() ?: mutableListOf())
                } else if (data.translateStatus == 2) {
                    //未翻译
                    allKeys?.addAll(allKeysModelList?.filter { it["cnum"].toString().toInt() == 1 }
                        ?.map { it["item_key"].toString() }?.toMutableList() ?: mutableListOf())
                } else if (data.translateStatus == 3) {
                    //翻译完成
                    allKeys?.addAll(allKeysModelList?.filter { it["cnum"].toString().toInt() == projectChannels.size }
                        ?.map { it["item_key"].toString() }?.toMutableList() ?: mutableListOf())
                }
                if (!TextUtils.isEmpty(data.searchContent)) {
                    //需要搜索 这个key是需要被查询出来的
                    if (allKeys.isNotEmpty()) {
                        query.`in`("item_key", allKeys)
                    } else {
                        query.eq("item_key", "")
                    }
                    query.and {
                        if (data.fixSearch) {
                            it.eq("item_source", data.searchContent).or().eq("item_key", data.searchContent)
                        } else {
                            it.like("item_source", data.searchContent).or().like("item_key", data.searchContent)
                        }
                    }
                } else {
                    if (allKeys.isNotEmpty()) {
                        query.`in`("item_key", allKeys)
                    } else {
                        query.eq("item_key", "")
                    }
                    query.eq(
                        "item_channel", project.projectChannel
                    )
                }
            } else {
                if (!TextUtils.isEmpty(data.searchContent)) {
                    query.eq("app_id", data.appId).and {
                        if (data.fixSearch) {
                            it.eq("item_source", data.searchContent).or().eq("item_key", data.searchContent)
                        } else {
                            it.like("item_source", data.searchContent).or().like("item_key", data.searchContent)
                        }
                    }
                } else {
                    query.eq("app_id", data.appId).eq(
                        "item_channel", project.projectChannel
                    )
                }
            }
            return query
        }

        val page = Page<TbV2StrTranslateItem>(data.page.toLong(), 50)
        //查询出所有数据
        val list = tbV2StrTranslateItemService?.page(page, getQueryConfig())

        val allList = tbV2StrTranslateItemService?.list(
            QueryWrapper<TbV2StrTranslateItem>().eq("app_id", data.appId)
        )

        val items = mutableListOf<MutableMap<String, Any>>()

        list?.records?.map { it.itemKey }?.toSet()?.forEach { key ->
            val item = mutableMapOf<String, Any>()
            item["item_key"] = AdminTranslateListResp.ItemChild(key, key)
            projectChannels.forEach { channel ->
                val data = allList?.find { it.itemChannel == channel && it.itemKey == key }
                if (data != null) {
                    val child = AdminTranslateListResp.ItemChild(data.itemSource, data.itemModule)
                    item[channel] = child
                } else {
                    item[channel] = AdminTranslateListResp.ItemChild("", "")
                }
            }
            items.add(item)
        }
        return CommonPageResp<AdminTranslateListResp>(
            page.total.toInt(),
            data.page.toInt(),
            50,
            items,
            extra = AdminTranslateListResp(project.projectChannel, tabs, allTabs)
        )
    }

    override fun channelSelect(data: TranslateChannelConfigRequest, httpServletRequest: HttpServletRequest) {
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        project.channelHideConfig = GsonGet.getGson().toJson(data.channels)
        tbV2StrTranslateProjectService?.updateById(project)
    }

    override fun editTranslate(data: TranslateEditRequest, httpServletRequest: HttpServletRequest) {
        tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")

        val itemOther = tbV2StrTranslateItemService?.list(QueryWrapper<TbV2StrTranslateItem>().apply {
            eq("app_id", data.appId)
            eq("item_key", data.key)
        })?.first()

        val item = tbV2StrTranslateItemService?.getOne(QueryWrapper<TbV2StrTranslateItem>().apply {
            eq("app_id", data.appId)
            eq("item_key", data.key)
            eq("item_channel", data.currentChannel)
        }, false)

        if (TextUtils.isEmpty(data.content)) {
            //置空
            if (item != null) {
                tbV2StrTranslateItemService?.removeById(item)
            }
        } else {
            if (item == null) {
                try {
                    //可能插入失败
                    val itemTemp = TbV2StrTranslateItem()
                    itemTemp.appId = data.appId
                    itemTemp.itemKey = data.key
                    itemTemp.itemModule = itemOther?.itemModule ?: ""
                    itemTemp.itemSource = data.content
                    itemTemp.itemChannel = data.currentChannel
                    itemTemp.updateTime = LocalDateTime.now()
                    itemTemp.addTime = LocalDateTime.now()
                    itemTemp.deleteFlag = false
                    tbV2StrTranslateItemService?.save(itemTemp)
                } catch (e: Throwable) {
                    throw WholeException("更新失败，请稍后再试")
                }
            } else {
                val itemTemp = item
                itemTemp.appId = data.appId
                itemTemp.itemKey = data.key
                itemTemp.itemModule = itemOther?.itemModule ?: ""
                itemTemp.itemSource = data.content
                itemTemp.itemChannel = data.currentChannel
                itemTemp.updateTime = LocalDateTime.now()
                itemTemp.deleteFlag = false
                tbV2StrTranslateItemService?.updateById(itemTemp)
            }
        }
    }

    private fun getRealPath(uniqueId: String, configContent: String): String {
        val typeV3 = object : TypeToken<MutableList<LocationModel>?>() {}.type
        val projectLocationConfig = GsonGet.getGson().fromJson<MutableList<LocationModel>>(configContent, typeV3)
        return projectLocationConfig.find { it.uniqueId == uniqueId }?.location ?: ""
    }

    override fun projectList(data: TranslateProjectListRequest, httpServletRequest: HttpServletRequest): Any {
        val user = UserContextHolder.getUserInfo()
        val userId = user?.id
        val items = mutableListOf<MutableMap<String, Any>>()
        val type = object : TypeToken<MutableList<String>?>() {}.type
        val typeV2 = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        val typeV3 = object : TypeToken<MutableList<ModuleConfigModel>?>() {}.type

        tbV2StrTranslateProjectService?.list(QueryWrapper<TbV2StrTranslateProject>().apply {
            this.eq("user_id", userId)
            this.orderByDesc("id")

        })?.forEach {
            //获取最近上传时间 和 最近更新时间
            var lastEditTime = "无更新"
            val translateLastEdit = tbV2StrTranslateItemService?.list(QueryWrapper<TbV2StrTranslateItem>().apply {
                this.orderByDesc("update_time")
                this.eq("app_id", it.id)
                this.ne("item_channel", it.projectChannel)
                this.last("limit 1")
            })
            if (!translateLastEdit.isNullOrEmpty()) {
                lastEditTime =
                    DateTime(translateLastEdit.first().updateTime.getMillis()).toString("yyyy-MM-dd HH:mm:ss")
            }
            items.add(mutableMapOf<String, Any>().apply {
                put("appId", it.id)
                put("appName", it.projectName)
                put("appMainChannel", it.projectChannel ?: "")
                put("appDesc", it.shortDesc ?: "")
                put("appCreator", user?.nickname ?: "")
                put("appProjectPath", getRealPath(data.unique_id ?: "", it.projectLocationConfig))
                put("appBackupPath", getRealPath(data.unique_id ?: "", it.projectBackupConfig))
                put("appPlatform", PlatformHelper.platformMap.get(it.projectPlatform)?.name ?: "")
                put("appPlatformKey", it.projectPlatform ?: "")
                put(
                    "appChannelCount", try {
                        GsonGet.getGson().fromJson<MutableList<String>>(it.channelConfig, type).size
                    } catch (e: Throwable) {
                        0
                    }
                )
                put(
                    "appModuleConfig", try {
                        GsonGet.getGson().fromJson<MutableList<ModuleConfigModel>>(it.projectModuleConfig, typeV3)
                    } catch (e: Throwable) {
                        mutableListOf<ModuleConfigModel>()
                    }
                )
                put(
                    "channelsName", try {
                        GsonGet.getGson()
                            .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(it.channelConfigName, typeV2)
                    } catch (e: Throwable) {
                        mutableListOf()
                    }
                )
                put("addTime", DateTime(it.addTime.getMillis()).toString("yyyy-MM-dd HH:mm:ss"))
                put(
                    "lastUploadTime",
                    if (it.lastUploadTime != null) DateTime(it.lastUploadTime.getMillis()).toString("yyyy-MM-dd HH:mm:ss") else "未上传"
                )
                put("lastEditTime", lastEditTime)
            })
        }
        return items
    }

    override fun translateAllChannelList(
        data: TranslateChannelListRequest, httpServletRequest: HttpServletRequest
    ): Any {
        val type = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        return GsonGet.getGson()
            .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(project.channelConfigName, type)
    }

    override fun translateAllChannelListUpdate(
        data: TranslateChannelUpdateRequest, httpServletRequest: HttpServletRequest
    ) {
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        project.channelConfigName = GsonGet.getGson().toJson(data.channels)
        tbV2StrTranslateProjectService?.updateById(project)
    }

    override fun projectCreate(data: TranslateProjectCreateRequest, httpServletRequest: HttpServletRequest) {
        val user = UserContextHolder.getUserInfo()
        val projectList = tbV2StrTranslateProjectService?.list(QueryWrapper<TbV2StrTranslateProject>().apply {
            this.eq("project_name", data.name)
            this.eq("user_id", user.id)
        })
        projectList?.removeIf { it.id == data.appId }
        if (projectList?.isEmpty() == false) throw WholeException("项目名称重复")
        val currentProject = tbV2StrTranslateProjectService?.getById(data.appId)
        val project = currentProject ?: TbV2StrTranslateProject()
        if (currentProject != null) {
            project.projectName = data.name
            project.shortDesc = data.desc
            project.updateTime = LocalDateTime.now()
            project.projectPlatform = data.platform
            tbV2StrTranslateProjectService?.updateById(project)
        } else {
            project.projectName = data.name
            project.shortDesc = data.desc
            project.userId = user.id
            project.projectChannel = ""
            project.channelConfig = "[]"
            project.channelHideConfig = "[]"
            project.channelConfigName = "[]"
            project.projectLocationConfig = "[]"
            project.projectBackupConfig = "[]"
            project.projectModuleConfig = "[]"
            project.projectPlatform = data.platform
            project.addTime = LocalDateTime.now()
            project.updateTime = LocalDateTime.now()
            tbV2StrTranslateProjectService?.save(project)
        }

    }

    override fun onlineConvert(data: TranslateOnlineConvertRequest, httpServletRequest: HttpServletRequest): Any {
        val result = mutableMapOf<String, String>()
        val translate =
            TranslateNetworkHelper.getTranslate(restTemplate, data.content, data.from, data.to) ?: throw WholeException(
                "翻译失败"
            )
        result["result"] = translate.result
        return result
    }

    override fun login(data: DesktopTranslateLoginRequest, httpServletRequest: HttpServletRequest): Any {
        val user = selfCheckToken(data.token, strTranslateUserService)
        return mutableMapOf<String, Any>().apply {
            put("token", user.token)
            put("nickname", user.nickname)
        }
    }

    override fun platfroms(httpServletRequest: HttpServletRequest): Any {
        val list = mutableListOf<MutableMap<String, Any>>()
        PlatformHelper.platformMap.forEach { t, u ->
            list.add(mutableMapOf<String, Any>().apply {
                put("key", t)
                put("flag", u.enable)
                put("name", u.name)
            })
        }
        return list
    }

    override fun downloadPre(data: DesktopTranslateListRequest, httpServletRequest: HttpServletRequest): Any {
        //获取所有的包列表
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")

        //所有tab 用于筛选的 需要返回是否可用
        //获取语言配置
        val typeV2 = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        val channelNames = GsonGet.getGson()
            .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(project.channelConfigName, typeV2)
        val allTabs = mutableListOf<AdminTranslateListResp.Tab>()
        //ui上需要展示的所有tab

        fun getChannelName(channel: String): String {
            val channelModel = channelNames.find { it.channel == channel }
            if (channelModel != null && !TextUtils.isEmpty(channelModel.name)) {
                return channel + "(${channelModel.name})"
            } else {
                return channel
            }
        }

        val tabs = mutableListOf<AdminTranslateListResp.Tab>()
        tabs.add(AdminTranslateListResp.Tab("item_key", "唯一KEY", true))

        val allList = tbV2StrTranslateItemService?.list(
            QueryWrapper<TbV2StrTranslateItem>().eq("app_id", data.appId).eq("delete_flag", false)
        )
        //项目所有渠道
        val projectChannels = mutableSetOf<String>(project.projectChannel)

        allList?.forEach {
            projectChannels.add(it.itemChannel)
        }

        projectChannels.forEach { channel ->
            tabs.add(AdminTranslateListResp.Tab(channel, getChannelName(channel), true))
        }

        val items = mutableListOf<MutableMap<String, Any>>()
        allList?.filter { it.itemChannel == project.projectChannel }?.map { it.itemKey }?.apply {
            forEach { key ->
                //判断一下有没有key
                if ((allList.count { it.itemKey == key } ?: 0) > 1) {
                    val item = mutableMapOf<String, Any>()
                    item["item_key"] = AdminTranslateListResp.ItemChild(key, key)
                    projectChannels.forEach { channel ->
                        val data = allList?.find { it.itemChannel == channel && it.itemKey == key }
                        if (data != null) {
                            val child = AdminTranslateListResp.ItemChild(data.itemSource, data.itemModule)
                            item[channel] = child
                        } else {
                            item[channel] = AdminTranslateListResp.ItemChild("", "")
                        }
                    }
                    items.add(item)
                }
            }
        }
        val pageSize = 50
        var laseIndex = (data.page * pageSize).toInt()
        if (items.size < laseIndex) {
            laseIndex = items.size
        }
        return CommonPageResp<AdminTranslateListResp>(
            items.size.toInt(),
            data.page.toInt(),
            pageSize,
            items.subList(((data.page - 1) * pageSize).toInt(), laseIndex),
            extra = AdminTranslateListResp(project.projectChannel, tabs, allTabs)
        )
    }

    override fun projectAsync(data: DesktopTranslateAsyncRequest, httpServletRequest: HttpServletRequest): Any {
        val user = UserContextHolder.getUserInfo()
        val it = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        val type = object : TypeToken<MutableList<String>?>() {}.type
        val typeV2 = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        return mutableMapOf<String, Any>().apply {
            put("appId", it.id)
            put("appName", it.projectName)
            put("appMainChannel", it.projectChannel ?: "")
            put("appDesc", it.shortDesc ?: "")
            put("appCreator", user?.nickname ?: "")
            put("appProjectPath", getRealPath(data.uniqueId ?: "", it.projectLocationConfig))
            put("appBackupPath", getRealPath(data.uniqueId ?: "", it.projectBackupConfig))
            put("appPlatform", PlatformHelper.platformMap.get(it.projectPlatform)?.name ?: "")
            put("appPlatformKey", it.projectPlatform ?: "")
            put(
                "appChannelCount", try {
                    GsonGet.getGson().fromJson<MutableList<String>>(it.channelConfig, type).size
                } catch (e: Throwable) {
                    0
                }
            )
            put(
                "channelsName", try {
                    GsonGet.getGson()
                        .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(it.channelConfigName, typeV2)
                } catch (e: Throwable) {
                    mutableListOf()
                }
            )
            put("addTime", DateTime(it.addTime.getMillis()).toString("yyyy-MM-dd HH:mm:ss"))
        }
    }

    override fun downloadList(data: DesktopTranslateListRequest, httpServletRequest: HttpServletRequest): Any {
        //获取所有的包列表
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        val user = UserContextHolder.getUserInfo()
        if (project.userId != user.id) {
            throw WholeException("项目不存在")
        }
        //获取所有渠道 除了主要渠道
        //查询所有数据

        val allChannels = mutableSetOf<String>()
        val allItems = mutableListOf<MutableMap<String, Any>>()
        val allList = tbV2StrTranslateItemService?.list(QueryWrapper<TbV2StrTranslateItem>().apply {
            eq("app_id", data.appId)
        })

        val ignoreModules =
            allList?.filter { it.itemChannel == project.projectChannel && it.deleteFlag }?.map { it.itemModule }
                ?.toMutableSet()

        allList?.forEach {
            if (it.itemChannel != project.projectChannel) {
                if (ignoreModules?.contains(it.itemModule) == false) {
                    allChannels.add(it.itemChannel)
                    allItems.add(
                        mutableMapOf(
                            "itemKey" to it.itemKey,
                            "itemChannel" to it.itemChannel,
                            "itemSource" to it.itemSource,
                        )
                    )
                }
            }
        }
        return mutableMapOf<String, Any>().apply {
            put("channels", allChannels)
            put("items", allItems)
            put("ignoreModules", ignoreModules ?: mutableSetOf<String>())
        }
    }

    override fun downloadDataConvert(
        data: DesktopTranslateDataConvertRequest, httpServletRequest: HttpServletRequest
    ): Any {
        val items = GsonGet.getGson().fromJson<MutableMap<String, Any>>(data.origin, MutableMap::class.java)
        val newMap = modifyMapKeys(items)
        return newMap
    }

    override fun commonLocalPhpConvertPre(
        data: DesktopTranslateDataConvertRequest, httpServletRequest: HttpServletRequest
    ): Any {
        return PHPFileParserHelper.parserPhpToMap(data.origin, true)!!
    }

    fun handlerMap(
        channel: String, allList: MutableList<TbV2StrTranslateItem>?, pre: String, it: MutableMap<String, Any>
    ) {
        it.forEach { (t, u) ->
            if (u is MutableMap<*, *>) {
                val newKey = if (t.contains("@")) t.split("@").last() else t
                it.remove(t)
                it[newKey] = u
                handlerMap(channel, allList, pre, u as MutableMap<String, Any>)
            } else if (u is ArrayList<*>) {
                val newKey = if (t.contains("@")) t.split("@").last() else t
                it.remove(t)
                it[newKey] = u
                handlerList(channel, allList, pre, u)
            } else if (u is String) {
                val newKey = if (t.contains("@")) t.split("@").last() else t
                it.remove(t)
                val searchKey = "$pre.$t"
                val searchData =
                    allList?.find { it.itemKey == searchKey && it.itemChannel == channel }?.itemSource ?: ""
                if (!TextUtils.isEmpty(searchData)) it[newKey] = searchData
            }
        }
    }

    fun handlerList(
        channel: String, allList: MutableList<TbV2StrTranslateItem>?, pre: String, list: ArrayList<*>
    ) {
        list.forEach {
            if (it is MutableMap<*, *>) {
                handlerMap(channel, allList, pre, it as MutableMap<String, Any>)
            } else if (it is ArrayList<*>) {
                handlerList(channel, allList, pre, it)
            }
        }
    }

    override fun downloadPhpDataConvert(
        data: DesktopTranslatePhpDataConvertRequest, httpServletRequest: HttpServletRequest
    ): Any {
        //这个是php原中文json内容
        val allList = tbV2StrTranslateItemService?.list(QueryWrapper<TbV2StrTranslateItem>().apply {
            eq("app_id", data.appId)
            eq("item_channel", data.channel)
            eq("delete_flag", false)
        })
        val parserMap = PHPFileParserHelper.parserPhpToMap(data.origin, false)
        parserMap.forEach {
            handlerMap(data.channel, allList, data.filePre, it)
        }

//        fun handlerMap(cacheMap:Map<String,Any>?, input: Map<String, Any>): Any {
////            return when (input) {
////                is Map<*, *> -> {
////                    input.mapValues { (key, value) ->
////                        val newKey = if (key.toString().contains("@")) key.toString().split("@").last() else key
////                        handlerMap(value!!).let { newKey to it }
////                    }
////                }
////                is List<*> -> {
////                    input.map { handlerMap(it!!) }
////                }
////                else -> input
////            }
//
//            input.forEach { t, u ->
//                if(u is String){
//                    resultList.add(mutableMapOf( t to u))
//                }else if(u is Map<*,*>){
//
//                    resultList.add(cacheMap)
//                }
//            }
//        }
//
//        val newMap = handlerMap(parserMap!!)
////        replaceList.forEach {
////            removeList.add(handlerRemoveMap(it as LinkedHashMap<String, Any>))
////        }
        return PHPFileParserHelper.createPhpFileContent(parserMap)
    }

    override fun excelExport(data: TranslateExcelExportRequest, httpServletResponse: HttpServletResponse) {
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        val type = object : TypeToken<MutableList<String>?>() {}.type
        //项目所有渠道
        val projectChannels = mutableSetOf<String>(project.projectChannel)
        //获取已经隐藏的渠道
        val hideChannels = mutableListOf<String>()
        if (!TextUtils.isEmpty(project.channelConfig)) {
            projectChannels.addAll(GsonGet.getGson().fromJson<MutableList<String>>(project.channelConfig, type))
        }
        if (!TextUtils.isEmpty(project.channelHideConfig)) {
            hideChannels.addAll(GsonGet.getGson().fromJson<MutableList<String>>(project.channelHideConfig, type))
        }

        //所有tab 用于筛选的 需要返回是否可用
        //获取语言配置
        val typeV2 = object : TypeToken<MutableList<TranslateChannelUpdateRequest.Item>?>() {}.type
        val channelNames = GsonGet.getGson()
            .fromJson<MutableList<TranslateChannelUpdateRequest.Item>>(project.channelConfigName, typeV2)
        val allTabs = mutableListOf<AdminTranslateListResp.Tab>()
        //ui上需要展示的所有tab
        val tabs = mutableListOf<AdminTranslateListResp.Tab>()
        tabs.add(AdminTranslateListResp.Tab("item_key", "唯一KEY", true))

        fun getChannelName(channel: String): String {
            val channelModel = channelNames.find { it.channel == channel }
            if (channelModel != null && !TextUtils.isEmpty(channelModel.name)) {
                return channel + "(${channelModel.name})"
            } else {
                return channel
            }
        }

        tabs.add(AdminTranslateListResp.Tab(project.projectChannel, getChannelName(project.projectChannel), true))
        projectChannels.forEach {
            if (it != project.projectChannel) {
                if (!hideChannels.contains(it)) {
                    tabs.add(AdminTranslateListResp.Tab(it, getChannelName(it), true))
                }
                allTabs.add(AdminTranslateListResp.Tab(it, getChannelName(it), !hideChannels.contains(it)))
            }
        }

        //开始查询数据
        fun getQueryConfig(): QueryWrapper<TbV2StrTranslateItem>? {
            val query = QueryWrapper<TbV2StrTranslateItem>()
            query.eq("app_id", data.appId)
                .eq("delete_flag", false)
                .orderByDesc("id")

            if (data.translateStatus != 0) {
                //要查询未翻译或者部分翻译的
                //这个key是有部分翻译的
                val allKeysModelList = customHomeService?.getTranslatedKey(
                    data.appId, projectChannels.toMutableList()
                )
                val allKeys = mutableListOf<String>()
                if (data.translateStatus == 1) {
                    //部分翻译
                    allKeys.addAll(allKeysModelList?.filter {
                        val count = it["cnum"].toString().toInt()
                        count > 1 && count < projectChannels.size
                    }?.map { it["item_key"].toString() }?.toMutableList() ?: mutableListOf())
                } else if (data.translateStatus == 2) {
                    //未翻译
                    allKeys?.addAll(allKeysModelList?.filter { it["cnum"].toString().toInt() == 1 }
                        ?.map { it["item_key"].toString() }?.toMutableList() ?: mutableListOf())
                } else if (data.translateStatus == 3) {
                    //翻译完成
                    allKeys?.addAll(allKeysModelList?.filter { it["cnum"].toString().toInt() == projectChannels.size }
                        ?.map { it["item_key"].toString() }?.toMutableList() ?: mutableListOf())
                }
                if (allKeys.isNotEmpty()) {
                    query.`in`("item_key", allKeys)
                } else {
                    query.eq("item_key", "")
                }
                query.eq(
                    "item_channel", project.projectChannel
                )
            } else {
                query.eq("app_id", data.appId).eq(
                    "item_channel", project.projectChannel
                )
            }
            return query
        }

        //查询出所有数据
        val list = tbV2StrTranslateItemService?.list(getQueryConfig())

        val allList = tbV2StrTranslateItemService?.list(
            QueryWrapper<TbV2StrTranslateItem>().eq("app_id", data.appId).eq("delete_flag", false)
        )

        val items = mutableListOf<MutableMap<String, Any>>()

        list?.map { it.itemKey }?.toSet()?.forEach { key ->
            val item = mutableMapOf<String, Any>()
            item["item_key"] = AdminTranslateListResp.ItemChild(key, key)
            projectChannels.forEach { channel ->
                val data = allList?.find { it.itemChannel == channel && it.itemKey == key }
                if (data != null) {
                    val child = AdminTranslateListResp.ItemChild(data.itemSource, data.itemModule)
                    item[channel] = child
                } else {
                    item[channel] = AdminTranslateListResp.ItemChild("", "")
                }
            }
            items.add(item)
        }

        val header = mutableListOf<MutableList<String>>()
        val tabIndex = mutableListOf<String>()
        tabs.forEach {
            header.add(mutableListOf(it.label))
            tabIndex.add(it.prop ?: "")
        }
        val dataList = mutableListOf<MutableList<String>>()
        items.forEach { map ->
            dataList.add(mutableListOf<String>().apply {
                tabIndex.forEach {
                    add((map[it] as AdminTranslateListResp.ItemChild).source)
                }
            })
        }

        fun getExportType(): String {
            return when (data.translateStatus) {
                0 -> "导出全部内容"
                1 -> "导出部分翻译"
                2 -> "导出未翻译"
                else -> "导出翻译完成"
            }
        }

        ExcelHelper.exportExcel(
            httpServletResponse,
            project.projectName + "-翻译导出-${PlatformHelper.platformMap.get(project.projectPlatform)?.name}-${getExportType()}-${DateTime.now().toString("yyyy-MM-dd-HH:mm:ss")}",
            project.projectName,
            header,
            dataList
        )
    }

    override fun importExcel(appId: Int, file: MultipartFile, httpServletResponse: HttpServletResponse): Any {
        tbV2StrTranslateProjectService?.getById(appId) ?: throw WholeException("项目不存在")
        // 创建临时文件
        val tempFile: Path =
            Files.createTempFile("uploaded-excel-file-" + DateTime.now().toString("yyyyMMddHHmmss"), ".tmp")
        // 将MultipartFile的内容复制到临时文件
        Files.copy(file.inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING)

        val allList = tbV2StrTranslateItemService?.list(QueryWrapper<TbV2StrTranslateItem>().apply {
            eq("app_id", appId)
            eq("delete_flag", false)
        })

        var header: MutableList<String>? = null
        val updateList = mutableListOf<TbV2StrTranslateItem>()
        val insertList = mutableListOf<TbV2StrTranslateItem>()

        try {
            EasyExcel.read(File(tempFile.toString()), object : ReadListener<LinkedHashMap<*, *>> {
                override fun invoke(p0: LinkedHashMap<*, *>?, p1: AnalysisContext?) {
                    var itemKey = ""
                    p0?.forEach { i, item ->
                        val index = i.toString().toInt()
                        if (index == 0) {
                            //item key
                            itemKey = item?.toString() ?: ""
                        } else {
                            if (!TextUtils.isEmpty(item?.toString() ?: "")) {
                                val channel = header?.get(index) ?: ""
                                val child = allList?.find { it.itemKey == itemKey && it.itemChannel == channel }
                                if (child == null) {
                                    //没有 新增
                                    val child = TbV2StrTranslateItem()
                                    child.updateTime = LocalDateTime.now()
                                    child.addTime = LocalDateTime.now()
                                    child.itemSource = item?.toString() ?: ""
                                    child.appId = appId
                                    child.itemChannel = channel
                                    child.itemKey = itemKey
                                    child.itemModule = "外部excel导入数据"
                                    insertList.add(child)
                                } else {
                                    //更新
                                    child.itemSource = item?.toString() ?: ""
                                    println(child.itemSource)
                                    child.updateTime = LocalDateTime.now()
                                    updateList.add(child)
                                }
                            }
                        }
                    }
                }

                override fun doAfterAllAnalysed(p0: AnalysisContext?) {
                    //更新
                    if (updateList.isNotEmpty()) tbV2StrTranslateItemService?.updateBatchById(updateList)
                    if (insertList.isNotEmpty()) tbV2StrTranslateItemService?.saveBatch(insertList)
                }

                override fun invokeHead(headMap: MutableMap<Int, ReadCellData<*>>?, context: AnalysisContext?) {
                    header = headMap?.values?.map {
                        it.stringValue?.let {
                            if (it.contains("(")) {
                                it.substring(0, it.indexOf("("))
                            } else {
                                it
                            }
                        } ?: ""
                    }?.toMutableList() ?: mutableListOf()
                    if (header?.get(0) != "唯一KEY") {
                        throw WholeException("文件格式不正确")
                    }
                }
            }).build().readAll()
        } catch (e: Throwable) {
            e.printStackTrace()
            throw WholeException("文件格式不正确")
        }
        return mutableMapOf(
            "status" to "ok"
        )
    }

    override fun appInfo(httpServletResponse: HttpServletResponse): Any {
        val list = mutableListOf<MutableMap<String, String>>()
        tbGlobalConfigService?.list(QueryWrapper<TbGlobalConfig>().apply {
            this.between("type", 2, 4)
        })?.forEach {
            list.add(
                mutableMapOf(
                    "url" to it.configExtra1, "version" to it.configDesc, "type" to it.type.toString()
                )
            )
        }
        return list
    }

    override fun commonTips(data: DesktopTranslateTipsRequest, httpServletRequest: HttpServletRequest): Any {
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        var tips = ""
        var header = ""
        var img = ""
        var enable = false
        if ((project.projectPlatform ?: "") == PLATFORM.TYPE_WEB_VUE_I18N.type) {
            enable = true
            header = "语言文件路径：项目根目录/src/locales/lang/zh-CN/xxx.json ，请严格按照此路径进行配置"
            tips =
                "1、项目默认检测zh-CN并将其作为默认语言<br>2、在zh-CN的同级，新建你需要适配的其他语言，如图：en-US，ja<br>3、语言文件仅支持.json后缀<br>4、json文件中支持单层json和多层json，如图所示"
            img = "https://jokes-avatar.cretinzp.com/static/software/translate/pics/vue-i18n.jpg"
        }

        val typeV3 = object : TypeToken<MutableList<ModuleConfigModel>?>() {}.type
        return mutableMapOf(
            "tips" to tips,
            "img" to img,
            "enable" to enable,
            "header" to header,
            "modules" to GsonGet.getGson().fromJson<MutableList<ModuleConfigModel>>(project.projectModuleConfig, typeV3)
        )

    }

    @Transactional
    override fun moduleConfig(data: TranslateModuleConfigRequest, httpServletRequest: HttpServletRequest) {
        val project = tbV2StrTranslateProjectService?.getById(data.appId) ?: throw WholeException("项目不存在")
        if (data?.modules == null || data?.modules?.isEmpty() == true) {

        } else {
            project.projectModuleConfig = GsonGet.getGson().toJson(data.modules)
            tbV2StrTranslateProjectService?.updateById(project)

            val list = tbV2StrTranslateItemService?.list(QueryWrapper<TbV2StrTranslateItem>().apply {
                this.eq("app_id", data.appId)
                this.eq("item_channel", project.projectChannel)
            })

            val updateList = mutableListOf<TbV2StrTranslateItem>()
            list?.forEach { item ->
                val module = data.modules?.find { it.module == item.itemModule }
                if (module != null) {
                    if (module.enable) {
                        item.deleteFlag = false
                    } else {
                        item.deleteFlag = true
                    }
                    updateList.add(item)
                }
            }

            if (updateList.isNotEmpty()) {
                tbV2StrTranslateItemService?.updateBatchById(updateList)
            }
        }
    }

    override fun commonAppUpdate(data: DesktopTranslateAppUpdateRequest, httpServletRequest: HttpServletRequest): Any {
        val type = if (data.platform == "darwin" && data.arch == "arm64") {
            3
        } else if (data.platform == "darwin") {
            2
        } else {
            4
        }
        val update = tbGlobalConfigService?.getOne(QueryWrapper<TbGlobalConfig>().apply {
            this.eq("type", type)
        }, false)

        fun getVersionCode(version: String): Int {
            return version.replace(".", "").toInt()
        }

        if (update == null) {
            return mutableMapOf("flag" to false)
        }

        if (getVersionCode(update.configDesc) > getVersionCode(data.version)) {
            //有新版本
            return mutableMapOf(
                "url" to update.configExtra1,
                "version" to update.configDesc,
                "type" to update.type.toString(),
                "flag" to true
            )
        } else {
            //没有新版本
            return mutableMapOf("flag" to false)
        }
    }
}

fun modifyMapKeys(map: Map<String, Any>): Map<String, Any> {
    return map.mapKeys { (key, value) ->
        if (key.startsWith("__")) {
            "#${key.substring(2)}"
        } else if (key.startsWith("_")) {
            "@${key.substring(1)}"
        } else {
            key
        }
    }.mapValues { (key, value) ->
        when (value) {
            is Map<*, *> -> modifyMapKeys(value as Map<String, Any>)
            is List<*> -> modifyListKeys(value as List<Any>)
            else -> value
        }
    }
}

fun modifyListKeys(list: List<Any>): List<Any> {
    return list.map { item ->
        when (item) {
            is Map<*, *> -> modifyMapKeys(item as Map<String, Any>)
            is List<*> -> modifyListKeys(item as List<Any>)
            else -> item
        }
    }
}


