package cd.casic.ci.process.process.service.target.impl;


import cd.casic.ci.process.dto.req.target.*;
import cd.casic.ci.process.dto.resp.sftpFile.FileBase64DownloadResp;
import cd.casic.ci.process.dto.resp.target.TargetManagerResp;
import cd.casic.ci.process.dto.resp.target.TargetVersionResp;
import cd.casic.ci.process.process.converter.TargetConverter;
import cd.casic.ci.process.process.converter.TargetVersionConverter;
import cd.casic.ci.process.process.dao.pipeline.TargetManagerDao;
import cd.casic.ci.process.process.dao.pipeline.TargetVersionDao;
import cd.casic.ci.process.process.dataObject.base.BaseIdReq;
import cd.casic.ci.process.process.dataObject.target.TargetManager;
import cd.casic.ci.process.process.dataObject.target.TargetVersion;
import cd.casic.ci.process.process.service.pipeline.PipelineService;
import cd.casic.ci.process.process.service.sftpFile.impl.SftpFileServiceImpl;
import cd.casic.ci.process.process.service.target.TargetManagerService;
import cd.casic.ci.commons.properties.TargetFileUploadProperties;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.framework.commons.pojo.PageResult;
import cd.casic.framework.security.dal.user.AdminUserDO;
import cd.casic.framework.tenant.core.service.AdminUserServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @author HopeLi
 * @version v1.0
 * @ClassName TargetManagerServiceImpl
 * @Date: 2025/5/17 15:19
 * @Description:
 */
@Service
@Slf4j
public class TargetManagerServiceImpl extends ServiceImpl<TargetManagerDao, TargetManager> implements TargetManagerService {

    @Resource
    private TargetVersionServiceImpl targetVersionService;

    @Resource
    private TargetManagerDao targetManagerDao;

    @Resource
    private TargetVersionDao targetVersionDao;

    @Resource
    private AdminUserServiceImpl adminUserService;
    @Resource
    private TargetFileUploadProperties fileUploadProperties;

    @Resource
    private SftpFileServiceImpl sftpFileService;


    @Resource
    private PipelineService pipelineService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createTarget(TargetManagerCreateReq req) {
        TargetManager targetManager = TargetConverter.INSTANCE.createReqToBean(req);

        //根据目标名称做全局唯新校验
        QueryWrapper<TargetManager> wrapper = new QueryWrapper<>();
        wrapper.eq("target_name",targetManager.getTargetName());
        if (!ObjectUtils.isEmpty(targetManagerDao.selectList(wrapper))){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标名称已存在");
        }

        this.save(targetManager);
        TargetVersionCreateReq targetVersion = TargetVersionConverter.INSTANCE.targetCreateReqToTargetVersionCreateReq(req);
        targetVersion.setTargetId(targetManager.getId());
        createVersion(targetVersion);
//        //保存第一个版本

//        targetVersion.setTargetId(targetManager.getId());
//        targetVersionService.save(targetVersion);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTarget(TargetManagerUpdateReq req) {
        if (StringUtils.isEmpty(req.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"id不能为空");
        }

        TargetManager targetManager = targetManagerDao.selectById(req.getId());
        if (ObjectUtils.isEmpty(targetManager)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"数据错误，请联系管理员");
        }

        TargetConverter.INSTANCE.updateReqToBean(req,targetManager);
        targetManagerDao.updateById(targetManager);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTarget(BaseIdReq req) {
        if (StringUtils.isEmpty(req.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"id不能为空");
        }

        TargetManager targetManager = targetManagerDao.selectById(req.getId());
        if (ObjectUtils.isEmpty(targetManager)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"数据错误，请联系管理员");
        }
        targetManagerDao.deleteById(targetManager.getId());

        //删除对应的version版本
        List<TargetVersionResp> versionList = targetVersionService.selectListByManagerId(targetManager.getId());
        List<String> versionIdList = versionList.stream().map(TargetVersionResp::getId).toList();
        targetVersionDao.deleteByIds(versionIdList);
    }

    @Override
    public PageResult<TargetManagerResp> findTargetPage(TargetQueryReq query) {

        QueryWrapper<TargetManager> wrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(query.getId())){
            wrapper.eq("id",query.getId());
        }
        if (!ObjectUtils.isEmpty(query.getIdList())){
            wrapper.in("id",query.getId());
        }
        if (!ObjectUtils.isEmpty(query.getTargetName())){
            wrapper.like("target_name",query.getTargetName());
        }
        if (!ObjectUtils.isEmpty(query.getTargetType())){
            wrapper.like("target_type",query.getTargetType());
        }
        if (!ObjectUtils.isEmpty(query.getCreator())){
            wrapper.eq("creator",query.getCreator());
        }

        Page<TargetManager> targetManagerPage = targetManagerDao.selectPage(new Page<>(query.getPageNo(), query.getPageSize()), wrapper);

        if (ObjectUtils.isEmpty(targetManagerPage)){
            return new PageResult<>();
        }

        List<TargetManagerResp> respList = TargetConverter.INSTANCE.toRespList(targetManagerPage.getRecords());
        respList.forEach(this::setUserName);

        respList.forEach(o->{
            List<TargetVersionResp> targetVersionResps = targetVersionService.selectListByManagerId(o.getId());
            if (!ObjectUtils.isEmpty(targetVersionResps)){
                o.setVersionList(targetVersionResps);
            }
        });

        PageResult<TargetManagerResp> pageResult = new PageResult<>(respList,targetManagerPage.getTotal(),targetManagerPage.getCurrent(),targetManagerPage.getSize());
        return pageResult;
    }

    private void setUserName(TargetManagerResp targetManagerResp) {
        if (!StringUtils.isEmpty(targetManagerResp.getCreator())){
            AdminUserDO user = adminUserService.getUser(Long.valueOf(targetManagerResp.getCreator()));
            if (!ObjectUtils.isEmpty(user)){
                targetManagerResp.setCreatorName(user.getUsername());
            }
        }

        if (!StringUtils.isEmpty(targetManagerResp.getUpdater())){
            AdminUserDO user = adminUserService.getUser(Long.valueOf(targetManagerResp.getUpdater()));
            if (!ObjectUtils.isEmpty(user)){
                targetManagerResp.setUpdaterName(user.getUsername());
            }
        }
    }

    @Override
    public List<TargetManagerResp> findTargetList(TargetQueryReq query) {
        QueryWrapper<TargetManager> wrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(query.getId())){
            wrapper.eq("id",query.getId());
        }
        if (!ObjectUtils.isEmpty(query.getIdList())){
            wrapper.in("id",query.getId());
        }
        if (!ObjectUtils.isEmpty(query.getTargetName())){
            wrapper.like("target_name",query.getTargetName());
        }
        if (!ObjectUtils.isEmpty(query.getTargetType())){
            wrapper.like("target_type",query.getTargetType());
        }
        if (!ObjectUtils.isEmpty(query.getCreator())){
            wrapper.eq("creator",query.getCreator());
        }
        List<TargetManager> targetManagerList = targetManagerDao.selectList(wrapper);
        if (ObjectUtils.isEmpty(targetManagerList)){
            return new ArrayList<>(0);
        }

        List<TargetManagerResp> respList = TargetConverter.INSTANCE.toRespList(targetManagerList);
        respList.forEach(this::setUserName);

        return respList;
    }

    @Override
    public String fileUpload(MultipartFile file) throws SftpUploadUtil.SftpUploadException {
        String filePath = fileUploadProperties.getRemoteDir() + UUID.randomUUID();

        String path = SftpUploadUtil.uploadFileSftp(
                fileUploadProperties.getRemoteHost(),
                fileUploadProperties.getRemotePort(),
                fileUploadProperties.getUsername(),
                fileUploadProperties.getPassword(),
                fileUploadProperties.getSshKeyPath(),
                file,
                filePath,
                file.getOriginalFilename()
        );
        return path;
    }

    @Override
    public void createVersion(TargetVersionCreateReq req) {
        TargetVersion targetVersion = TargetVersionConverter.INSTANCE.versionCreateReqToTargetVersionBean(req);

        //根据版本做局部唯新校验
        QueryWrapper<TargetVersion> wrapper = new QueryWrapper<>();
        wrapper.eq("version",targetVersion.getVersion());
        wrapper.eq("target_id",targetVersion.getTargetId());
        if (!CollectionUtils.isEmpty(targetVersionDao.selectList(wrapper))){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"版本已存在");
        }

        targetVersionService.save(targetVersion);
    }

    @Override
    public void deleteVersion(BaseIdReq req) {
        if (pipelineService.targetVersionInUse(Collections.singletonList(req.getId()))) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"当前目标正在被流水线使用无法删除");
        }
        targetVersionDao.deleteById(req.getId());
    }

    @Override
    public void updateVersion(TargetVersionUpdateReq req){
        if (ObjectUtils.isEmpty(req.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标id不能为空");
        }
        TargetVersion targetVersion = targetVersionDao.selectById(req.getId());
        if (ObjectUtils.isEmpty(targetVersion)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标版本不存在");
        }
        //根据版本做局部唯新校验
        QueryWrapper<TargetVersion> wrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(req.getVersion())){
            wrapper.eq("version",req.getVersion());
            wrapper.eq("target_id",targetVersion.getTargetId());

            if (!ObjectUtils.isEmpty(targetVersionDao.selectList(wrapper))){
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标版本号已存在");
            }
        }

        TargetVersionConverter.INSTANCE.updateReqCopyToTargetVersion(req,targetVersion);
        targetVersionService.updateById(targetVersion);
    }

    @Override
    public void fileDownload(BaseIdReq req, HttpServletResponse response){
        if (ObjectUtils.isEmpty(req.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标id不能为空");
        }
        //根据versionId查询对应的版本信息，获取版本保存地址
        TargetVersion targetVersion = targetVersionDao.selectById(req.getId());

        if (ObjectUtils.isEmpty(targetVersion) || ObjectUtils.isEmpty(targetVersion.getFilePath())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标版本或路径不存在");
        }
        sftpFileService.downloadFile(targetVersion.getFilePath(),response);
    }

    @Override
    public FileBase64DownloadResp zipDownload(BaseIdReq req, HttpServletResponse response){
        if (ObjectUtils.isEmpty(req.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标管理id不能为空");
        }
        TargetManager targetManager = targetManagerDao.selectById(req.getId());
        if (ObjectUtils.isEmpty(targetManager)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标不存在");
        }

        //根据targetId查询对应的全部版本信息，获取版本保存地址
        QueryWrapper<TargetVersion> wrapper = new QueryWrapper<>();
        wrapper.eq("target_id",req.getId());
        List<TargetVersion> targetVersionList = targetVersionDao.selectList(wrapper);

        if (ObjectUtils.isEmpty(targetVersionList)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"目标版本不存在");
        }

        List<String> filePathList = targetVersionList.stream().map(TargetVersion::getFilePath).toList();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        String targetName = targetManager.getTargetName();
        sftpFileService.downloadFilesAsZip(filePathList,bos);
        byte[] byteArray = bos.toByteArray();
        String file = Base64.getEncoder().encodeToString(byteArray);
        FileBase64DownloadResp resp = new FileBase64DownloadResp();
        resp.setFile(file);
        resp.setFileName(targetName+".zip");
        return resp;
    }


    public static byte[] toByteArray(InputStream is) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        byte[] data = new byte[8192];
        int nRead;

        while ((nRead = is.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        return buffer.toByteArray();
    }
    private void setTargetVersionCompose(TargetVersion targetVersion){
        
    }
}
