package com.xjrsoft.module.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.YesOrNoEnum;
import com.xjrsoft.common.exception.MyException;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.config.GeneratePathConfig;
import com.xjrsoft.module.app.dto.AddAppPageDesignDto;
import com.xjrsoft.module.app.dto.UpdateAppPageDesignDto;
import com.xjrsoft.module.app.entity.AppMenu;
import com.xjrsoft.module.app.entity.AppPageDesign;
import com.xjrsoft.module.app.mapper.AppMenuMapper;
import com.xjrsoft.module.app.mapper.AppPageDesignMapper;
import com.xjrsoft.module.app.service.IAppPageDesignService;
import com.xjrsoft.module.generator.utils.GeneratorUtil;
import com.xjrsoft.module.system.entity.DictionaryDetail;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * <p>
 * xjr_data_display【数据展示表】 服务实现类
 * </p>
 *
 * @author hnyyzy
 * @since 2023-06-25
 */
@Service
@AllArgsConstructor
public class AppPageDesignServiceImpl extends ServiceImpl<AppPageDesignMapper, AppPageDesign> implements IAppPageDesignService {

    private final AppMenuMapper appMenuMapper;

    private final GeneratePathConfig generatePathConfig;

    private final RedisUtil redisUtil;


    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Boolean add(AddAppPageDesignDto dto) {
        long count = count(Wrappers.<AppPageDesign>query().lambda().eq(AppPageDesign::getName, dto.getName()));
        if (count > 0) {
            throw new MyException("此数据展示页已经存在！");
        }
        AppPageDesign appPageDesign = BeanUtil.toBean(dto, AppPageDesign.class);

        List<DictionaryDetail> detailList = redisUtil.get(GlobalConstant.DIC_DETAIL_CACHE_KEY, new TypeReference<List<DictionaryDetail>>() {
        });


        if (dto.getIsMenu() == YesOrNoEnum.YES.getCode()) {


            Optional<DictionaryDetail> first = detailList.stream().filter(x -> x.getId().equals(dto.getCategoryId())).findFirst();

            if (!first.isPresent()) {
                throw new MyException("找不到当前功能类别信息！");
            }
            AppMenu appMenu = new AppMenu();
            appMenu.setCode(dto.getCode());
            appMenu.setName(dto.getName());
            appMenu.setIcon(dto.getIcon());
            appMenu.setCategoryId(dto.getCategoryId());
            appMenu.setRemark(dto.getRemark());
            appMenu.setUrl(StringPool.SLASH+"pages"+StringPool.SLASH +first.get().getValue().toLowerCase() + StringPool.SLASH + dto.getCode().toLowerCase());
            appMenuMapper.insert(appMenu);

            appPageDesign.setAppMenuId(appMenu.getId());
            save(appPageDesign);

            //保存成功之后  生成代码
            GeneratorUtil.writeFile(getPageOutputDir(first.get().getValue()), dto.getCode().toLowerCase() + StringPool.DOT + "vue", dto.getPageCode());

            File tempFile = FileUtil.file(generatePathConfig.getAppPath() + StringPool.SLASH + "pages.json");

            JSON jsonContent = JSONUtil.readJSON(tempFile, StandardCharsets.UTF_8);

            Map<String, Object> pageJsonMap = new HashMap<>();
            pageJsonMap.put("path", "pages/" + first.get().getValue().toLowerCase() + StringPool.SLASH + dto.getCode().toLowerCase());
            Map<String, Object> styleMap = new HashMap<>();
            styleMap.put("navigationBarTitleText", dto.getName());
            pageJsonMap.put("style", styleMap);

            JSONArray pages = JSONUtil.parseArray(jsonContent.getByPath("pages").toString());

            pages.add(pageJsonMap);

            jsonContent.putByPath("pages", pages);

            FileUtil.writeString(jsonContent.toJSONString(4), tempFile, StandardCharsets.UTF_8);


        } else {
            save(appPageDesign);

            return Boolean.TRUE;
        }



        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public Boolean modify(UpdateAppPageDesignDto dto) {

        AppPageDesign appPageDesign = BeanUtil.toBean(dto, AppPageDesign.class);


        if (dto.getIsMenu() == YesOrNoEnum.YES.getCode()) {
            List<DictionaryDetail> detailList = redisUtil.get(GlobalConstant.DIC_DETAIL_CACHE_KEY, new TypeReference<List<DictionaryDetail>>() {
            });

            Optional<DictionaryDetail> first = detailList.stream().filter(x -> x.getId().equals(dto.getCategoryId())).findFirst();

            if (!first.isPresent()) {
                throw new MyException("找不到当前功能类别信息！");
            }
            GeneratorUtil.writeFile(getPageOutputDir(first.get().getValue().toLowerCase()), dto.getCode().toLowerCase() + StringPool.DOT + "vue", dto.getPageCode());

            AppMenu appMenu = new AppMenu();
            appMenu.setCode(dto.getCode());
            appMenu.setName(dto.getName());
            appMenu.setIcon(dto.getIcon());
            appMenu.setCategoryId(dto.getCategoryId());
            appMenu.setUrl(StringPool.SLASH+"pages"+StringPool.SLASH +first.get().getValue().toLowerCase() + StringPool.SLASH + dto.getCode().toLowerCase());
            appMenu.setRemark(dto.getRemark());
            //如果发布菜单  menuid 不为空  则需要修改
            if (ObjectUtil.isNotNull(dto.getAppMenuId())) {
                appMenu.setId(dto.getAppMenuId());

                appMenuMapper.updateById(appMenu);


            } else {

                appMenuMapper.insert(appMenu);
            }

//            //保存成功之后  生成代码
//            GeneratorUtil.writeFile(getPageOutputDir(first.get().getValue()), dto.getCode().toLowerCase() + StringPool.DOT + "vue", dto.getPageCode());

            File tempFile = FileUtil.file(generatePathConfig.getAppPath() + StringPool.SLASH + "pages.json");

            JSON jsonContent = JSONUtil.readJSON(tempFile, StandardCharsets.UTF_8);

            //判断page.json里面是否有对应的路径，没有就进行生成
            String path = "pages/" + first.get().getValue().toLowerCase() + StringPool.SLASH + dto.getCode().toLowerCase();

            if (((JSONObject) jsonContent).get("pages").toString().contains(path)){
                JSONArray pages = JSONUtil.parseArray(jsonContent.getByPath("pages").toString());
                for (Object page : pages) {
                    if (page.toString().contains(path) && !page.toString().contains(dto.getName())){//找到这个path路径的值，再判断页面名称是否改变，改变则先移除，再新增
                        pages.remove(page);
                        Map<String, Object> pageJsonMap = new HashMap<>();
                        pageJsonMap.put("path", path);
                        Map<String, Object> styleMap = new HashMap<>();
                        styleMap.put("navigationBarTitleText", dto.getName());
                        pageJsonMap.put("style", styleMap);
                        pages.add(pageJsonMap);
                        jsonContent.putByPath("pages", pages);
                        FileUtil.writeString(jsonContent.toJSONString(4), tempFile, StandardCharsets.UTF_8);
                    }
                }
            }else {
                Map<String, Object> pageJsonMap = new HashMap<>();
                pageJsonMap.put("path", path);
                Map<String, Object> styleMap = new HashMap<>();
                styleMap.put("navigationBarTitleText", dto.getName());
                pageJsonMap.put("style", styleMap);
                JSONArray pages = JSONUtil.parseArray(jsonContent.getByPath("pages").toString());
                pages.add(pageJsonMap);
                jsonContent.putByPath("pages", pages);
                FileUtil.writeString(jsonContent.toJSONString(4), tempFile, StandardCharsets.UTF_8);
            }

            appPageDesign.setAppMenuId(appMenu.getId());

        } else {
            //如果不发布菜单  并且 appmenuId又在  需要删除菜单
            if (ObjectUtil.isNotNull(dto.getAppMenuId())) {
                appMenuMapper.deleteById(dto.getAppMenuId());
            }
        }
        updateById(appPageDesign);
        return Boolean.TRUE;
    }



    /**
     * 获取实体类生成目录
     *
     * @param outputArea
     * @return
     */
    private String getPageOutputDir(String outputArea) {
        return generatePathConfig.getAppPath() + StringPool.SLASH + "pages" + StringPool.SLASH + outputArea.toLowerCase();
    }

}
