package com.microservices.cms.project.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.microservices.cms.doc.domain.CmsDir;
import com.microservices.cms.doc.domain.CmsDocBaseDto;
import com.microservices.cms.doc.domain.CmsDocSearchVo;
import com.microservices.cms.doc.service.ICmsAsyncService;
import com.microservices.cms.doc.service.ICmsDocService;
import com.microservices.cms.project.domain.CmsProject;
import com.microservices.cms.project.mapper.CmsProjectMapper;
import com.microservices.cms.project.service.ICmsProjectService;
import com.microservices.cms.utils.CmsGitLinkRequestUrl;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.enums.SystemRole;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.PinYinStringUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.datascope.annotation.DataScope;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.system.api.RemoteDeptService;
import com.microservices.system.api.RemoteUserService;
import com.microservices.system.api.domain.SysDept;
import com.microservices.system.api.domain.SysRole;
import com.microservices.system.api.domain.SysUser;
import com.microservices.system.api.utils.FeignUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 专区对应项目Service业务层处理
 *
 * @author otto
 * @date 2023-03-27
 */
@Service
public class CmsProjectServiceImpl implements ICmsProjectService {
    @Autowired
    private CmsProjectMapper cmsProjectMapper;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private RemoteDeptService remoteDeptService;
    @Autowired
    private ICmsAsyncService cmsAsyncService;
    @Lazy
    @Autowired
    private ICmsDocService cmsDocService;
    @Autowired
    private GitLinkRequestHelper gitLinkRequestHelper;
    @Value("${http.gitLinkUrl}")
    private String gitLinkUrl;
    @Value("${cms.gitLinkOrganization}")
    private String gitLinkOrganization;


    /**
     * 查询专区对应项目
     *
     * @param id 专区对应项目主键
     * @return 专区对应项目
     */
    @Override
    public CmsProject selectCmsProjectById(Long id) {
        return cmsProjectMapper.selectCmsProjectById(id);
    }

    /**
     * 查询专区对应项目列表
     *
     * @param cmsProjectInput 专区对应项目
     * @return 专区对应项目
     */
    @Override
    @DataScope(deptAlias = "p")
    public List<CmsProject> selectCmsProjectList(CmsProject cmsProjectInput) {
        List<CmsProject> cmsProjectList = cmsProjectMapper.selectCmsProjectList(cmsProjectInput);
        if (cmsProjectList == null) {
            return new ArrayList<>();
        }
        cmsProjectList
                .forEach(x -> x.setProjectUrl(genGitLinkUrl(x)));
        return cmsProjectList;
    }

    private String genGitLinkUrl(CmsProject cmsProject) {
        return gitLinkUrl + cmsProject.getUsername() + "/" + cmsProject.getIdentifier();
    }

    /**
     * 新增专区对应项目
     *
     * @param cmsProject 专区对应项目
     * @return 结果
     */
    @Override
    public int insertCmsProject(CmsProject cmsProject) {
        return cmsProjectMapper.insertCmsProject(cmsProject);
    }

    /**
     * 修改专区对应项目
     *
     * @param cmsProject 专区对应项目
     * @return 结果
     */
    @Override
    public int updateCmsProject(CmsProject cmsProject) {
        return cmsProjectMapper.updateCmsProject(cmsProject);
    }

    /**
     * 批量删除专区对应项目
     *
     * @param deptIds 需要删除的专区对应项目主键
     * @return 结果
     */
    @Override
    public int deleteCmsProjectByIds(Long[] deptIds) {
        int success = 0;
        for (Long deptId : deptIds) {
            CmsProject cmsProject = cmsProjectMapper.selectCmsProjectByDeptId(deptId);
            if (cmsProject == null) {
                throw new ServiceException("组织对应项目不存在(组织Id[" + deptId + "])");
            }
            // 删除专区下所有栏目及文章
            List<CmsDir> cmsDirList = cmsDocService.selectCmsDocDirList(deptId, false);
            for (CmsDir cmsDir : cmsDirList) {
                CmsDocSearchVo cmsDocSearchVo = new CmsDocSearchVo();
                cmsDocSearchVo.setDeptId(deptId);
                cmsDocSearchVo.setDirName(cmsDir.getName());
                List<CmsDocBaseDto> cmsDocList = cmsDocService.selectCmsDocList(cmsDir.getId(), cmsDocSearchVo);
                for (CmsDocBaseDto cmsDocBaseDto : cmsDocList) {
                    cmsDocService.deleteCmsDocById(cmsDocBaseDto.getId());
                }
                cmsDocService.deleteCmsDocById(cmsDir.getId());
            }
            JSONObject result = gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_PROJECT(cmsProject));
            String message = result.getString("message");
            if ("success".equals(message)) {
                success += cmsProjectMapper.deleteCmsProjectById(cmsProject.getId());
            } else {
                throw new ServiceException("专区对应项目删除失败(项目名称[" + cmsProject.getName() + "]):" + message);
            }
        }
        return success;
    }

    /**
     * 删除专区对应项目信息
     *
     * @param deptId 专区对应项目主键
     * @return 结果
     */
    @Override
    public int deleteCmsProjectByDeptId(Long deptId) {
        return deleteCmsProjectByIds(new Long[]{deptId});
    }

    private Long getOrganizationId() {
        JSONObject result = gitLinkRequestHelper.doGet(CmsGitLinkRequestUrl.GET_GITLINK_ORGANIZATIONS_INFO(gitLinkOrganization));
        return result.getLong("id");
    }

    @Override
    public Long insertZoneCmsProjectByDept(Long deptId) {
        CmsProject cmsProject = cmsProjectMapper.selectCmsProjectByDeptId(deptId);
        if (cmsProject != null) {
            throw new ServiceException("该组织已创建项目(组织id[" + deptId + "])");
        }
        //通过Feign获取部门信息
        SysDept sysDept = FeignUtils.getReturnData(remoteDeptService.getDeptByDeptId(deptId, SecurityConstants.INNER));
        if (sysDept == null) {
            throw new ServiceException("该组织不存在(组织id[" + deptId + "])");
        }
        Long organizationId = getOrganizationId();
        String cmsProjectKey = "TSZQ_" + PinYinStringUtils.toCamelCasePinyin(sysDept.getDeptName());
        CmsProject cmsProjectByKey = cmsProjectMapper.selectCmsProjectByIdentifier(cmsProjectKey);
        int cmsProjectKeyExtra = 1;
        while (cmsProjectByKey != null) {
            cmsProjectKey += cmsProjectKeyExtra;
            cmsProjectByKey = cmsProjectMapper.selectCmsProjectByIdentifier(cmsProjectKey);
            cmsProjectKeyExtra++;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("user_id", organizationId);
        jsonObject.put("name", "特色专区_" + sysDept.getDeptName());
        jsonObject.put("repository_name", handleSpecialCharacters(cmsProjectKey));
        jsonObject.put("description", sysDept.getDeptName() + "-专区对应项目");
        jsonObject.put("private", false);
        //调用GitLink接口创建项目
        JSONObject result = gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.CREATE_PROJECT(), jsonObject);
        cmsProject = new CmsProject();
        cmsProject.setId(result.getLong("id"));
        cmsProject.setIdentifier(result.getString("identifier"));
        cmsProject.setName(result.getString("name"));
        cmsProject.setDescription(result.getString("description"));
        cmsProject.setUserId(organizationId);
        cmsProject.setDeptId(deptId);
        cmsProject.setUsername(result.getString("login"));
        //通过创建项目返回值创建专区项目
        boolean insertResult = cmsProjectMapper.insertCmsProject(cmsProject) > 0;
        if (insertResult) {
            cmsAsyncService.asyncCreateWebhook(cmsProject);
            return cmsProject.getId();
        }
        return null;
    }

    @Override
    public boolean operateProtectedBranchByZoneAuditSetting(String userName, String identifier, Long deptId, String operationType) {

        switch (operationType) {
            case "create":
                cmsAsyncService.asyncCreateProtectedBranchSetting(userName, identifier, deptId);
                break;
            case "update":
                cmsAsyncService.asyncUpdateProtectedBranchSetting(userName, identifier, deptId);
                break;
            case "delete":
                cmsAsyncService.asyncDeleteProtectedBranchSetting(userName, identifier, deptId);
                break;
        }
        return true;
    }


    private String handleSpecialCharacters(String name) {
        return StringUtils.replace(name, " ", "-");
    }

    @Override
    public CmsProject selectCmsProjectByDeptId(Long deptId) {
        CmsProject cmsProject = cmsProjectMapper.selectCmsProjectByDeptId(deptId);
        if (cmsProject == null) {
            throw new ServiceException("该组织未创建专区项目(组织id[" + deptId + "])");
        }
        return cmsProject;
    }

    @Override
    public Boolean changeUserRole(Long userId, Long oldDeptId, Long newDeptId, Long oldRoleId, Long newRoleId) {
        SysUser sysUser = FeignUtils.getReturnData(remoteUserService.getSysUserByUserId(userId, SecurityConstants.INNER));
        if (sysUser == null || sysUser.getGitlinkUserId() == null) {
            return false;
        }
        JSONObject requestBody = new JSONObject();
        requestBody.put("user_id", String.valueOf(sysUser.getGitlinkUserId()));
        CmsProject oldCmsProject = cmsProjectMapper.selectCmsProjectByDeptId(oldDeptId);
        if (oldCmsProject != null) {
            if (oldCmsProject.getUsername().equals(sysUser.getUserName())) {
                throw new ServiceException("该用户为原组织项目的创建者，不允许从原组织项目迁出" +
                        "(用户名[" + sysUser.getUserName() + "]，原组织项目名[" + oldCmsProject.getName() + "]");
            }
            //将用户从原项目中移除
            try {
                gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.REMOVE_USER_FROM_PROJECT(oldCmsProject), requestBody);
            } catch (ServiceException e) {
                if (!e.getMessage().contains("用户为组织成员，请到组织下操作")) {
                    throw new ServiceException(e.getMessage());
                }
            }
        }
        //将用户加入新的项目
        CmsProject newCmsProject = cmsProjectMapper.selectCmsProjectByDeptId(newDeptId);
        if (newCmsProject != null) {
            try {
                gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.ADD_USER_FROM_PROJECT(newCmsProject), requestBody);
            } catch (ServiceException e) {
                if (!e.getMessage().contains("已经是项目成员")) {
                    throw new ServiceException(e.getMessage());
                }
            }
        }
        //判断是否为专区管理员角色，是-赋予项目管理员角色，否-不发起赋予
        if (newRoleId != null) {
            SysRole newRole = FeignUtils.getReturnData(
                    remoteUserService.getRoleInfoByInner(newRoleId, SecurityConstants.INNER)
            );
            if (newRole != null && SystemRole.ZONE_ADMIN.getRoleKey().equals(newRole.getRoleKey())) {
                requestBody = new JSONObject();
                requestBody.put("user_id", String.valueOf(sysUser.getGitlinkUserId()));
                requestBody.put("role", "Manager");
                try {
                    if (newCmsProject != null) {
                        gitLinkRequestHelper.doPut(CmsGitLinkRequestUrl.CHANGE_ROLE(newCmsProject), requestBody);
                    }
                } catch (ServiceException e) {
                    if (!e.getMessage().contains("用户为组织成员，请到组织下操作")) {
                        throw new ServiceException(e.getMessage());
                    }
                }
            }
        }

        //更新分支保护推动白名单设置
        JSONObject zoneJson = cmsDocService.getZoneJSONByDeptId(oldDeptId != null ? oldDeptId : newDeptId);
        if (zoneJson != null) {
            String needAudit = zoneJson.getString("docNeedAudit");
            if (StringUtils.isNotEmpty(needAudit) && needAudit.equals("1")) {
                String userName = null, identifier = null;
                Long deptId = null;
                if (oldCmsProject != null) {
                    userName = oldCmsProject.getUsername();
                    identifier = oldCmsProject.getIdentifier();
                    deptId = oldDeptId;
                } else if (newCmsProject != null) {
                    userName = newCmsProject.getUsername();
                    identifier = newCmsProject.getIdentifier();
                    deptId = newDeptId;
                }
                cmsAsyncService.asyncUpdateProtectedBranchSetting(userName, identifier, deptId);
            }
        }

        return true;
    }

    @Override
    public JSONObject getDeptProjectList() {
        JSONObject jsonObject = new JSONObject();
        List<CmsProject> projectList = cmsProjectMapper.selectCmsProjectList(null);
        for (CmsProject cmsProject : projectList) {
            String projectUrl = gitLinkUrl + cmsProject.getUsername() + "/" + cmsProject.getIdentifier();
            jsonObject.put(String.valueOf(cmsProject.getDeptId()), projectUrl);
        }
        return jsonObject;
    }

    @Override
    public Boolean updateCmsProjectByDept(SysDept dept) {
        CmsProject cmsProject = selectCmsProjectByDeptId(dept.getDeptId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "特色专区_" + dept.getDeptName());
        jsonObject.put("identifier", cmsProject.getIdentifier());
        jsonObject.put("description", dept.getDeptName() + "-专区对应项目");
        //调用GitLink接口创建项目
        JSONObject result = gitLinkRequestHelper.doPut(CmsGitLinkRequestUrl.UPDATE_PROJECT(cmsProject), jsonObject);
        cmsProject.setName(result.getString("name"));
        cmsProject.setDescription(result.getString("description"));
        return cmsProjectMapper.updateCmsProject(cmsProject) > 0;
    }
}
