package com.cf.imes.module.executor.service.veneer;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcelFactory;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.executor.constants.file.TemplateFilePathConstants;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameRespVO;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerClassificationNameSaveReqVO;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPageReqVO;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerClassificationNameDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO;
import com.cf.imes.module.executor.dal.mysql.veneer.VeneerBatchMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.VeneerClassificationNameMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.VeneerMapper;
import com.cf.imes.module.executor.util.file.FileHelperUtil;
import com.cf.imes.module.infra.api.file.FileApi;
import com.cf.imes.module.system.api.organ.OrganApi;
import com.cf.imes.module.system.api.organ.dto.OrganizationDTO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_IMPORT_TEMPLATE_DOWNLOAD_ERROR;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NOT_EXIST;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NO_EXIST;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_EMPTY;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_EXIST;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_NOT_EXIST;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_ORG_CLASSIFICATION_NAME_USED;

/**
 * 贴皮管理ServiceImpl 实现类
 *
 * @author Gqr
 * @since 2026/1/4 14:24
 */
@Service
public class VeneerServiceImpl implements VeneerService {
    @Resource
    private FileApi fileApi;

    @Resource
    private OrganApi organApi;

    @Resource
    private VeneerMapper veneerMapper;

    @Resource
    private VeneerBatchMapper veneerBatchMapper;

    @Resource
    private VeneerClassificationNameMapper veneerClassificationNameMapper;

    @Override
    public Long create(VeneerSaveReqVO reqVO) {
        // 1、校验贴皮编号
        boolean validateVeneerNoOnly = validateVeneerNoOnly(reqVO.getVeneerNo(), reqVO.getId());
        if(!validateVeneerNoOnly) {
            throw new ServiceException(VENEER_NO_EXIST);
        }

        //2、贴皮数据入库
        VeneerDO veneerDO = BeanUtil.copyProperties(reqVO, VeneerDO.class);
        veneerMapper.insert(veneerDO);

        return veneerDO.getId();
    }

    @Override
    public void update(VeneerSaveReqVO reqVO) {
        Long id = reqVO.getId();

        // 1、校验贴皮是否存在
        if (ObjectUtil.isNull(id) || ObjectUtil.isNull(validateExist(id))) {
            throw new ServiceException(VENEER_NOT_EXIST);
        }

        // 2、校验贴皮编号
        boolean validateVeneerNoOnly = validateVeneerNoOnly(reqVO.getVeneerNo(), id);
        if(!validateVeneerNoOnly) {
            throw new ServiceException(VENEER_NO_EXIST);
        }


        //3、贴皮数据入库
        VeneerDO veneerDO = BeanUtil.copyProperties(reqVO, VeneerDO.class);
        veneerMapper.updateById(veneerDO);
    }

    @Override
    public void delete(Long id) {
        // 1、校验贴皮是否存在
        if (ObjectUtil.isNull(validateExist(id))) {
            throw new ServiceException(VENEER_NOT_EXIST);
        }

        //2、删除贴皮
        veneerMapper.deleteById(id);
    }

    @Override
    public Long uploadPic(Long id, MultipartFile file) throws IOException {
        if (ObjectUtil.isNotNull(id) && ObjectUtil.isNull(validateExist(id))) {
            throw new ServiceException(VENEER_NOT_EXIST);
        }

        Long organId = SecurityFrameworkUtils.getUserOrganId();

        // 获取组织名称
        OrganizationDTO organizationDTO;
        CommonResult<OrganizationDTO> details = organApi.getOrganDetails(organId);
        if (details.isError()) {
            throw new ServiceException(details.getCode(), details.getMsg());
        } else {
            organizationDTO = details.getData();
        }
        Long fileId = fileApi.createFileAndReturnId(file.getBytes(), String.format("%s-veneer-pic-file-%s.%s", organizationDTO.getName(), LocalDateTimeUtil.format(LocalDateTime.now(), PURE_DATETIME_PATTERN), getFileExtension(file.getOriginalFilename())));
        if (ObjectUtil.isNotNull(id)) {
            veneerMapper.update(new LambdaUpdateWrapper<VeneerDO>()
                    .eq(VeneerDO::getId, id)
                    .set(VeneerDO::getFileId, fileId));
        }
        return fileId;
    }

    @Override
    public void importTemplateDownload(HttpServletResponse response) {
        try {
            // 根据语种获取模版的路径
            String veneerImportTemplatePath = TemplateFilePathConstants.getVeneerImportTemplatePath(LocaleContextHolder.getLocale().getLanguage());

            // 获取文件
            File templateFile = FileHelperUtil.getFirstFile(veneerImportTemplatePath);

            // 获取组织分类名称列表
            List<VeneerClassificationNameRespVO> orgVeneerClassificationNameList = getOrgVeneerClassificationNameList();
            if (CollUtil.isEmpty(orgVeneerClassificationNameList)) {
                throw new ServiceException(VENEER_ORG_CLASSIFICATION_NAME_EMPTY);
            }

            String[] options = orgVeneerClassificationNameList.stream().map(VeneerClassificationNameRespVO::getName).toArray(String[]::new);

            // 从第2行开始， 到200行写入数据源
            EasyExcelFactory.write(response.getOutputStream())
                    .withTemplate(FileUtil.getInputStream(templateFile))
                    .registerWriteHandler(new VeneerExcelTemplateClassificationNameWriteHandler(
                            2,
                            options,
                            1,
                            200
                    ))
                    .sheet(0)
                    .doWrite(Collections.emptyList());
        } catch (IOException ie) {
            throw new ServiceException(VENEER_IMPORT_TEMPLATE_DOWNLOAD_ERROR);
        }
    }

    @Override
    public PageResult<VeneerRespVO> getPage(VeneerPageReqVO pageReqVO) {
        PageResult<VeneerDO> veneerDOPageResult = veneerMapper.selectPage(pageReqVO);

        PageResult<VeneerRespVO> pageResult = new PageResult<>();
        if (veneerDOPageResult.getTotal() != 0) {
            pageResult.setList(BeanUtil.copyToList(veneerDOPageResult.getList(), VeneerRespVO.class));
            pageResult.setTotal(veneerDOPageResult.getTotal());
        }
        return pageResult;
    }

    @Override
    public VeneerRespVO get(Long id) {
        // 1、校验贴皮是否存在
        VeneerDO veneerDO = validateExist(id);
        if (ObjectUtil.isNull(veneerDO)) {
            throw new ServiceException(VENEER_NOT_EXIST);
        }
        String defectData = veneerDO.getDefectData();
        if (StringUtils.isNotEmpty(defectData)) {
            veneerDO.setDefectData(JsonUtils.unzipString(defectData));
        }
        return BeanUtil.copyProperties(veneerDO, VeneerRespVO.class);
    }

    @Override
    public Map<String, Long> getOrgVeneerNo() {
        return veneerMapper.selectList(new LambdaQueryWrapper<VeneerDO>().select(VeneerDO::getId, VeneerDO::getVeneerNo)).stream().collect(Collectors.toMap(VeneerDO::getVeneerNo, VeneerDO::getId));
    }

    @Override
    public void batchInsert(List<VeneerDO> list) {
        veneerBatchMapper.insertBatchSomeColumn(list);
    }

    @Override
    public void batchUpdate(List<VeneerDO> list) {
        veneerBatchMapper.updateBatch(list);
    }

    @Override
    public void saveDefect(VeneerDefectSaveReqVO defectSaveReqVO) {
        Long id = defectSaveReqVO.getId();
        // 校验贴皮是否存在
        if (ObjectUtil.isNull(validateExist(id))) {
            throw new ServiceException(VENEER_NOT_EXIST);
        }

        String defectData = defectSaveReqVO.getDefectData();
        if(StringUtils.isNotEmpty(defectData)) {
            // 更新瑕疵数据和状态
            veneerMapper.update(new LambdaUpdateWrapper<VeneerDO>()
                    .eq(VeneerDO::getId, id)
                    .set(VeneerDO::getDefect, true)
                    .set(VeneerDO::getDefectData, JsonUtils.zipString(defectData)));
        }
    }

    /**
     * 校验贴皮是否存在
     *
     * @param id
     * @return true：存在、false：不存在
     */
    private VeneerDO validateExist(Long id) {
        return veneerMapper.selectById(id);
    }

    /**
     * 校验贴皮编号是否组织唯一
     *
     * @param veneerNo
     * @param id
     * @return true：唯一、false：不唯一
     */
    private boolean validateVeneerNoOnly(String veneerNo, Long id) {
        return veneerMapper.selectCount(new LambdaQueryWrapperX<VeneerDO>()
                .eq(VeneerDO::getVeneerNo, veneerNo)
                .neIfPresent(VeneerDO::getId, id)) == 0;
    }

    /**
     * 截取文件类型
     *
     * @param fileName
     * @return
     */
    public static String getFileExtension(String fileName) {
        return Optional.ofNullable(fileName)
                .filter(StringUtils::isNotBlank)
                .filter(name -> name.contains("."))
                .map(name -> name.substring(name.lastIndexOf('.')))
                .filter(ext -> ext.length() > 1)
                .map(ext -> ext.toLowerCase(Locale.ROOT))
                .orElse(".jpg");
    }

    @Override
    public Long addClassificationName(VeneerClassificationNameSaveReqVO saveReqVO) {
        String classificationName = saveReqVO.getName();
        // 校验组织下分类名称唯一
        validOrgClassificationName(classificationName);

        VeneerClassificationNameDO veneerClassificationNameDO = new VeneerClassificationNameDO();
        veneerClassificationNameDO.setName(classificationName);
        veneerClassificationNameMapper.insert(veneerClassificationNameDO);
        return veneerClassificationNameDO.getId();
    }

    @Override
    public void deleteClassificationName(Long id) {
        VeneerClassificationNameDO classificationNameDO = veneerClassificationNameMapper.selectById(id);
        if (ObjectUtil.isNull(classificationNameDO)) {
            throw new ServiceException(VENEER_ORG_CLASSIFICATION_NAME_NOT_EXIST);
        }
        if (veneerMapper.selectCount(new LambdaQueryWrapper<VeneerDO>()
                .eq(VeneerDO::getClassificationName, classificationNameDO.getName())) > 0) {
            throw new ServiceException(VENEER_ORG_CLASSIFICATION_NAME_USED);
        }
        veneerClassificationNameMapper.deleteById(id);
    }

    /**
     * 校验组织下分类名称唯一
     *
     * @param classificationName
     */
    private void validOrgClassificationName(String classificationName) {
        if (veneerClassificationNameMapper.selectCount(new LambdaQueryWrapper<VeneerClassificationNameDO>()
                .eq(VeneerClassificationNameDO::getName, classificationName)) > 0) {
            throw new ServiceException(VENEER_ORG_CLASSIFICATION_NAME_EXIST);
        }
    }

    @Override
    public List<VeneerClassificationNameRespVO> getOrgVeneerClassificationNameList() {
        return BeanUtil.copyToList(veneerClassificationNameMapper.selectList(), VeneerClassificationNameRespVO.class);
    }
}
