package jnpf.certificate.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jnpf.certificate.mapper.CertificateBusinessLicenseExtMapper;
import jnpf.certificate.mapper.CertificateHygieneLicenseExtMapper;
import jnpf.certificate.mapper.CertificateInstanceItemMapper;
import jnpf.certificate.mapper.CertificateInstanceMapper;
import jnpf.certificate.service.CertificateManageService;
import jnpf.model.certificate.po.CertificateBusinessLicenseExtEntity;
import jnpf.model.certificate.po.CertificateHygieneLicenseExtEntity;
import jnpf.model.certificate.po.CertificateInstanceEntity;
import jnpf.model.certificate.po.CertificateInstanceItemEntity;
import jnpf.model.certificate.req.CertificateInstanceItemReq;
import jnpf.model.certificate.req.app.CertificateAppBusinessLicenseUpdateReq;
import jnpf.model.certificate.req.app.CertificateAppHealthCertificateUpdateReq;
import jnpf.model.certificate.req.app.CertificateAppHygieneLicenseUpdateReq;
import jnpf.model.certificate.req.app.CertificateAppStoreCustomUpdateReq;
import jnpf.model.certificate.vo.CertificateInstanceItemVO;
import jnpf.model.certificate.vo.app.CertificateAppBusinessLicenseDetailVO;
import jnpf.model.certificate.vo.app.CertificateAppCertificateDetailVO;
import jnpf.model.certificate.vo.app.HealthCertificateDetailVO;
import jnpf.model.certificate.vo.app.CertificateAppHygieneLicenseDetailVO;
import jnpf.model.certificate.vo.app.CertificateAppStoreCustomDetailVO;
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
import jnpf.util.FtbUtil;
import jnpf.util.ServiceException;
import jnpf.util.UserProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * App端证照管理服务实现。
 */
@Service
public class CertificateManageServiceImpl implements CertificateManageService {

    private static final int STATUS_MISSING = 1;
    private static final int STATUS_EXPIRED = 2;
    private static final int STATUS_NEAR_EXPIRE = 3;
    private static final int STATUS_NORMAL = 4;
    private static final int NEAR_EXPIRE_DAYS = 30;

    @Autowired
    private CertificateInstanceMapper certificateInstanceMapper;
    @Autowired
    private CertificateBusinessLicenseExtMapper certificateBusinessLicenseExtMapper;
    @Autowired
    private CertificateHygieneLicenseExtMapper certificateHygieneLicenseExtMapper;
    @Autowired
    private CertificateInstanceItemMapper certificateInstanceItemMapper;

    /**
     * 根据证照实例ID查询详情，按证照类型返回不同明细对象。
     */
    @Override
    public CertificateAppCertificateDetailVO queryInfo(String certificateInstanceId) {
        ServiceException.isTrue(StrUtil.isNotBlank(certificateInstanceId), "证照实例ID不能为空");
        CertificateInstanceEntity entity = queryActiveEntity(StrUtil.trim(certificateInstanceId));
        Optional<CertificateTypeEnum> certificateTypeEnumOptional = CertificateTypeEnum.getByType(entity.getCertificateType());
        ServiceException.isTrue(certificateTypeEnumOptional.isPresent(), "不支持的证照类型");
        CertificateTypeEnum certificateTypeEnum = certificateTypeEnumOptional.get();

        Integer status = calculateStatus(entity.getIsLongTerm(), entity.getExpireDate());
        CertificateAppCertificateDetailVO result = new CertificateAppCertificateDetailVO();
        result.setCertificateInstanceId(entity.getId());
        result.setCertificateType(certificateTypeEnum.getType());
        result.setStatus(status);
        result.setStatusName(resolveStatusName(status));

        if (CertificateTypeEnum.HEALTH_CERTIFICATE.equals(certificateTypeEnum)) {
            result.setDetail(buildHealthDetail(entity));
            return result;
        }
        if (CertificateTypeEnum.BUSINESS_LICENSE.equals(certificateTypeEnum)) {
            result.setDetail(buildBusinessLicenseDetail(entity));
            return result;
        }
        if (CertificateTypeEnum.HYGIENE_LICENSE.equals(certificateTypeEnum)) {
            result.setDetail(buildHygieneLicenseDetail(entity));
            return result;
        }
        result.setDetail(buildStoreCustomDetail(entity));
        return result;
    }

    /**
     * 更新健康证数据。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateHealthCertificate(CertificateAppHealthCertificateUpdateReq req) {
        ServiceException.notNull(req, "请求参数不能为空");
        CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.HEALTH_CERTIFICATE, "健康证");

        Date issueDate = parseDate(req.getIssueDate(), "发证日期");
        Date expireDate = parseDate(req.getExpireDate(), "到期日期");

        //原生app增量更新，可能不传值，则使用数据库值
        if(Objects.isNull(issueDate)){
            issueDate = entity.getIssueDate();
        }
        if(Objects.isNull(expireDate)){
            expireDate = entity.getExpireDate();
        }
        if(Objects.nonNull(issueDate) && Objects.nonNull(expireDate) && issueDate.after(expireDate)){
            throw new ServiceException("发证日期不能大于到期日期");
        }

        entity.setCertificateImage(trimToNull(req.getCertificateImage()));
        entity.setIssueDate(issueDate);
        entity.setExpireDate(expireDate);
        entity.setIsLongTerm(0);
        entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
        int r = certificateInstanceMapper.updateById(entity);
        if(r <= 0){
            return;
        }

    }

    /**
     * 更新营业执照数据，并同步营业执照扩展表。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBusinessLicense(CertificateAppBusinessLicenseUpdateReq req) {
        ServiceException.notNull(req, "请求参数不能为空");
        CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.BUSINESS_LICENSE, "营业执照");

        Date establishDate = parseDate(req.getEstablishDate(), "成立时间");
        Date issueDate = parseDate(req.getIssueDate(), "发证日期");
        Date expireDate = parseDate(req.getExpireDate(), "到期日期");
        Integer isLongTerm = req.getIsLongTerm() == null ? 0 : req.getIsLongTerm();
        if (Integer.valueOf(1).equals(isLongTerm)) {
            expireDate = null;
        }

        entity.setCertificateImage(trimToNull(req.getCertificateImage()));
        entity.setCertificateNo(trimToNull(req.getCertificateNo()));
        entity.setIssueDate(issueDate);
        entity.setExpireDate(expireDate);
        entity.setIsLongTerm(isLongTerm);
        entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
        certificateInstanceMapper.updateById(entity);

        saveBusinessLicenseExt(entity.getId(), req, establishDate);
    }

    /**
     * 更新食品经营许可证数据，并同步食品许可扩展表。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateHygieneLicense(CertificateAppHygieneLicenseUpdateReq req) {
        ServiceException.notNull(req, "请求参数不能为空");
        CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.HYGIENE_LICENSE, "食品经营许可证");

        Date issueDate = parseDate(req.getIssueDate(), "发证日期");
        Date expireDate = parseDate(req.getExpireDate(), "到期日期");

        entity.setCertificateImage(trimToNull(req.getCertificateImage()));
        entity.setIssueDate(issueDate);
        entity.setExpireDate(expireDate);
        entity.setIsLongTerm(0);
        entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
        certificateInstanceMapper.updateById(entity);

        saveHygieneLicenseExt(entity.getId(), req);
    }

    /**
     * 更新门店自定义证照数据，并重写自定义字段明细。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStoreCustomCertificate(CertificateAppStoreCustomUpdateReq req) {
        ServiceException.notNull(req, "请求参数不能为空");
        CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE, "门店自定义证照");

        Date expireDate = parseDate(req.getExpireDate(), "到期日期");
        entity.setCertificateImage("");
        entity.setIssueDate(null);
        entity.setExpireDate(expireDate);
        entity.setIsLongTerm(0);
        entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
        certificateInstanceMapper.updateById(entity);

        deleteAndSaveStoreCustomItems(entity.getId(), req.getItemList());
    }

    /**
     * 构建健康证明细返回对象。
     */
    private HealthCertificateDetailVO buildHealthDetail(CertificateInstanceEntity entity) {
        HealthCertificateDetailVO detailVO = new HealthCertificateDetailVO();
        detailVO.setCertificateImage(entity.getCertificateImage());
        detailVO.setIssueDate(entity.getIssueDate());
        detailVO.setExpireDate(entity.getExpireDate());
        detailVO.setStatus(entity.getStatus());
        return detailVO;
    }

    /**
     * 构建营业执照明细返回对象。
     */
    private CertificateAppBusinessLicenseDetailVO buildBusinessLicenseDetail(CertificateInstanceEntity entity) {
        CertificateBusinessLicenseExtEntity extEntity = queryBusinessLicenseExt(entity.getId());
        CertificateAppBusinessLicenseDetailVO detailVO = new CertificateAppBusinessLicenseDetailVO();
        detailVO.setCertificateImage(entity.getCertificateImage());
        detailVO.setCertificateNo(entity.getCertificateNo());
        detailVO.setIssueDate(entity.getIssueDate());
        detailVO.setExpireDate(entity.getExpireDate());
        detailVO.setIsLongTerm(entity.getIsLongTerm());
        detailVO.setStatus(entity.getStatus());
        if (extEntity != null) {
            detailVO.setCompanyName(extEntity.getCompanyName());
            detailVO.setLegalRepresentative(extEntity.getLegalRepresentative());
            detailVO.setEstablishDate(extEntity.getEstablishDate());
            detailVO.setBusinessScope(extEntity.getBusinessScope());
            detailVO.setAddress(extEntity.getCompanyAddress());
        }
        return detailVO;
    }

    /**
     * 构建食品经营许可证明细返回对象。
     */
    private CertificateAppHygieneLicenseDetailVO buildHygieneLicenseDetail(CertificateInstanceEntity entity) {
        CertificateHygieneLicenseExtEntity extEntity = queryHygieneLicenseExt(entity.getId());
        CertificateAppHygieneLicenseDetailVO detailVO = new CertificateAppHygieneLicenseDetailVO();
        detailVO.setCertificateImage(entity.getCertificateImage());
        detailVO.setIssueDate(entity.getIssueDate());
        detailVO.setExpireDate(entity.getExpireDate());
        detailVO.setStatus(entity.getStatus());
        if (extEntity != null) {
            detailVO.setBusinessProject(extEntity.getBusinessProject());
        }
        return detailVO;
    }

    /**
     * 构建门店自定义证照明细返回对象。
     */
    private CertificateAppStoreCustomDetailVO buildStoreCustomDetail(CertificateInstanceEntity entity) {
        CertificateAppStoreCustomDetailVO detailVO = new CertificateAppStoreCustomDetailVO();
        detailVO.setCertificateImage(entity.getCertificateImage());
        detailVO.setExpireDate(entity.getExpireDate());

        LambdaQueryWrapper<CertificateInstanceItemEntity> itemWrapper = Wrappers.lambdaQuery();
        itemWrapper.eq(CertificateInstanceItemEntity::getInstanceId, entity.getId());
        itemWrapper.eq(CertificateInstanceItemEntity::getEnabledMark, 0);
        itemWrapper.orderByAsc(CertificateInstanceItemEntity::getSorts);
        List<CertificateInstanceItemEntity> itemList = certificateInstanceItemMapper.selectList(itemWrapper);
        if (CollUtil.isNotEmpty(itemList)) {
            detailVO.setItemList(itemList.stream().map(CertificateInstanceItemVO::convert).collect(Collectors.toList()));
        }
        return detailVO;
    }

    /**
     * 保存营业执照扩展信息，不存在则新增，存在则更新。
     */
    private void saveBusinessLicenseExt(String instanceId, CertificateAppBusinessLicenseUpdateReq req, Date establishDate) {
        CertificateBusinessLicenseExtEntity extEntity = queryBusinessLicenseExt(instanceId);
        if (extEntity == null) {
            extEntity = new CertificateBusinessLicenseExtEntity();
            extEntity.setId(FtbUtil.getId());
            extEntity.setInstanceId(instanceId);
            extEntity.setEnabledMark(0);
            fillBusinessLicenseExt(extEntity, req, establishDate);
            certificateBusinessLicenseExtMapper.insert(extEntity);
            return;
        }
        fillBusinessLicenseExt(extEntity, req, establishDate);
        certificateBusinessLicenseExtMapper.update(null,new LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity>()
                .eq(CertificateBusinessLicenseExtEntity::getId, extEntity.getId())
                .set(CertificateBusinessLicenseExtEntity::getCompanyName,extEntity.getCompanyName())
                .set(CertificateBusinessLicenseExtEntity::getCompanyAddress,extEntity.getCompanyAddress())
                .set(CertificateBusinessLicenseExtEntity::getBusinessScope,extEntity.getBusinessScope())
                .set(CertificateBusinessLicenseExtEntity::getEstablishDate,extEntity.getEstablishDate())
                .set(CertificateBusinessLicenseExtEntity::getLegalRepresentative,extEntity.getLegalRepresentative())
                .set(CertificateBusinessLicenseExtEntity::getLastModifyUserId, UserProvider.getLoginUserId())
                .set(CertificateBusinessLicenseExtEntity::getLastModifyTime,new Date()));
    }

    /**
     * 填充营业执照扩展字段。
     */
    private void fillBusinessLicenseExt(CertificateBusinessLicenseExtEntity extEntity, CertificateAppBusinessLicenseUpdateReq req, Date establishDate) {
        extEntity.setCompanyName(trimToNull(req.getCompanyName()));
        extEntity.setLegalRepresentative(trimToNull(req.getLegalRepresentative()));
        extEntity.setEstablishDate(establishDate);
        extEntity.setBusinessScope(trimToNull(req.getBusinessScope()));
        extEntity.setCompanyAddress(req.getAddress());
    }

    /**
     * 保存食品经营许可扩展信息，不存在则新增，存在则更新。
     */
    private void saveHygieneLicenseExt(String instanceId, CertificateAppHygieneLicenseUpdateReq req) {
        CertificateHygieneLicenseExtEntity extEntity = queryHygieneLicenseExt(instanceId);
        if (extEntity == null) {
            extEntity = new CertificateHygieneLicenseExtEntity();
            extEntity.setId(FtbUtil.getId());
            extEntity.setInstanceId(instanceId);
            extEntity.setEnabledMark(0);
            extEntity.setBusinessProject(trimToNull(req.getBusinessProject()));
            certificateHygieneLicenseExtMapper.insert(extEntity);
            return;
        }
        extEntity.setBusinessProject(trimToNull(req.getBusinessProject()));
        certificateHygieneLicenseExtMapper.update(null,new LambdaUpdateWrapper<CertificateHygieneLicenseExtEntity>()
                .eq(CertificateHygieneLicenseExtEntity::getId, extEntity.getId())
                .set(CertificateHygieneLicenseExtEntity::getBusinessProject,extEntity.getBusinessProject()));
    }

    /**
     * 删除旧的门店自定义明细并保存新的明细列表。
     */
    private void deleteAndSaveStoreCustomItems(String instanceId, List<CertificateInstanceItemReq> itemList) {
        LambdaQueryWrapper<CertificateInstanceItemEntity> deleteWrapper = Wrappers.lambdaQuery();
        deleteWrapper.eq(CertificateInstanceItemEntity::getInstanceId, instanceId);
        certificateInstanceItemMapper.delete(deleteWrapper);

        List<CertificateInstanceItemReq> safeList = itemList == null ? Collections.emptyList() : itemList;
        long defaultSort = 1L;
        for (CertificateInstanceItemReq itemReq : safeList) {
            if (itemReq == null || StrUtil.isBlank(itemReq.getItemName())) {
                continue;
            }
            CertificateInstanceItemEntity itemEntity = new CertificateInstanceItemEntity();
            itemEntity.setId(FtbUtil.getId());
            itemEntity.setInstanceId(instanceId);
            itemEntity.setTemplateItemId(trimToNull(itemReq.getTemplateItemId()));
            itemEntity.setItemName(trimToNull(itemReq.getItemName()));
            itemEntity.setItemType(itemReq.getItemType());
            itemEntity.setItemValue(trimToNull(itemReq.getItemValue()));
            itemEntity.setSorts(itemReq.getSorts() == null ? defaultSort : itemReq.getSorts());
            itemEntity.setEnabledMark(0);
            certificateInstanceItemMapper.insert(itemEntity);
            defaultSort++;
        }
    }

    /**
     * 根据实例ID查询营业执照扩展信息。
     */
    private CertificateBusinessLicenseExtEntity queryBusinessLicenseExt(String instanceId) {
        LambdaQueryWrapper<CertificateBusinessLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(CertificateBusinessLicenseExtEntity::getInstanceId, instanceId);
        wrapper.eq(CertificateBusinessLicenseExtEntity::getEnabledMark, 0);
        wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getLastModifyTime);
        wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getCreatorTime);
        List<CertificateBusinessLicenseExtEntity> extList = certificateBusinessLicenseExtMapper.selectList(wrapper);
        return CollUtil.isEmpty(extList) ? null : extList.get(0);
    }

    /**
     * 根据实例ID查询食品许可扩展信息。
     */
    private CertificateHygieneLicenseExtEntity queryHygieneLicenseExt(String instanceId) {
        LambdaQueryWrapper<CertificateHygieneLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(CertificateHygieneLicenseExtEntity::getInstanceId, instanceId);
        wrapper.eq(CertificateHygieneLicenseExtEntity::getEnabledMark, 0);
        wrapper.orderByDesc(CertificateHygieneLicenseExtEntity::getLastModifyTime);
        wrapper.orderByDesc(CertificateHygieneLicenseExtEntity::getCreatorTime);
        List<CertificateHygieneLicenseExtEntity> extList = certificateHygieneLicenseExtMapper.selectList(wrapper);
        return CollUtil.isEmpty(extList) ? null : extList.get(0);
    }

    /**
     * 查询有效证照实例。
     */
    private CertificateInstanceEntity queryActiveEntity(String id) {
        CertificateInstanceEntity entity = certificateInstanceMapper.selectById(id);
        ServiceException.notNull(entity, "证照数据不存在");
        ServiceException.isTrue(Integer.valueOf(0).equals(entity.getEnabledMark()), "证照数据不存在");
        return entity;
    }

    /**
     * 查询实例并校验证照类型。
     */
    private CertificateInstanceEntity queryAndAssertType(String certificateInstanceId, CertificateTypeEnum expectType, String typeName) {
        ServiceException.isTrue(StrUtil.isNotBlank(certificateInstanceId), "证照实例ID不能为空");
        CertificateInstanceEntity entity = queryActiveEntity(StrUtil.trim(certificateInstanceId));
        ServiceException.isTrue(StrUtil.equalsIgnoreCase(StrUtil.trim(entity.getCertificateType()), expectType.getType()),
                "当前证照不是" + typeName);
        return entity;
    }

    /**
     * 解析日期字符串。
     */
    private Date parseDate(String dateText, String fieldName) {
        if (StrUtil.isBlank(dateText)) {
            return null;
        }
        try {
            return DateUtil.parseDate(StrUtil.trim(dateText));
        } catch (Exception e) {
            throw new ServiceException(fieldName + "格式不正确，正确格式为yyyy-MM-dd");
        }
    }

    /**
     * 解析日期时间戳
     */
    private Date parseDate(Long dateTimestamp, String fieldName) {
        if (Objects.isNull(dateTimestamp) || dateTimestamp <= 0L) {
            return null;
        }
        try {
            return new Date(dateTimestamp);
        } catch (Exception e) {
            throw new ServiceException(fieldName + "格式不正确，正确格式为yyyy-MM-dd");
        }
    }

    /**
     * 计算证照状态。
     */
    private Integer calculateStatus(Integer isLongTerm, Date expireDate) {
        if (Integer.valueOf(1).equals(isLongTerm)) {
            return STATUS_NORMAL;
        }
        if (expireDate == null) {
            return STATUS_MISSING;
        }
        Date today = DateUtil.beginOfDay(DateUtil.date());
        Date target = DateUtil.beginOfDay(expireDate);
        if (target.before(today)) {
            return STATUS_EXPIRED;
        }
        long daysDiff = DateUtil.betweenDay(today, target, false);
        if (daysDiff <= NEAR_EXPIRE_DAYS) {
            return STATUS_NEAR_EXPIRE;
        }
        return STATUS_NORMAL;
    }

    /**
     * 状态转中文名称。
     */
    private String resolveStatusName(Integer status) {
        if (Integer.valueOf(STATUS_MISSING).equals(status)) {
            return "缺失";
        }
        if (Integer.valueOf(STATUS_EXPIRED).equals(status)) {
            return "过期";
        }
        if (Integer.valueOf(STATUS_NEAR_EXPIRE).equals(status)) {
            return "临期";
        }
        if (Integer.valueOf(STATUS_NORMAL).equals(status)) {
            return "正常";
        }
        return "-";
    }

    /**
     * 字符串去空格，空串按null处理。
     */
    private String trimToNull(String value) {
        String trimValue = StrUtil.trim(value);
        return StrUtil.isBlank(trimValue) ? null : trimValue;
    }
}

