package com.tofly.feesapi.bmgl.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.feesapi.common.constant.JtjslxEnum;
import com.tofly.feesapi.bmgl.entity.BmSj;
import com.tofly.feesapi.bmgl.entity.BmYslx;
import com.tofly.feesapi.bmgl.entity.dto.BmSjFilter;
import com.tofly.feesapi.bmgl.entity.dto.BmSjInsert;
import com.tofly.feesapi.bmgl.entity.dto.BmSjSelectDto;
import com.tofly.feesapi.bmgl.entity.dto.BmSjUpdate;
import com.tofly.feesapi.bmgl.entity.vo.BmSjSelect;
import com.tofly.feesapi.bmgl.entity.vo.BmSjView;
import com.tofly.feesapi.bmgl.mapper.BmSjMapper;
import com.tofly.feesapi.bmgl.service.BmSjService;
import com.tofly.feesapi.bmgl.service.BmYslxService;
import com.tofly.feesapi.bmgl.service.IBmSjlsService;
import com.tofly.feesapi.common.core.dto.PageDto;
import com.tofly.feesapi.common.core.vo.PageResult;
import com.tofly.feesapi.common.exception.FeesErrorCode;
import com.tofly.feesapi.common.exception.FeesException;

import com.tofly.feesapi.security.util.SecurityUtils;
import com.tofly.feesapi.udb.entity.Company;
import com.tofly.feesapi.udb.service.ICompanyService;
import com.tofly.feesapi.udb.service.IUserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service("bmSjService")
public class BmSjServiceImpl extends ServiceImpl<BmSjMapper, BmSj> implements BmSjService {

    @Autowired
    private BmYslxService bmYslxService;
    @Autowired
    private IBmSjlsService bmSjlsService;
    @Autowired
    private IUserService userService;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Override
    public BmSjView getViewById(String code) {
        if (StringUtils.isEmpty(code)) throw new FeesException("水价编码不能为空", FeesErrorCode.BUSINESS_ERROR);
        BmSj bmSj = this.getById(code);
        if (bmSj == null)
            throw new FeesException(String.format("水价编码(%s)不存在", code), FeesErrorCode.BUSINESS_ERROR);
        BmSjView view = new BmSjView();
        BeanUtils.copyProperties(bmSj, view);
        return view;
    }

    @Override
    public boolean update(BmSjUpdate update) {
        String code = update.getCode();
        if (StringUtils.isEmpty(code)) {
            throw new FeesException("水价编码不能为空", FeesErrorCode.BUSINESS_ERROR);
        }

        BmSj bmSj = this.getById(code);
        if (bmSj == null) {
            throw new FeesException(String.format("水价编码(%s)不存在", code), FeesErrorCode.BUSINESS_ERROR);
        }

        BeanUtils.copyProperties(update, bmSj);
        bmSj.setXgrq(LocalDateTime.now());

        check(bmSj);

        transactionTemplate.execute((status) -> {
            try {
                this.updateById(bmSj);
                bmSjlsService.save(bmSj);
            } catch (Exception e) {
                status.setRollbackOnly();
                throw e;
            }
            return 1;
        });
        return true;
    }

    @Override
    public boolean delById(String code) {
        if (StringUtils.isEmpty(code)) throw new FeesException("水价编码不能为空", FeesErrorCode.BUSINESS_ERROR);
        BmSj bmSj = this.getById(code);
        if (bmSj == null)
            throw new FeesException(String.format("水价编码(%s)不存在", code), FeesErrorCode.BUSINESS_ERROR);
        return this.removeById(code);
    }

    @Override
    public boolean delByIds(List<String> codes) {
        codes.forEach(code -> delById(code));
        return true;
    }

    @Override
    public boolean save(BmSjInsert insert) {
        BmSj bmSj = new BmSj();
        Integer maxCode = getMaxCode();
        bmSj.setCode(String.valueOf(maxCode + 1));
        BeanUtils.copyProperties(insert, bmSj);
        String czry = String.valueOf(SecurityUtils.getUserId());
        bmSj.setCzry(czry);
        
        LocalDateTime now = LocalDateTime.now();
        bmSj.setCzsj(now);
        bmSj.setXgrq(now);
        check(bmSj);
        transactionTemplate.execute((status) -> {
            try {
                this.save(bmSj);
                bmSjlsService.save(bmSj);
            } catch (Exception e) {
                status.setRollbackOnly();
                throw e;
            }
            return 1;
        });
        return true;
    }

    private Integer getMaxCode() {
        return this.baseMapper.selectMaxId();
    }

    private void check(BmSj bmSj) {
        if (StringUtils.isEmpty(bmSj.getCode())) {
            throw new FeesException("水价编号不能为空", FeesErrorCode.BUSINESS_ERROR);
        }

        String ssgs = bmSj.getSsgs();
        if (StringUtils.isEmpty(ssgs)) {
            throw new FeesException("所属公司编码不能为空", FeesErrorCode.BUSINESS_ERROR);
        } else {
            Company company = companyService.getById(Long.valueOf(ssgs));
            if (company == null)
                throw new FeesException(String.format("所属公司编码(%s)不存在", ssgs), FeesErrorCode.BUSINESS_ERROR);
        }

        String yslx = bmSj.getYslx();
        if (StringUtils.isEmpty(yslx)) {
            throw new FeesException("用水类型编码不能为空", FeesErrorCode.BUSINESS_ERROR);
        } else {
            BmYslx bmYslx = bmYslxService.getById(yslx);
            if (bmYslx == null)
                throw new FeesException(String.format("用水类型编码(%s)不存在", yslx), FeesErrorCode.BUSINESS_ERROR);
        }
        String jtbz = bmSj.getJtbz();
        if (StringUtils.isEmpty(jtbz)) {
            throw new FeesException("阶梯标志不能为空", FeesErrorCode.BUSINESS_ERROR);
        }
        if ("0".equals(jtbz) && bmSj.getSj() == null) {
            if (bmSj.getSj().compareTo(BigDecimal.ZERO) <= 0) {
                throw new FeesException("水价应大于0", FeesErrorCode.BUSINESS_ERROR);
            }
            throw new FeesException("水价不能为空", FeesErrorCode.BUSINESS_ERROR);
        }
        if ("1".equals(jtbz)) {
            JtjslxEnum jtjslx = bmSj.getJtjslx();
            if (jtjslx == null) throw new FeesException("阶梯计算类型不能为空", FeesErrorCode.BUSINESS_ERROR);
            BigDecimal jt1Sj = bmSj.getJt1Sj();
            if (jt1Sj == null) throw new FeesException("阶梯1水价不能为空", FeesErrorCode.BUSINESS_ERROR);
            BigDecimal jt1Zs = bmSj.getJt1Zs();
            if (jt1Zs == null) throw new FeesException("阶梯1止数不能为空", FeesErrorCode.BUSINESS_ERROR);

            BigDecimal jt2Zs = bmSj.getJt2Zs();
            BigDecimal jt2Sj = bmSj.getJt2Sj();
            if (!jt2Zs.equals(BigDecimal.ZERO)) {
                if (jt2Zs.compareTo(jt1Zs) <= 0)
                    throw new FeesException("阶梯2止数不能小于等于阶梯1止数", FeesErrorCode.BUSINESS_ERROR);
                if (jt2Sj == null) throw new FeesException("阶梯2水价不能为空", FeesErrorCode.BUSINESS_ERROR);
            }
            BigDecimal jt3Zs = bmSj.getJt3Zs();
            BigDecimal jt3Sj = bmSj.getJt2Sj();
            if (!jt3Zs.equals(BigDecimal.ZERO)) {
                if (jt3Zs.compareTo(jt2Zs) <= 0)
                    throw new FeesException("阶梯3止数不能小于等于阶梯2止数", FeesErrorCode.BUSINESS_ERROR);
                if (jt3Sj == null) throw new FeesException("阶梯3水价不能为空", FeesErrorCode.BUSINESS_ERROR);
            }
            BigDecimal jt4Zs = bmSj.getJt4Zs();
            BigDecimal jt4Sj = bmSj.getJt2Sj();
            if (!jt4Zs.equals(BigDecimal.ZERO)) {
                if (jt4Zs.compareTo(jt3Zs) <= 0)
                    throw new FeesException("阶梯4止数不能小于等于阶梯3止数", FeesErrorCode.BUSINESS_ERROR);
                if (jt4Sj == null) throw new FeesException("阶梯4水价不能为空", FeesErrorCode.BUSINESS_ERROR);
            }
        }
    }

    @Override
    public PageResult<BmSjSelect> getPage(PageDto pageDto, BmSjFilter filter) {
        PageDto<BmSjSelectDto> page = this.baseMapper.getPage(pageDto, filter);
        PageResult<BmSjSelectDto> pageResult = page.toVo();
        List<BmSjSelectDto> records = pageResult.getRecords();
        List<BmSjSelect> bmSjSelects = getBmSjSelects(records);
        return new PageResult<>(pageResult.getTotal(), bmSjSelects);
    }

    private List<BmSjSelect> getBmSjSelects(List<BmSjSelectDto> records) {
        List<BmSjSelect> bmSjSelects = records.stream()
                .map(r -> {
                    BmSjSelect bmSjSelect = new BmSjSelect();
                    BeanUtils.copyProperties(r, bmSjSelect);
                    String ssgs = r.getSsgs();
                    if (ssgs != null) {
                        Company company = companyService.get(Long.valueOf(ssgs));
                        bmSjSelect.setSsgsmc(company.getCompanyName());
                    }
                    bmSjSelect.setSzyfdj(String.format("%.2f", r.getSzyfdj()));
                    bmSjSelect.setLjfdj(String.format("%.2f", r.getLjfdj()));
                    bmSjSelect.setWsfdj(String.format("%.2f", r.getWsfdj()));
                    bmSjSelect.setJtrksl(String.format("%.2f", r.getJtrksl()));
                    bmSjSelect.setJtrkjs(String.format("%.2f", r.getJtrkjs()));
                    bmSjSelect.setHjtsj(createHjtsj(r, "<br/>"));
                    return bmSjSelect;
                })
                .collect(Collectors.toList());
        return bmSjSelects;
    }

    private List<BmSjSelect> getBmSjSelects2(List<BmSjSelectDto> records) {
        List<BmSjSelect> bmSjSelects = records.stream()
                .map(r -> {
                    BmSjSelect bmSjSelect = new BmSjSelect();
                    BeanUtils.copyProperties(r, bmSjSelect);
                    String ssgs = r.getSsgs();
                    if (ssgs != null) {
                        Company company = companyService.get(Long.valueOf(ssgs));
                        bmSjSelect.setSsgsmc(company.getCompanyName());
                    }
                    bmSjSelect.setSzyfdj(String.format("%.2f", r.getSzyfdj()));
                    bmSjSelect.setLjfdj(String.format("%.2f", r.getLjfdj()));
                    bmSjSelect.setWsfdj(String.format("%.2f", r.getWsfdj()));
                    bmSjSelect.setJtrksl(String.format("%.2f", r.getJtrksl()));
                    bmSjSelect.setJtrkjs(String.format("%.2f", r.getJtrkjs()));
                    bmSjSelect.setHjtsj(createHjtsj2(r, "；"));
                    return bmSjSelect;
                })
                .collect(Collectors.toList());
        return bmSjSelects;
    }

    @Override
    public List<BmSjSelect> getList(BmSjFilter filter) {
        filter.setIsdisabled("1");
        List<BmSjSelectDto> list = this.baseMapper.getList(filter);
        return getBmSjSelects2(list);
    }

    @Override
    public List<BmSjSelect> getList() {
        return this.getList(new BmSjFilter());
    }

    @Override
    public List<BmSj> selectListMap() {
        LambdaQueryWrapper<BmSj> wrapper = Wrappers.<BmSj>lambdaQuery()
                .eq(BmSj::getIsdisabled, "1")
                .orderByAsc(BmSj::getCode);
        List<BmSj> bmSjs = baseMapper.selectList(wrapper);

        if (CollectionUtil.isNotEmpty(bmSjs)) {
            bmSjs = bmSjs.stream().sorted(Comparator.comparing(o -> Integer.valueOf(o.getCode())))
                    .collect(Collectors.toList());
        }

        return bmSjs;
    }

    private String createHjtsj(BmSjSelectDto sj, String delimiter) {
        String jtbz = sj.getJtbz();
        if ("0".equals(jtbz)) {
            return String.format("%.2f", sj.getSj());
        } else {
            List<String> jts = new ArrayList<>();
            if (sj.getJt1Zs() != null && sj.getJt1Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("阶梯一: 单价一(%.2f) 水量(0~%.0f)", sj.getJt1Sj(), sj.getJt1Zs()));
            }
            if (sj.getJt2Zs() != null && sj.getJt2Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("阶梯二: 单价一(%.2f) 水量(%.0f~%.0f)", sj.getJt2Sj(), sj.getJt1Zs(), sj.getJt2Zs()));
            }
            if (sj.getJt3Zs() != null && sj.getJt3Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("阶梯三: 单价一(%.2f) 水量(%.0f~%.0f)", sj.getJt3Sj(), sj.getJt2Zs(), sj.getJt3Zs()));
            }
            if (sj.getJt4Zs() != null && sj.getJt4Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("阶梯四: 单价一(%.2f) 水量(%.0f~%.0f)", sj.getJt4Sj(), sj.getJt3Zs(), sj.getJt4Zs()));
            }
            return String.join(delimiter, jts);
        }
    }

    private String createHjtsj2(BmSjSelectDto sj, String delimiter) {
        String jtbz = sj.getJtbz();
        if ("0".equals(jtbz)) {
            return String.format("单价:%.2f元/方", sj.getSj());
        } else {
            List<String> jts = new ArrayList<>();
            if (sj.getJt1Zs() != null && sj.getJt1Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("一阶:%.2f元/方", sj.getJt1Sj()));
            }
            if (sj.getJt2Zs() != null && sj.getJt2Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("二阶:%.2f元/方", sj.getJt2Sj()));
            }
            if (sj.getJt3Zs() != null && sj.getJt3Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("三阶:%.2f元/方", sj.getJt3Sj()));
            }
            if (sj.getJt4Zs() != null && sj.getJt4Zs().compareTo(BigDecimal.ZERO) > 0) {
                jts.add(String.format("四阶:%.2f元/方", sj.getJt4Sj()));
            }
            return String.join(delimiter, jts);
        }
    }
}
