package com.dayou.service.impl;

import cn.hutool.core.util.StrUtil;
import com.dayou.common.BaseEntity;
import com.dayou.dto.TakeNumberDTO;
import com.dayou.entity.BusinessNumber;
import com.dayou.enums.MainBusinessEnum;
import com.dayou.enums.TakeNumberEnum;
import com.dayou.exception.ErrorCode;
import com.dayou.mapper.BusinessNumberMapper;
import com.dayou.mapper.MajorProductionMapper;
import com.dayou.service.IBusinessNumberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dayou.utils.DateUtils;
import com.dayou.vo.IdNameVO;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;

import static com.dayou.common.Constants.*;
import static com.dayou.enums.MainBusinessEnum.ALL_BUSINESS;
import static com.dayou.enums.MainBusinessEnum.ASSET_BUSINESS;
import static com.dayou.enums.TakeNumberEnum.ORDER_NUMBER;

/**
 * <p>
 * 业务号 服务实现类
 * </p>
 *
 * @author wucl
 * @since 2023-11-06
 */
@Service
public class BusinessNumberServiceImpl extends ServiceImpl<BusinessNumberMapper, BusinessNumber> implements IBusinessNumberService {

    private static DecimalFormat zero4 = new DecimalFormat("0000");

    private static DecimalFormat zero3 = new DecimalFormat("000");

    private static DecimalFormat zero2 = new DecimalFormat("00");
    private final MajorProductionMapper majorProductionMapper;


    public BusinessNumberServiceImpl(MajorProductionMapper majorProductionMapper) {
        this.majorProductionMapper = majorProductionMapper;
    }

    @Override
    public synchronized String takeMainNumber(TakeNumberDTO taskRecordDTO) {
        TakeNumberEnum takeType = taskRecordDTO.getTakeType();
        MainBusinessEnum businessType = taskRecordDTO.getBusinessType();
        Integer year = taskRecordDTO.getYear();
        int number ;
        BusinessNumber busNumber  = null;

        busNumber = this.getOne(new LambdaQueryWrapper<BusinessNumber>().eq(BusinessNumber::getTakeType, takeType).eq(BusinessNumber::getBusinessType, businessType)
                .eq(BusinessNumber::getYear, year).eq(BaseEntity::getDeleted, Boolean.FALSE));
        if (busNumber==null){
            busNumber = new BusinessNumber();
            busNumber.setTakeType(takeType.name());
            busNumber.setBusinessType(businessType.name());
            busNumber.setYear(year);
            busNumber.setNextNo(1);
            this.save(busNumber);
            number = busNumber.getNextNo();
        }
        else {
            number = busNumber.getNextNo();
        }

        this.update(new LambdaUpdateWrapper<BusinessNumber>().set(BusinessNumber::getNextNo,(number+1)).eq(BaseEntity::getId,busNumber.getId()));

        //格式化
        //大中型取土地号
        if (takeType.equals(TakeNumberEnum.LAND_NUMBER) && businessType.equals(MainBusinessEnum.MAJOR_BUSINESS)){
            return LAND_NUMBER_FORMAT.replace(YEAR, String.valueOf(year)).replace(NUMBER, zero3.format(number));
        }
        //大中型取房地产号
        if (takeType.equals(TakeNumberEnum.REALTY_NUMBER) && businessType.equals(MainBusinessEnum.MAJOR_BUSINESS)){
            String yearNumber = year + zero4.format(number);
            return REALTY_NUMBER_FORMAT.replace(NUMBER, yearNumber);
        }
        ErrorCode.throwBusinessException(ErrorCode.PARAM_ERROR);
        return null;
    }

    @Override
    public synchronized List<IdNameVO>  takeSubNumber(TakeNumberDTO taskRecordDTO,String mainNumber) {
        if (StrUtil.isEmpty(mainNumber)){
            mainNumber = takeMainNumber(taskRecordDTO);
        }
        return generateSubNumber(mainNumber,taskRecordDTO.getTargets());

    }

    @Override
    public synchronized String takeOrderNumber() {
        Date now = new Date();
        int year = DateUtils.getYear(now);
        int month = DateUtils.getMonth(now);
        BusinessNumber exist = null;
        int number;
        exist = this.getOne(new LambdaQueryWrapper<BusinessNumber>().eq(BusinessNumber::getTakeType, ORDER_NUMBER).eq(BusinessNumber::getBusinessType, ALL_BUSINESS)
                .eq(BusinessNumber::getYear, year).eq(BusinessNumber::getMonth, month).eq(BaseEntity::getDeleted, Boolean.FALSE));
        if (exist==null){
            exist = new BusinessNumber();
            exist.setTakeType(ORDER_NUMBER.name());
            exist.setBusinessType(ALL_BUSINESS.name());
            exist.setYear(year);
            exist.setNextNo(1);
            exist.setMonth(month);
            this.save(exist);
            number = exist.getNextNo();
        }
        number = exist.getNextNo();
        this.update(new LambdaUpdateWrapper<BusinessNumber>().set(BusinessNumber::getNextNo,(number+1)).eq(BaseEntity::getId,exist.getId()));
        //格式化 订单号取号：年份4位月份2位序号4位(全局唯一)
        return new StringBuffer().append(year).append(zero2.format(month)).append(zero4.format(number)).toString();
    }

    @Override
    public synchronized String takeStatementMainNumber(String orderId, TakeNumberEnum takeNumberEnum) {
        if (takeNumberEnum.equals(TakeNumberEnum.LAND_NUMBER)){
            return STATEMENT_LAND_FORMAT.replace(NUMBER, orderId);
        }
        if (takeNumberEnum.equals(TakeNumberEnum.REALTY_NUMBER)){
            return STATEMENT_REALTY_FORMAT.replace(NUMBER, orderId);
        }
        ErrorCode.throwBusinessException(ErrorCode.PARAM_ERROR);
        return null;
    }

    @Override
    public synchronized List<IdNameVO> takeStatementSubNumber(String orderId, TakeNumberEnum takeNumberEnum, String mainNumber,List<IdNameVO> targets) {
        if (StrUtil.isEmpty(mainNumber)){
            mainNumber = takeStatementMainNumber(orderId, takeNumberEnum);
        }
        return generateSubNumber(mainNumber,targets);

    }

    @Override
    public synchronized String takeLetterMainNumber(String orderId,TakeNumberEnum takeNumberEnum) {
        if (takeNumberEnum.equals(TakeNumberEnum.LAND_NUMBER)){
            return LETTER_LAND_FORMAT.replace(NUMBER, orderId);
        }
        if (takeNumberEnum.equals(TakeNumberEnum.REALTY_NUMBER)){
            return LETTER_REALTY_FORMAT.replace(NUMBER, orderId);
        }
        ErrorCode.throwBusinessException(ErrorCode.PARAM_ERROR);
        return null;
    }

    @Override
    public synchronized List<IdNameVO> takeLetterSubNumber(String orderId, TakeNumberEnum takeNumberEnum, String mainNumber,List<IdNameVO> targets,Long businessId) {
        if (StrUtil.isEmpty(mainNumber)){
            mainNumber = takeLetterMainNumber(orderId, takeNumberEnum);
        }
        return generateSubNumber(mainNumber,targets);
    }


    /**
     * 取项目编号
     * 资产项目订单号取号：年份4位 + 月份2位 + 序号3位(当月下单量)
     * 如: 2025010001
     * @return String
     */
    @Override
    public synchronized String takeAssetsOrderNumber() {
        Date now = new Date();
        int year = DateUtils.getYear(now);
        int month = DateUtils.getMonth(now);
        BusinessNumber exist = null;
        int number;
        //
        exist = this.getOne(new LambdaQueryWrapper<BusinessNumber>().eq(BusinessNumber::getTakeType, ORDER_NUMBER).eq(BusinessNumber::getBusinessType, ASSET_BUSINESS)
                .eq(BusinessNumber::getYear, year).eq(BusinessNumber::getMonth, month).eq(BaseEntity::getDeleted, Boolean.FALSE));
        if (exist==null){
            exist = new BusinessNumber();
            exist.setTakeType(ORDER_NUMBER.name());
            exist.setBusinessType(ASSET_BUSINESS.name());
            exist.setYear(year);
            exist.setNextNo(1);
            exist.setMonth(month);
            this.save(exist);
            number = exist.getNextNo();
        }
        number = exist.getNextNo();
        this.update(new LambdaUpdateWrapper<BusinessNumber>().set(BusinessNumber::getNextNo,(number+1)).eq(BaseEntity::getId,exist.getId()));
        // 格式化
        return new StringBuffer().append(year).append(zero2.format(month)).append(zero3.format(number)).toString();
    }

    /**
     * 在一个订单中按顺序取复评函号
     * @param businessId
     * @return
     */
    @Override
    public synchronized String takeLetterByOrder(Long businessId,String orderId,TakeNumberEnum takeNumberEnum) {
        String maxLetterNo = majorProductionMapper.findMaxLetterNoByBusinessId(businessId);
        if (StrUtil.isEmpty(maxLetterNo)){
            if (takeNumberEnum.equals(TakeNumberEnum.LAND_NUMBER)){
                return new StringBuffer(LETTER_LAND_FORMAT_X.replace(NUMBER, orderId)).append(BRI).append("1").append(HAO).toString();
            }else{
                return new StringBuffer(LETTER_REALTY_FORMAT_X.replace(NUMBER, orderId)).append(BRI).append("1").append(HAO).toString();
            }

        }else {
            String[] split = maxLetterNo.split(BRI);
            String mainNumber = split[0];
            Integer index = Integer.valueOf(split[1].replace(HAO,""));
            StringBuilder subNumber = new StringBuilder(mainNumber);
            return subNumber.append(BRI + (index + 1) + HAO).toString();
        }

    }

    /**
     * 根据主号生成字号
     * @param mainNumber
     * @param targets
     * @return
     */
    private synchronized List<IdNameVO> generateSubNumber(String mainNumber,List<IdNameVO> targets){
        if (StrUtil.isNotEmpty(mainNumber)){
            if (!mainNumber.contains(BRI)){
                int length = mainNumber.length();
                for (int i=0; i<targets.size(); i++){
                    StringBuilder subNumber = new StringBuilder(mainNumber);
                    targets.get(i).setName(subNumber.insert(length-1,BRI+1).toString());
                }
                return targets;
            }else {
                String[] split = mainNumber.split(BRI);
                mainNumber = split[0];
                Integer index = Integer.valueOf(split[1].replace(HAO,""));
                for (int i=0; i<targets.size(); i++){
                    StringBuilder subNumber = new StringBuilder(mainNumber);
                    String name = subNumber.append(BRI + (index + 1) + HAO).toString();
                    targets.get(i).setName(name);
                }
                return targets;
            }
        }
        ErrorCode.throwBusinessException(ErrorCode.PARAM_ERROR);
        return null;
    }
}
