package com.jeeplus.human.practice.logwrite.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jeeplus.human.practice.logwrite.domain.HolidayVo;
import com.fasterxml.jackson.core.type.TypeReference;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 节假日工具类
 * @author 王强
 * @version 1.0
 * @date 2023-09-18 15:28
 */
public class HolidayUtil {
    /**
     * 发送get请求
     */
    private static String get(String url){
        StringBuilder inputLine = new StringBuilder();
        String read;
        try {
            HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
            urlConnection.setReadTimeout(30 * 1000);
            urlConnection.setConnectTimeout(30 * 1000);
            urlConnection.setRequestProperty("Charset", "UTF-8");
            urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36)");
            BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), StandardCharsets.UTF_8));
            while ((read = in.readLine()) != null) {
                inputLine.append(read);
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return inputLine.toString();
    }

    /**
     * 调用免费API查询全年工作日、周末、法定节假日、节假日调休补班数据
     * 1、调用 https://api.apihubs.cn/holiday/get?size=500&year=2021 查询全年日历（含周末）
     * 2、调用 https://timor.tech/api/holiday/year/2021 查询全年节假日、调休
     */
    public static List<String> getAllHolidayByYear(String year) throws IOException {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        ArrayList<HolidayVo> holidayVoList = new ArrayList<>();
        HashMap<String,HolidayVo> hashMap = new HashMap<>();


        //查询全年日历包含周末
        String allDayJson = HolidayUtil.get("https://timor.tech/api/holiday/year/"+year);
        ObjectMapper mapper = new ObjectMapper();
        Map allDayMap = mapper.readValue(allDayJson,Map.class);
        Map allDayData = (Map)allDayMap.get("holiday");

        allDayData.forEach((k,v)->{
            String s = v.toString();
            // 去掉大括号
            String keyValuePairs = s.substring(1, s.length() - 1);

            // 分割键值对
            String[] pairs = keyValuePairs.split(", ");

            // 创建一个新的 HolidayVo 对象
            HolidayVo holidayVo = new HolidayVo();

            // 遍历键值对数组
            for (String pair : pairs) {
                String[] keyValue = pair.split("=");
                String key = keyValue[0].trim();
                String value = keyValue[1].trim();

                // 根据键名设置相应的属性
                switch (key) {
                    case "holiday":
                        holidayVo.setHoliday(Boolean.parseBoolean(value));
                        break;
                    case "name":
                        holidayVo.setName(value);
                        break;
                    case "wage":
                        holidayVo.setWage(Integer.parseInt(value));
                        break;
                    case "date":
                        holidayVo.setDate(value);
                        break;
                    case "rest":
                        holidayVo.setRest(Integer.parseInt(value));
                        break;
                    case "after":
                        holidayVo.setAfter(Boolean.parseBoolean(value));
                        break;
                    // 可以根据需要添加其他属性
                }
            }
            holidayVoList.add(holidayVo);

        });
        List<String> daiList = new ArrayList<>();
        holidayVoList.forEach(holidayVo -> {
            daiList.add(holidayVo.getDate());
        });

        return daiList;
    }

    //判断区间里面有没有节假日，并返回具体天数
    public static int getHolidayCounts(String startTime,String endTime) throws IOException {
        //判断区间内是否有节假日
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startDate = LocalDate.parse(startTime, formatter);
        LocalDate endDate = LocalDate.parse(endTime, formatter);

        List<String> dateRange = new ArrayList<>();
        LocalDate currentDate = startDate;

        while (!currentDate.isAfter(endDate)) {
            dateRange.add(currentDate.toString());
            currentDate = currentDate.plusDays(1);
        }
        // 获取当前日期
        LocalDate nowDate = LocalDate.now();

        // 从当前日期中提取年份
        String currentYear = nowDate.getYear() + "";
        //获取所有的节假日具体天数
        List<String> holiday = HolidayUtil.getAllHolidayByYear(currentYear);
        int count = 0;
        for (int i=0;i<dateRange.size();i++) {
            if (holiday.contains(dateRange.get(i))){
                count ++;
            }
        }
        //判断是否是星期六星期天
        for (int i=0;i<dateRange.size();i++){
            // 使用字符串截取获取年、月、日的子字符串
            String yearStr = dateRange.get(i).substring(0, 4);  // 截取年份部分（从索引0到4，不包括4）
            String monthStr = dateRange.get(i).substring(5, 7); // 截取月份部分
            String dayStr = dateRange.get(i).substring(8);      // 截取日份部分（从索引8开始到字符串末尾）

            // 将子字符串解析为整数
            int year = Integer.parseInt(yearStr);
            int month = Integer.parseInt(monthStr);
            int day = Integer.parseInt(dayStr);
            boolean isRestDay = computeWhetherIsSaturdayAndSunday(new Date(year-1900, month-1, day));
            if (isRestDay){
                count ++;
            }
        }


        return count;
    }


    /**
     * 计算是周六还是周日
     */
    public static boolean computeWhetherIsSaturdayAndSunday(Date date) {
        // 创建Calendar类实例
        Calendar instance = Calendar.getInstance();
        // 根据指定日期获取周几
        instance.setTime(date);
        //因为数组下标从0开始，而返回的是数组的内容，是数组{1,2,3,4,5,6,7}中用1~7来表示
        int week = instance.get(Calendar.DAY_OF_WEEK);
        // 周日的编号是1，周六的编号是7
        if (week == Calendar.SUNDAY || week == Calendar.SATURDAY) {
            // 是周六日返回true
            return true;
        }else {
            // 不是周六日返回false
            return false;
        }
    }
}
