package cn.com.countrygarden.bi.main.service.mediaResource.impl;

import cn.com.countrygarden.bi.main.constant.mediaResource.MediaResourceConstant;
import cn.com.countrygarden.bi.main.dao.mediaResource.BasicInfoMapper;
import cn.com.countrygarden.bi.main.dao.mediaResource.MediaOrderBillMapper;
import cn.com.countrygarden.bi.main.dao.mediaResource.MediaOrderCycleMapper;
import cn.com.countrygarden.bi.main.dao.mediaResource.MediaResourceNewMapper;
import cn.com.countrygarden.bi.main.dao.mediaResource.ScheduleBasicInfoMapper;
import cn.com.countrygarden.bi.main.dto.mediaResource.MediaCycleDto;
import cn.com.countrygarden.bi.main.dto.mediaResource.MediaResourceDto;
import cn.com.countrygarden.bi.main.exception.ServiceException;
import cn.com.countrygarden.bi.main.model.mediaResource.AdvertisingResources;
import cn.com.countrygarden.bi.main.model.mediaResource.MediaOrderBill;
import cn.com.countrygarden.bi.main.model.mediaResource.Regional;
import cn.com.countrygarden.bi.main.model.twerp.hm.TbSysUser;
import cn.com.countrygarden.bi.main.service.mediaResource.BasicInfoService;
import cn.com.countrygarden.bi.main.service.mediaResource.MediaCommonService;
import cn.com.countrygarden.bi.main.service.mediaResource.MediaResourceNewService;
import cn.com.countrygarden.bi.main.service.twerp.hm.TbSysUserService;
import cn.com.countrygarden.bi.main.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * <pre>
 *  公共内容
 * </pre>
 *
 * @author ferren  liao-r@neusoft.com
 * @version 1.00.00
 * <p>
 * <p>
 * <pre>
 * 修改记录
 *    修改后版本:     修改人：  修改日期:     修改内容:
 * </pre>
 */
@Service
public class MediaCommonServiceImpl implements MediaCommonService {
    @Autowired
    private MediaOrderCycleMapper mediaOrderCycleMapper;
    @Autowired
    private MediaOrderBillMapper mediaOrderBillMapper;
    @Autowired
    private ScheduleBasicInfoMapper scheduleBasicInfoMapper;
    @Autowired
    private TbSysUserService tbSysUserService;
    @Autowired
    private MediaResourceNewMapper mediaResourceNewMapper;
    @Autowired
	private BasicInfoMapper basicInfoMapper;
    
    @Autowired
    private BasicInfoService basicInfoService;

    private final BigDecimal mondayDay = new BigDecimal(30);

    @Override
    public Map<String, Object> checkBill(MediaCycleDto param) {
        Date startDate = param.getCycleStartDate();
        Date endDate = param.getCycleEndDate();
        String mediaId = param.getMediaId();

        MediaResourceDto resources = mediaResourceNewMapper.selectByPrimaryKey(mediaId);

        MediaOrderBill orderBill = mediaOrderBillMapper.selectByPrimaryKey(param.getOrderBillId());
        if (orderBill == null) {
            throw new ServiceException("不存在该订单");
        }

        Date orderBillStartDate = orderBill.getOrderBillStartDate();
        Date orderBillEndDate = orderBill.getOrderBillEndDate();

        /*if (startDate.before(orderBillStartDate)) {
            int num = mediaOrderCycleMapper.findUseNum(startDate, orderBillStartDate, mediaId);
            if (num > 0) {
                throw new ServiceException("该时间段"+DateUtil.simpleFormat(startDate)+" "+DateUtil.simpleFormat(orderBillStartDate)+"资源已被占用,占用天数" + num);
            }
        }
        if (endDate.after(orderBillEndDate)) {
            int num = mediaOrderCycleMapper.findUseNum(orderBillEndDate, endDate, mediaId);
            if (num > 0) {
                throw new ServiceException("该时间段"+DateUtil.simpleFormat(orderBillEndDate)+" "+DateUtil.simpleFormat(endDate)+"资源已被占用,占用天数" + num);
            }
        }*/

        Integer mediaType = Integer.parseInt(param.getMediaType());
        Integer mediaWidth = 0;
        if (StringUtils.hasText(param.getMediaWidth())) {
            mediaWidth = Integer.parseInt(param.getMediaWidth());
        }
        Integer mediaHeight = 0;
        if (StringUtils.hasText(param.getMediaWidth())) {
            mediaHeight = Integer.parseInt(param.getMediaHeight());
        }
        BigDecimal unitAmount = calculateUnitAmount(startDate, endDate, mediaType, strToInteger(resources.getMediaForm(), 0), param.getOrderBillAmount(), mediaWidth, mediaHeight);
        Map<String, Object> map = new HashMap<>();
        map.put("orderBillUnitAmount", unitAmount);
        return map;
    }

    @Override
    public BigDecimal calculateUnitAmount(Date startDate, Date endDate,
                                          int mediaType, int mediaForm, BigDecimal billAmount,
                                          int mediaWidth, int mediaHeight) {
        if (billAmount == null || billAmount.equals(new BigDecimal(0))) {
            return new BigDecimal(0);
        }
        int day = this.dayDiff(startDate, endDate);
        BigDecimal billUnitAmount = null;
        if (isCalculateByArea(mediaType, mediaForm)) {
            billUnitAmount = calculateByArea(billAmount, day, mediaWidth, mediaHeight);
        } else {
            billUnitAmount = calculateByNumber(billAmount, day);
        }
        return billUnitAmount;
    }

    /**
     * str转换为int
     */
    private Integer strToInteger(String str, Integer defaultInt){
        if (!StringUtils.hasText(str)) {
            // todo 换为日志记录
            System.out.println("str转换数据为空");
            return defaultInt;
        } else {
            return Integer.parseInt(str);
        }
    }

    @Override
    public BigDecimal calculateBillAmount(Date startDate, Date endDate,
                                          int mediaType, int mediaForm, BigDecimal unitAmount,
                                          int mediaWidth, int mediaHeight) {
        if (unitAmount == null || unitAmount.equals(new BigDecimal(0))) {
            return new BigDecimal(0);
        }
        int day = this.dayDiff(startDate, endDate);
        BigDecimal dayDecimal = new BigDecimal(day);
        BigDecimal billAmount = null;
        // 注意计算方式的顺序,也会导致精度缺失问题
        if (isCalculateByArea(mediaType, mediaForm)) {
            billAmount = unitAmount
                    .multiply(dayDecimal)
                    .multiply(new BigDecimal(mediaWidth)
                            .multiply(new BigDecimal(mediaHeight)
                                    .divide(new BigDecimal(1000 * 1000))))
                    .divide(mondayDay, 4, BigDecimal.ROUND_HALF_UP);
        } else {
            billAmount = dayDecimal
                    .multiply(unitAmount)
                    .divide(mondayDay, 4, BigDecimal.ROUND_HALF_UP);
        }
        return billAmount.setScale(4, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 是否通过面积计算
     * @param mediaType
     * @return
     */
    private boolean isCalculateByArea(int mediaType, int mediaForm){
        switch (mediaType) {
            case MediaResourceConstant.MEDIA_TYPE.DX:
                if (MediaResourceConstant.MEDIA_FORM.HW_GD_DX == mediaForm ||
                        MediaResourceConstant.MEDIA_FORM.SNGDDX == mediaForm) {
                    return true;
                } else {
                    return false;
                }
            case MediaResourceConstant.MEDIA_TYPE.DP:
                return true;
            case MediaResourceConstant.MEDIA_TYPE.QT:
                if (MediaResourceConstant.MEDIA_TYPE.QT == mediaType) {
                    if (MediaResourceConstant.MEDIA_FORM.DQB == mediaForm ||
                            MediaResourceConstant.MEDIA_FORM.MQ == mediaForm) {
                        return true;
                    } else {
                        return false;
                    }
                }
            case MediaResourceConstant.MEDIA_TYPE.BTL:
                // 步梯楼广告 -> 室内固定灯箱 地贴 玻璃贴 通过面积计算
                if (MediaResourceConstant.MEDIA_TYPE.BTL == mediaType) {
                    if (MediaResourceConstant.MEDIA_FORM.SNGDDX == mediaForm ||
                        MediaResourceConstant.MEDIA_FORM.DQB == mediaForm ||
                            MediaResourceConstant.MEDIA_FORM.MQ == mediaForm) {
                        return true;
                    } else {
                        return false;
                    }
                }
            default:
                return false;
        }
    }

    @Override
    public List<Map<String, String>> getOrderStatusType() {
        Set<Map.Entry<Integer, String>> entries = MediaResourceConstant.ORDER_STATUS_TYPE.DES.entrySet();
        Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();
        List<Map<String, String>> mapList = new ArrayList<>();
        while (iterator.hasNext()){
            Map.Entry<Integer, String> next = iterator.next();
            Map<String, String> map = new HashMap<>();
            map.put("code", next.getKey().toString());
            map.put("value", next.getValue());
            mapList.add(map);
        }
        return mapList;
    }

    @Override
    public boolean isAdminRole() {
        TbSysUser currentSysUser = tbSysUserService.getCurrentSysUser();
        int count = scheduleBasicInfoMapper.findUserRole(currentSysUser.getUserCode(),MediaResourceConstant.roleCode);
        return count != 0;
    }

    @Override
    public boolean isAreaRole() {
        TbSysUser currentSysUser = tbSysUserService.getCurrentSysUser();
        int count = scheduleBasicInfoMapper.findUserRole(currentSysUser.getUserCode(),"mediaResource_area");
        return count != 0;
    }

    @Override
    public int dayDiff(Date startDate, Date endDate) {
        int i = DateUtil.diffDay(startDate, endDate);
        return i + 1;
    }

    /**
     * 通过面积进行计算
     * 合同金额/投放天数*30天/面积
     */
    private BigDecimal calculateByArea(BigDecimal orderBillAmount, int day, int width, int height) {
        if (orderBillAmount == null || orderBillAmount.equals(new BigDecimal(0))) {
            return new BigDecimal(0);
        }
        // 注: 先乘 后除精确度更大
        BigDecimal dayDecimal = new BigDecimal(day);
        BigDecimal squareMeterArea = new BigDecimal(width).multiply(new BigDecimal(height)).divide(new BigDecimal(1000 * 1000));
        BigDecimal unitAmount = orderBillAmount
                .multiply(mondayDay)
                .divide(squareMeterArea.multiply(dayDecimal), 4, BigDecimal.ROUND_HALF_UP);
        return unitAmount;
    }

    /**
     * 通过数量进行计算
     * 合同金额/投放天数/30天/媒体数量
     */
    private BigDecimal calculateByNumber(BigDecimal orderBillAmount, int day) {
        // 注: 先乘 后除精确度更大
        BigDecimal dayDecimal = new BigDecimal(day);
        BigDecimal unitAmount = orderBillAmount
                .multiply(mondayDay)
                .divide(dayDecimal, 4, BigDecimal.ROUND_HALF_UP);
        return unitAmount;
    }

	@Override
	public List<Regional> findCompany(String accessToken) {
		TbSysUser user = basicInfoService.findErpUser(accessToken);
		List<Regional> findCompany = basicInfoMapper.findCompany(user.getUserCode());
		return findCompany;
	}


}
