package org.linlinjava.jz.service;

import com.google.common.collect.Lists;
import org.linlinjava.jz.core.util.DateTimeUtil;
import org.linlinjava.jz.db.domain.ContractSubTemplate;
import org.linlinjava.jz.db.util.hm.CalendarUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author fuxubing
 */
@Service
public class HmServantIncomeService {
    @Resource
    private HmEmployClockService hmEmployClockService;

    /**
     * 获取总收入
     *
     * @param hmEmployRelationId
     * @param contractSubTemplate
     * @param startTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public BigDecimal getTotalIncome(Long hmEmployRelationId, ContractSubTemplate contractSubTemplate, LocalDate startTime, LocalDate endTime) throws ParseException {

        //总收入
        BigDecimal money = BigDecimal.ZERO;

        if (null != contractSubTemplate.getMonthlySalary()) {
            money = getNoHourlyWorkerIncome(hmEmployRelationId, contractSubTemplate, startTime, endTime);
        }

        if (null != contractSubTemplate.getDaySalary()) {
            money = getSubstituteWorkerIncome(hmEmployRelationId, contractSubTemplate, startTime, endTime);
        }

        if (null != contractSubTemplate.getHourlySalary()) {
            money = getHourlyWorkerIncome(hmEmployRelationId, contractSubTemplate, startTime, endTime);
        }

        return money;
    }


    /**
     * 获取历史收入
     *
     * @param hmEmployRelationId
     * @param contractSubTemplate
     * @return
     * @throws Exception
     */
    public List<Map<String, Object>> getHistoryIncome(Long hmEmployRelationId, ContractSubTemplate contractSubTemplate) throws Exception {

        LocalDateTime serviceStartTime = contractSubTemplate.getServiceStartTime();
        LocalDateTime serviceEndTime = contractSubTemplate.getServiceEndTime();

        if (serviceEndTime.isAfter(LocalDateTime.now())) {
            serviceEndTime = LocalDateTime.now();
        }

        List<Map<String, Object>> mapList = Lists.newArrayList();

        String startTime = DateTimeUtil.localDateFormat(serviceStartTime, "yyyy-MM-dd");

        String endTime = DateTimeUtil.localDateFormat(serviceEndTime, "yyyy-MM-dd");

        List<String> monthBetween = DateTimeUtil.getMonthBetween(startTime, endTime);
        //本月
        if (CollectionUtils.isEmpty(monthBetween)) {
            LocalDate startDate = DateTimeUtil.firstDayOfMonth(LocalDate.now());
            LocalDate endDate = DateTimeUtil.lastDayOfMonth(LocalDate.now());
            Map<String, Object> map = new HashMap<>(16);
            BigDecimal totalIncome = getTotalIncome(hmEmployRelationId, contractSubTemplate, startDate, endDate);
            map.put("title", +startDate.getYear() + "-" + startDate.getMonthValue() + "  " + totalIncome + "元");
            map.put("size", 14);
            map.put("description", "进行中");
            map.put("yyyyMM", +startDate.getYear() + "年" + startDate.getMonthValue() + "月");
            map.put("income", totalIncome + "元");
            map.put("payDay", contractSubTemplate.getPayday());
            mapList.add(map);
        }

        AtomicInteger index = new AtomicInteger(0);

        AtomicInteger size = new AtomicInteger(monthBetween.size() - 1);

        monthBetween.forEach(item -> {
            int year = Integer.parseInt(item.substring(0, item.indexOf("-")));
            int month = Integer.parseInt(item.substring(item.indexOf("-") + 1));
            String startDate = CalendarUtil.getFirstDayOfMonth(year, month);
            String endDate = CalendarUtil.getLastDayOfMonth(year, month);

            Map<String, Object> map = new HashMap<>(16);
            BigDecimal totalIncome = null;
            try {
                totalIncome = getTotalIncome(hmEmployRelationId, contractSubTemplate, DateTimeUtil.strToLocalDate(startDate), DateTimeUtil.strToLocalDate(endDate));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            map.put("title", item + "  " + totalIncome + "元");
            //判断是否是本月
            String description;
            if (item.equals(DateTimeUtil.localDateFormat(LocalDateTime.now(), "yyyy-MM"))) {
                description = "进行中";
            } else if (item.equals(DateTimeUtil.localDateFormat(serviceStartTime, "yyyy-MM"))) {
                description = "服务开始月";
            } else {
                description = "第" + size.getAndDecrement() + "月";
            }
            map.put("description", description);
            map.put("size", 0 == index.get() ? 14 : 8);
            map.put("yyyyMM", +year + "年" + month + "月");
            map.put("income", totalIncome + "元");
            map.put("payDay", contractSubTemplate.getPayday());
            mapList.add(map);
            index.getAndDecrement();
        });
        return mapList;
    }


    /**
     * 获取每天打卡收入
     *
     * @param contractSubTemplate
     * @return
     * @throws ParseException
     */
    public BigDecimal getDayClockIncome(ContractSubTemplate contractSubTemplate) throws ParseException {
        BigDecimal clockMoney = BigDecimal.ZERO;

        //每月休息天数
        Integer monthRestDays = contractSubTemplate.getMonthRestDays();
        // 应工作天数
        int days = DateTimeUtil.getDayOfMonth() - monthRestDays;

        if (null != contractSubTemplate.getMonthlySalary()) {
            //月薪
            Long monthlySalary = contractSubTemplate.getMonthlySalary();
            //每次打卡收入金额
            clockMoney = new BigDecimal(monthlySalary / days);
        }

        if (null != contractSubTemplate.getDaySalary()) {
            clockMoney = new BigDecimal(contractSubTemplate.getDaySalary());
        }

        if (null != contractSubTemplate.getHourlySalary()) {
            //实际每次打卡收入金额
            BigDecimal hourlyMoney = new BigDecimal(contractSubTemplate.getHourlySalary());
            //获取每天工作时长
            long workHours = getWorkHours(contractSubTemplate.getDayWorkTime());
            clockMoney = hourlyMoney.multiply(new BigDecimal(workHours));
        }
        return clockMoney;
    }

    /**
     * 非钟点工收入
     *
     * @param hmEmployRelationId
     * @param contractSubTemplate
     * @return
     */
    private BigDecimal getNoHourlyWorkerIncome(Long hmEmployRelationId, ContractSubTemplate contractSubTemplate, LocalDate startTime, LocalDate endTime) {
        BigDecimal money;
        //每月休息天数
        Integer monthRestDays = contractSubTemplate.getMonthRestDays();
        // 应工作天数
        int days = DateTimeUtil.getDayOfMonth() - monthRestDays;
        //月薪
        Long monthlySalary = contractSubTemplate.getMonthlySalary();
        //每次打卡收入金额
        BigDecimal clockMoney = new BigDecimal(monthlySalary / days);
        //获取总的打卡天数
        int dayOfMonthClock = (int) hmEmployClockService.getDayOfMonthClock(hmEmployRelationId, startTime, endTime);
        //判断是否有加班 如果有判断是否是节假日加班还是休息日加班
        if (days - dayOfMonthClock >= 0 || null == contractSubTemplate.getOffMultiple() && null == contractSubTemplate.getWorkerMultiple()) {
            money = clockMoney.multiply(new BigDecimal(dayOfMonthClock));
        } else {

            long countByIsRestDay = hmEmployClockService.queryCountByIsRestDay(hmEmployRelationId, startTime, endTime);
            long countByIsHoliday = hmEmployClockService.queryCountByIsHoliday(hmEmployRelationId, startTime, endTime);
            //休息日加班薪资
            BigDecimal restDayMoney = clockMoney.multiply(BigDecimal.valueOf(contractSubTemplate.getOffMultiple()));
            //节假日加班薪资
            BigDecimal holidayMoney = clockMoney.multiply(BigDecimal.valueOf(contractSubTemplate.getWorkerMultiple()));
            //工作日打卡天数= 总的每月打卡天数-每月休息日打卡天数-每月节假日打卡天数
            int workClockDays = dayOfMonthClock - (int) countByIsHoliday - (int) countByIsRestDay;
            //总薪资=工作日打卡薪资+休息日加班薪资+节假日加班薪资
            money = clockMoney.multiply(new BigDecimal(workClockDays)).add(restDayMoney).add(holidayMoney);
        }

        return money;
    }

    /**
     * 代班保姆收入（只针对日薪）
     *
     * @param hmEmployRelationId
     * @param contractSubTemplate
     * @return
     */
    private BigDecimal getSubstituteWorkerIncome(Long hmEmployRelationId, ContractSubTemplate contractSubTemplate, LocalDate startTime, LocalDate endTime) throws ParseException {
        //日薪
        BigDecimal daySalary = new BigDecimal(contractSubTemplate.getDaySalary());
        //获取总的打卡天数
        int dayOfMonthClock = (int) hmEmployClockService.getDayOfMonthClock(hmEmployRelationId, startTime, endTime);
        //总收入
        return daySalary.multiply(new BigDecimal(dayOfMonthClock));
    }

    /**
     * 钟点工收入（包含代班终点工）
     *
     * @param hmEmployRelationId
     * @param contractSubTemplate
     * @return
     */
    private BigDecimal getHourlyWorkerIncome(Long hmEmployRelationId, ContractSubTemplate contractSubTemplate, LocalDate startTime, LocalDate endTime) throws ParseException {
        BigDecimal money;
        //每月休息天数
        Integer monthRestDays = contractSubTemplate.getMonthRestDays();
        // 应工作天数
        int days = DateTimeUtil.getDayOfMonth() - monthRestDays;
        //实际每次打卡收入金额
        BigDecimal clockMoney = new BigDecimal(contractSubTemplate.getHourlySalary());
        //获取每天工作时长
        long workHours = getWorkHours(contractSubTemplate.getDayWorkTime());
        //获取总的打卡时长
        int hoursOfMonthClock = (int) hmEmployClockService.getHoursOfMonthClock(hmEmployRelationId, null, null, startTime, endTime);
        //判断是否有加班 如果有判断是否是节假日加班还是休息日加班 ||区分代班终点工

        if (days * workHours - hoursOfMonthClock >= 0 || null == contractSubTemplate.getOffMultiple() && null == contractSubTemplate.getWorkerMultiple()) {
            money = clockMoney.multiply(new BigDecimal(hoursOfMonthClock));
        } else {
            //休息日加班小时数
            long countByIsRestDay = hmEmployClockService.getHoursOfMonthClock(hmEmployRelationId, 1, null, startTime, endTime);
            //节假日加班小时数
            long countByIsHoliday = hmEmployClockService.getHoursOfMonthClock(hmEmployRelationId, null, 1, startTime, endTime);
            //休息日加班薪资
            BigDecimal restDayMoney = clockMoney.multiply(BigDecimal.valueOf(contractSubTemplate.getOffMultiple()));
            //节假日加班薪资
            BigDecimal holidayMoney = clockMoney.multiply(BigDecimal.valueOf(contractSubTemplate.getWorkerMultiple()));
            //工作日打卡时长= 总的打卡时长-休息日打卡时长-节假日打卡时长
            int workClockDays = hoursOfMonthClock - (int) countByIsHoliday - (int) countByIsRestDay;
            //总薪资=工作日打卡薪资+休息日加班薪资+节假日加班薪资
            money = clockMoney.multiply(new BigDecimal(workClockDays)).add(restDayMoney).add(holidayMoney);
        }

        return money;
    }

    /**
     * 获取每天工作小时数
     *
     * @param dayWorkTime
     * @return
     * @throws ParseException
     */
    private long getWorkHours(String dayWorkTime) throws ParseException {
        String[] split = dayWorkTime.split(",");
        long hours = 0;
        for (String s : split) {
            String startTime = s.substring(0, s.indexOf("-"));
            String endTime = s.substring(s.indexOf("-") + 1);
            hours += DateTimeUtil.dateDiff(startTime, endTime, "HH:mm");
        }
        return hours;
    }
}
