package com.bcxin.tenant.open.domains.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bcxin.tenant.open.domains.entities.ConfigOfBillEntity;
import com.bcxin.tenant.open.domains.entities.DailyBillEntity;
import com.bcxin.tenant.open.domains.entities.MonthlyBillEntity;
import com.bcxin.tenant.open.domains.pojo.DailyBillPojo;
import com.bcxin.tenant.open.domains.pojo.MonthBillPojo;
import com.bcxin.tenant.open.infrastructures.enums.BillPaymentStatus;
import com.bcxin.tenant.open.infrastructures.enums.BillType;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class BillUtils {
    public static String getMonthBillId(String orgId, Date date, BillType type) {

        return String.format("%s-%s-%s", orgId, type.ordinal(), new SimpleDateFormat("yyyyMM").format(date));
    }

    public static String getDateFormat(Date date, String format) {
        return new SimpleDateFormat(format).format(date);
    }

    public static String getDailyBillId(String orgId, Date date, BillType type) {

        return String.format("%s-%s-%s", orgId, type.ordinal(), new SimpleDateFormat("yyyyMM-dd").format(date));
    }

    public static boolean isFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfMonth = calendar.get(calendar.DAY_OF_MONTH);
        return dayOfMonth == 1;
    }

    public static DailyBillEntity createDailyBillEntity(DailyBillPojo attendancePojo, Date date, BillType billType) {
        int opeCount = attendancePojo.getOpeCount();
        String orgId = attendancePojo.getOrgId();
        DailyBillEntity dailyBillEntity = DailyBillEntity.create(
                getDailyBillId(orgId, date, billType),
                billType,
                orgId,
                java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(date)),
                getMonthBillId(orgId, date, billType),
                opeCount,
                attendancePojo.getHeadCount()
        );
        return dailyBillEntity;
    }

    public static MonthlyBillEntity createMonthlyBillEntity(ConfigOfBillEntity configOfBill, MonthBillPojo billPojo, BillType type, Date date) {
        int opePerCalc = 1;
        int pointsPerCalc = 0;
        switch (type) {
            case Attendance -> {
                opePerCalc = configOfBill.getSignDo();
                pointsPerCalc = configOfBill.getSignMinutePerson();
            }
            case RollCall -> {
                opePerCalc = configOfBill.getCallDo();
                pointsPerCalc = configOfBill.getCallMinutePerson();
            }
            case Track -> {
                opePerCalc = configOfBill.getTrackDo();
                pointsPerCalc = configOfBill.getTrackMinutePerson();
            }
            case Fence -> {
                opePerCalc = configOfBill.getFenceDo();
                pointsPerCalc = configOfBill.getFenceMinutePerson();
            }
            case Audio -> {
                pointsPerCalc = configOfBill.getAudioMinutePerson();
            }
            case Video -> {
                pointsPerCalc = configOfBill.getVideoMinutePerson();
            }
        }
        int opeCount = billPojo.getCount();
        int amount = (opeCount / opePerCalc + (opeCount % opePerCalc == 0 ? 0 : 1)) * pointsPerCalc;
        String configStr = JSON.toJSONString(configOfBill, SerializerFeature.WriteMapNullValue);
        return MonthlyBillEntity.create(
                BillUtils.getMonthBillId(billPojo.getOrgId(), date, type),
                type,
                billPojo.getOrgId(),
                BillPaymentStatus.Unpaid,
                null,
                new SimpleDateFormat("yyyyMM").format(date),
                amount,
                0,
                billPojo.getCount(),
                configStr,
                1
        );
    }

    public static Date getNextDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    public static Date getMin(Date date1, Date date2){
        int cmpResult = compareDate(date1,date2);
        if(cmpResult <= 0) return date1;
        else return date2;
    }

    /**
     * 如果是当月最后一天则返回，如果不是则返回上个月最后一天
     * @param date
     * @return
     */
    public static Date getLastDateOfCurOrPreMonth(Date date){
        if(date == null) return null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if(calendar.getActualMaximum(Calendar.DAY_OF_MONTH) == calendar.get(Calendar.DAY_OF_MONTH)){
            return date;
        }else{
            calendar.set(Calendar.DAY_OF_MONTH,1);
            calendar.add(Calendar.DAY_OF_MONTH,-1);
            return calendar.getTime();
        }
    }

    /**
     * 比较年月
     *
     * @param date1
     * @param date2
     * @return 0，同年同月，-1：date1 < date2; 1:date1 > date2
     */
    public static int compareMonth(Date date1, Date date2) {
        if (date1 == null && date2 == null) return 0;
        if (date1 == null) return -1;
        if (date2 == null) return 1;
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);
        int year1 = calendar1.get(Calendar.YEAR);
        int month1 = calendar1.get(Calendar.MONTH);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);
        int year2 = calendar2.get(Calendar.YEAR);
        int month2 = calendar2.get(Calendar.MONTH);
        if (year1 < year2) {
            return -1;
        } else if (year1 > year2) {
            return 1;
        } else {
            if (month1 < month2) return -1;
            else if (month1 > month2) return 1;
            else return 0;
        }
    }

    public static int compareMonth(String m1, String m2) {
        if (m1 == null && m2 == null) return 0;
        if (m1 == null) return -1;
        if (m2 == null) return 1;
        return m1.compareTo(m2);
    }

    /**
     * 获取上个月的最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastDateOfPreviousMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DATE, 1);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return calendar.getTime();
    }

    public static Date getPreviousMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);
        return calendar.getTime();
    }

    public static Date getNextMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        return calendar.getTime();
    }

    public static Date getFirstDateOfNextMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DATE, 1);
        calendar.add(Calendar.MONTH, 1);
        return calendar.getTime();
    }

    public static Date getPreviousDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return calendar.getTime();
    }

    public static int compareDate(Date date1, Date date2) {
        if (date1 == null && date2 == null) return 0;
        if (date1 == null) return -1;
        if (date2 == null) return 1;
        int monthCompRst = compareMonth(date1, date2);
        if (monthCompRst == 0) {
            Calendar calendar1 = Calendar.getInstance();
            calendar1.setTime(date1);
            int day1 = calendar1.get(Calendar.DATE);
            Calendar calendar2 = Calendar.getInstance();
            calendar2.setTime(date2);
            int day2 = calendar2.get(Calendar.DATE);
            return day1 - day2;
        } else {
            return monthCompRst;
        }
    }
}
