package org.jeecg.modules.hikiot;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.hikiot.dto.AddDoorWeekPlanDTO;
import org.jeecg.modules.hikiot.dto.AddFaceRequestDTO;
import org.jeecg.modules.hikiot.dto.AddUserRequestDTO;
import org.jeecg.modules.hikiot.dto.AddUserWeekPlanDTO;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.alibaba.dashscope.utils.JsonUtils.gson;
import static org.jeecg.modules.hikiot.HikiotConstant.*;

public class HikiotTool {

    private static String cachedAppAccessToken = null;
    private static long expirationTime = 0L;
    private static String cachedUserAccessToken = null;
    private static long userTokenExpirationTime = 0L;
    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .build();
    /**
     * 发送HTTPS POST请求
     * @param url 请求地址
     * @param jsonParam 请求参数（JSON格式）
     * @return 响应结果
     */
    public static String sendPostRequest(String url, String jsonParam, Map<String, String> variables) {
        // 参数校验
        Objects.requireNonNull(url, "请求URL不能为空");
        Objects.requireNonNull(jsonParam, "JSON参数不能为空");

        try {
            // 构建请求基础配置
            HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .header("Content-Type", "application/json; charset=UTF-8")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonParam, StandardCharsets.UTF_8));

            // 添加自定义Header
            if (variables != null) {
                variables.forEach(requestBuilder::header);
            }

            // 构建最终请求
            HttpRequest request = requestBuilder.build();

            // 发送请求并返回结果
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            return response.body();

        } catch (IOException e) {
            throw new JeecgBootException("请求海康开放平台接口IO异常", e);
        } catch (InterruptedException e) {
            // 恢复中断状态
            Thread.currentThread().interrupt();
            throw new JeecgBootException("请求海康开放平台接口被中断", e);
        }
    }
    /**
     * 发送HTTPS GET请求
     * @param url 完整请求地址（包含查询参数）
     * @return 响应结果
     */
    public static String sendGetRequest(String url, Map<String, String> headers){
        // 构建请求基础配置
        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .GET()
                .header("Content-Type", "application/json")
                .header(APP_ACCESS_TOKEN_AUTH_HEADER, getAppAccessToken());

        // 添加动态header
        if (headers != null) {
            headers.forEach(requestBuilder::header);
        }

        // 构建最终请求
        HttpRequest request = requestBuilder.build();
        HttpResponse<String> response = null;
        try {
            response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        }catch (Exception e){
            throw new JeecgBootException("请求海康开放平台接口异常", e);
        }
        return response.body();
    }

    /**
     * @Author SheepHy
     * @Description 获取应用访问凭证（带缓存）
     * @Date 16:05 2025/8/12
     **/
    public static synchronized String getAppAccessToken() {
        // 检查缓存是否有效
        if (cachedAppAccessToken != null && System.currentTimeMillis() < expirationTime) {
            return cachedAppAccessToken;
        }
        // 缓存失效或不存在，重新获取
        Map<String, String> map = new HashMap<>();
        map.put(APP_KEY, APP_KEY_VALUE);
        map.put(APP_SECRET, APP_SECRET_VALUE);
        JsonObject appAccessToken = JsonParser.parseString(HikiotTool.sendPostRequest(GET_ACCESS_TOKEN_URL, gson.toJson(map), null)).getAsJsonObject();
        if (appAccessToken.get("code").getAsInt() == 0) {
            JsonObject data = appAccessToken.getAsJsonObject("data");
            int expiresIn = data.get("expiresIn").getAsInt();
            String token = data.get("appAccessToken").getAsString();
            // 更新缓存和过期时间（单位：小时转毫秒）
            cachedAppAccessToken = token;
            expirationTime = System.currentTimeMillis() + (expiresIn * 60L * 60L * 1000L);
            return token;
        } else {
            throw new JeecgBootException("海康API appAccessToken请求失败: " + appAccessToken.get("msg").getAsString());
        }
    }

    /**
     * @Author SheepHy
     * @Description 刷新应用访问凭证
     * @Date 16:25 2025/8/12
     **/
    public static String refreshAppAccessToken(String appAccessToken, String refreshAppToken) {
        Map<String, String> map = new HashMap<>();
        map.put(APP_ACCESS_TOKEN, appAccessToken);
        map.put(REFRESH_APP_TOKEN, refreshAppToken);
        return HikiotTool.sendPostRequest(REFRESH_ACCESS_TOKEN_URL, gson.toJson(map), null);
    }

    /**
     * @Author SheepHy
     * @Description 申请授权码
     * @Date 14:04 2025/8/14
     * @Param
     * @return
     **/
    public static String getAuthCode() {
        Map<String, String> map = new HashMap<>();
        map.put(USER_NAME, USER_NAME_VALUE);
        map.put(PASSWORD, PASSWORD_VALUE);
        map.put(APP_KEY, APP_KEY_VALUE);
        map.put(REDIRECT_URL, REDIRECT_URL_VALUE);
        return HikiotTool.sendPostRequest(GET_AUTH_CODE_URL, gson.toJson(map), null);
    }

    /**
     * @Author SheepHy
     * @Description 授权码获取用户访问凭证（带缓存）
     * @Date 11:36 2025/8/14
     */
    public static synchronized String getUserAccessToken() {
        // 检查缓存是否有效
        if (cachedUserAccessToken != null && System.currentTimeMillis() < userTokenExpirationTime) {
            return cachedUserAccessToken;
        }
        // 缓存失效或不存在，重新获取
        JsonObject dataAuthCode = JsonParser.parseString(HikiotTool.getAuthCode()).getAsJsonObject();
        if (dataAuthCode.get("code").getAsInt() != 0) {
            throw new JeecgBootException("海康API authCode请求失败: " + dataAuthCode.get("msg").getAsString());
        }
        String authCode = dataAuthCode.getAsJsonObject("data").get("authCode").getAsString();
        JsonObject userAccessToken = JsonParser.parseString(sendGetRequest(GET_USER_ACCESS_TOKEN_URL + authCode, null)).getAsJsonObject();
        if (userAccessToken.get("code").getAsInt() != 0) {
            throw new JeecgBootException("海康API userAccessToken请求失败: " + userAccessToken.get("msg").getAsString());
        }
        JsonObject data = userAccessToken.getAsJsonObject("data");
        String expiresInStr = data.get("expiresIn").getAsString();
        try {
            int expiresInDays = Integer.parseInt(expiresInStr);
            String token = data.get("userAccessToken").getAsString();
            // 更新缓存和过期时间（单位：天转毫秒）
            cachedUserAccessToken = token;
            userTokenExpirationTime = System.currentTimeMillis() + (expiresInDays * 24L * 60L * 60L * 1000L);
            return token;
        } catch (NumberFormatException e) {
            throw new JeecgBootException("海康API expiresIn字段解析失败: " + expiresInStr, e);
        }
    }

    /** 
     * @Author SheepHy
     * @Description 新增/修改人员
     * @Date 9:35 2025/8/15
     * @param inputDate 开始日期（必填）
     * @param deviceSerial 设备序列号（必填）
     * @param name 用户名称（必填）
     * @param employeeNo 员工编号（必填）
     * @param endDate 结束日期（选填，不传则使用开始日期）
     * @param frameTimeStr 时间段（选填，支持两种格式）
     *                     格式1: "HH:mm:ss-HH:mm:ss" 如"18:00:00-22:00:00" - 场地预约订单（type=0）的当日时间段
     *                            示例：2025-11-05的18:00-22:00，结果为 beginTime:2025-11-05T18:00:00, endTime:2025-11-05T22:00:00
     *                     格式2: "yyyy-MM-dd-MM-dd" 如"2025-11-02-11-02" - 场地预约订单（type=5）的课程日期范围
     *                            示例：2025-11-02到2025-11-02，结果为 beginTime:2025-11-02T00:00:00, endTime:2025-11-02T23:59:59
     *                     注意：纯课程订单通常不传此参数（传null），直接使用inputDate和endDate即可
     * @return 海康接口返回结果
     **/
    public static String addUser(Date inputDate,String deviceSerial,String name,String employeeNo,Date endDate, String frameTimeStr){
        // 将Date转换为LocalDateTime，使用系统默认时区
        LocalDateTime now = inputDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
        
        // 打印调试信息
        System.out.println("[HikiotTool.addUser] inputDate: " + inputDate);
        System.out.println("[HikiotTool.addUser] 转换后的LocalDateTime: " + now);
        System.out.println("[HikiotTool.addUser] endDate: " + endDate);
        System.out.println("[HikiotTool.addUser] frameTimeStr: " + frameTimeStr);
        
        // 默认开始时间为当天00:00:00
        LocalDateTime startOfDay = now.with(LocalTime.MIN); // 00:00:00
        // 默认结束时间为当天23:59:59
        LocalDateTime endOfDay = now.with(LocalTime.MAX);   // 23:59:59.999999999
        
        // 如果指定了结束日期，则使用该日期（保持23:59:59）
        if(null != endDate){
            LocalDateTime outputDate = endDate.toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            endOfDay = outputDate.with(LocalTime.MAX);
        }
        
        // 处理frameTimeStr参数，支持两种格式
        if(null != frameTimeStr && !frameTimeStr.isEmpty()){
            String[] parts = frameTimeStr.split("-");
            
            // 格式1: "HH:mm:ss-HH:mm:ss" (场地预约type=0，当日时间段，例如: "18:00:00-22:00:00")
            //        按'-'分割后长度为2，且包含':'
            //        注意：此格式只应用时间到当天，endTime使用当天的结束时间
            // 格式2: "yyyy-MM-dd-MM-dd" (场地预约type=5课程，日期范围，例如: "2025-11-02-11-02")
            //        按'-'分割后长度为5 (2025, 11, 02, 11, 02)
            
            if(parts.length == 2 && parts[0].contains(":")) {
                // 格式1: 场地预约type=0的当日时间段 "HH:mm:ss-HH:mm:ss"
                // 示例: "18:00:00-22:00:00" 表示当天18:00到22:00
                // 修复：当存在多个订单时，需要考虑endDate参数来扩展权限时间范围
                try {
                    LocalTime customStartTime = LocalTime.parse(parts[0]);
                    LocalTime customEndTime = LocalTime.parse(parts[1]);
                    // 开始时间应用到inputDate（最早日期）
                    startOfDay = now.with(customStartTime);
                    
                    // 结束时间应用到endDate（最晚日期，如果提供了的话）
                    if(null != endDate){
                        LocalDateTime endDateTime = endDate.toInstant()
                                .atZone(ZoneId.systemDefault())
                                .toLocalDateTime();
                        endOfDay = endDateTime.with(customEndTime);
                    } else {
                        endOfDay = now.with(customEndTime);
                    }
                    
                    System.out.println("[HikiotTool.addUser] 格式1-应用时间段后 startOfDay: " + startOfDay);
                    System.out.println("[HikiotTool.addUser] 格式1-应用时间段后 endOfDay: " + endOfDay);
                } catch (Exception e) {
                    // 时间格式解析失败，使用默认全天时间
                    System.err.println("[HikiotTool.addUser] 时间段解析失败: " + frameTimeStr + ", " + e.getMessage());
                }
            } else if(parts.length == 5) {
                // 格式2: 场地预约type=5课程的日期范围 "yyyy-MM-dd-MM-dd"
                // 示例: "2025-11-02-11-05" 表示从2025-11-02到2025-11-05全天
                try {
                    // 起始日期: parts[0]-parts[1]-parts[2] = "2025-11-02"
                    String startDateStr = parts[0] + "-" + parts[1] + "-" + parts[2];
                    // 结束日期: parts[0]-parts[3]-parts[4] = "2025-11-05" (使用同一年份)
                    String endDateStr = parts[0] + "-" + parts[3] + "-" + parts[4];
                    
                    LocalDate parsedStartDate = LocalDate.parse(startDateStr);
                    LocalDate parsedEndDate = LocalDate.parse(endDateStr);
                    
                    startOfDay = parsedStartDate.atTime(LocalTime.MIN);  // 2025-11-02T00:00:00
                    endOfDay = parsedEndDate.atTime(LocalTime.MAX);      // 2025-11-05T23:59:59
                    
                    System.out.println("[HikiotTool.addUser] 格式2-应用日期范围后 startOfDay: " + startOfDay);
                    System.out.println("[HikiotTool.addUser] 格式2-应用日期范围后 endOfDay: " + endOfDay);
                } catch (Exception e) {
                    // 日期格式解析失败，使用默认全天时间
                    System.err.println("[HikiotTool.addUser] 日期范围解析失败: " + frameTimeStr + ", " + e.getMessage());
                }
            }
        }
        
        System.out.println("[HikiotTool.addUser] 最终 beginTime: " + LocalDateTimeUtil.format(startOfDay, "yyyy-MM-dd'T'HH:mm:ss"));
        System.out.println("[HikiotTool.addUser] 最终 endTime: " + LocalDateTimeUtil.format(endOfDay, "yyyy-MM-dd'T'HH:mm:ss"));
        
        AddUserRequestDTO addUserRequestDTO = new AddUserRequestDTO();
        List<AddUserRequestDTO.DoorRightPlan> doorRightPlans = new ArrayList<>();
        AddUserRequestDTO.DoorRightPlan doorRightPlan = new AddUserRequestDTO.DoorRightPlan();
        doorRightPlan.setDoorNo(1);
        doorRightPlan.setPlanTemplateId(Collections.singletonList(1));
        doorRightPlans.add(doorRightPlan);
        addUserRequestDTO.setDeviceSerial(deviceSerial);
        addUserRequestDTO.setPayload(new AddUserRequestDTO.Payload()
                .setUserInfo(new AddUserRequestDTO.UserInfo()
                        .setUserType("normal")
                        .setEmployeeNo(employeeNo)
                        .setName(name)
                        .setDoorRightPlan(doorRightPlans)
                        .setDoorRight(Collections.singletonList(1))
                        .setPermanentValid(false)
                        .setMaxOpenDoorTime(255)
                        .setEnableBeginTime(LocalDateTimeUtil.format(startOfDay, "yyyy-MM-dd'T'HH:mm:ss"))
                        .setEnableEndTime(LocalDateTimeUtil.format(endOfDay, "yyyy-MM-dd'T'HH:mm:ss"))));
        return sendPostRequest(ADD_USER_URL, gson.toJson(addUserRequestDTO),setHeaders());
    }

    /** 
     * @Author SheepHy
     * @Description 设备添加
     * @Date 10:47 2025/8/15
     **/
    public static String addDevice(String deviceSerial,String validateCode){
        Map<String, String> device = new HashMap<>();
        device.put("deviceSerial", deviceSerial);
        device.put("validateCode", validateCode);
        device.put("addMethod", "DeviceToken");
        device.put("qrCode", "");
        return sendPostRequest(ADD_DEVICE_URL, gson.toJson(device),setHeaders());
    }

    /**
     * @Author SheepHy
     * @Description 设置请求头
     * @Date 10:56 2025/8/15
     **/
    private static Map<String, String> setHeaders() {
        Map<String, String> variables = new HashMap<>();
        variables.put(APP_ACCESS_TOKEN_AUTH_HEADER, getAppAccessToken());
        variables.put(USER_ACCESS_TOKEN, getUserAccessToken());
        return variables;
    }

    /**
     * @Author SheepHy
     * @Description 设备/通道能力查询
     * @Date 12:00 2025/8/15
     **/
    public static String getDeviceAbility() throws IOException, InterruptedException {
        Map<String, String> headers = new HashMap<>();
        JsonObject userAccessToken = JsonParser.parseString(HikiotTool.getUserAccessToken()).getAsJsonObject();
        if (userAccessToken.get("code").getAsInt() == 0) {
            userAccessToken = userAccessToken.getAsJsonObject("data");
        }
        headers.put(USER_ACCESS_TOKEN, userAccessToken.get("userAccessToken").getAsString());
        return sendGetRequest(QUERY_DEVICE_ABILITY_URL + "FX0889961",headers);
    }

    /** 
     * @Author SheepHy
     * @Description 新增/修改人脸
     * @Date 14:28 2025/8/15
     **/
    public static String addFace(String deviceSerial,String employeeNo,String url){
        if(url == null || url.isEmpty() || url.equals("null") || url.equals("")) throw new RuntimeException("请重新上传人脸照片！");
        AddFaceRequestDTO addFaceRequestDTO = new AddFaceRequestDTO();
        addFaceRequestDTO.setDeviceSerial(deviceSerial);
        addFaceRequestDTO.setPayload(new AddFaceRequestDTO.Payload()
                .setFaceInfo(new AddFaceRequestDTO.Payload.FaceInfo()
                        .setEmployeeNo(employeeNo)
                        .setFaceURL(url)));
        return sendPostRequest(ADD_FACE_URL, gson.toJson(addFaceRequestDTO),setHeaders());
    }

    /**
     * @Author SheepHy
     * @Description 人员信息查询
     * @Date 15:08 2025/8/15
     **/
    public static String queryUserInfo(String deviceSerial){
        Map<String, String> queryUserInfo = new HashMap<>();
        queryUserInfo.put("deviceSerial", deviceSerial);
        return sendPostRequest(QUERY_USER_INFO_URL, gson.toJson(queryUserInfo),setHeaders());
    }

    /**
     * @Author SheepHy
     * @Description 删除已过期的访客
     * @Date 15:09 2025/8/15
     **/
    public static String deleteExpiredVisitors(String deviceSerial) {
        // 1. 查询访客信息
        String userInfoResponse = queryUserInfo(deviceSerial);
        JsonObject responseJson = JsonParser.parseString(userInfoResponse).getAsJsonObject();

        if (responseJson.get("code").getAsInt() != 0) {
            throw new JeecgBootException("查询用户信息失败: " + responseJson.get("msg").getAsString());
        }

        // 2. 解析并筛选过期访客
        List<String> expiredEmployees = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        JsonArray dataArray = responseJson.getAsJsonArray("data");

        for (JsonElement element : dataArray) {
            JsonObject user = element.getAsJsonObject();
            JsonObject valid = user.getAsJsonObject("Valid");

            // 解析时间字段
            String endTimeStr = valid.get("endTime").getAsString();

            // 增加对空字符串的检查
            if (endTimeStr == null || endTimeStr.isEmpty()) {
                // 如果 endTime 为空，可以考虑将其视为已过期或跳过处理
                expiredEmployees.add(user.get("employeeNo").getAsString());
                continue;
            }

            try {
                LocalDateTime endTime = LocalDateTime.parse(endTimeStr, DateTimeFormatter.ISO_DATE_TIME);

                // 判断是否过期
                if (endTime.isBefore(now)) {
                    expiredEmployees.add(user.get("employeeNo").getAsString());
                }
            } catch (Exception e) {
                // 如果解析失败，可以记录日志或按业务需求处理
                throw new JeecgBootException("时间解析失败: " + endTimeStr, e);
            }
        }

        // 3. 构造删除请求体
        if (expiredEmployees.isEmpty()) {
            return "无过期访客需要删除";
        }

        JsonObject requestJson = new JsonObject();
        requestJson.addProperty("deviceSerial", deviceSerial);  // deviceSerial在顶层

        // 创建payload对象
        JsonObject payload = new JsonObject();
        JsonArray userInfoArray = new JsonArray();

        // 添加userInfo数组
        for (String employeeNo : expiredEmployees) {
            JsonObject userInfoItem = new JsonObject();
            userInfoItem.addProperty("employeeNo", employeeNo);
            userInfoArray.add(userInfoItem);
        }

        payload.add("userInfo", userInfoArray);
        requestJson.add("payload", payload);  // payload作为顶层字段

        // 4. 发送删除请求
        return sendPostRequest(BATCH_DELETE_USER_URL, requestJson.toString(), setHeaders());
    }

    /** 
     * @Author SheepHy
     * @Description 配置人员周计划
     * @Date 16:12 2025/8/15
     **/
    public static String addUserWeekPlan(String deviceSerial) {
        AddUserWeekPlanDTO dto = new AddUserWeekPlanDTO();

        // 基础配置
        dto.setDeviceSerial(deviceSerial);

        // 初始化payload
        AddUserWeekPlanDTO.Payload payload = new AddUserWeekPlanDTO.Payload();
        AddUserWeekPlanDTO.UserWeekPlan userWeekPlan = new AddUserWeekPlanDTO.UserWeekPlan();

        userWeekPlan.setDoorWeekId(1);
        userWeekPlan.setEnable(true);

        // 生成时间配置
        userWeekPlan.setTimeSegment(createTimeSegments());

        payload.setUserWeekPlan(userWeekPlan);
        dto.setPayload(payload);

        return sendPostRequest(CONFIG_USER_WEEK_PLAN_URL, gson.toJson(dto), setHeaders());
    }

    // 生成时间片段
    private static List<AddUserWeekPlanDTO.TimeSegment> createTimeSegments() {
        List<AddUserWeekPlanDTO.TimeSegment> segments = new ArrayList<>();
        // 默认时间片段配置
        for (String day : Arrays.asList("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")) {
            for (int i = 1; i <= 8; i++) {
                AddUserWeekPlanDTO.TimeSegment segment = new AddUserWeekPlanDTO.TimeSegment();
                segment.setDoorWeekTimeSegmentId(i);
                segment.setWeek(day);
                segment.setDoorStatus("normal");
                segment.setBeginTime("01:00:00");
                segment.setEndTime("23:00:00");

                // 特殊配置
                if (i == 1) {
                    segment.setEnable(true);
                    segment.setBeginTime("06:00:00");
                    segment.setEndTime("23:00:00");
                } else {
                    segment.setEnable(false);
                }
                segments.add(segment);
            }
        }
        return segments;
    }

    /**
     * @Author SheepHy
     * @Description 配置人员计划模板
     * @Date 17:09 2025/8/15
     **/
    public static String addUserPlanTemplate(String deviceSerial){
        String addUserPlanTemplate = "{\n" +
                "    \"deviceSerial\": \"" + deviceSerial +"\",\n" +
                "    \"payload\": {\n" +
                "        \"userPlanTemplate\": {\n" +
                "            \"doorPlanTemplateId\": 1,\n" +
                "            \"enable\": true,\n" +
                "            \"name\": \"全天通行计划模板\",\n" +
                "            \"doorWeekId\": 1,\n" +
                "            \"holidayGroupId\": [\n" +
                "                1\n" +
                "            ]\n" +
                "        }\n" +
                "    }\n" +
                "}";
        return sendPostRequest(CONFIG_USER_PLAN_TEMPLATE_URL, addUserPlanTemplate, setHeaders());
    }

    /**
     * @Author SheepHy
     * @Description 配置门周计划
     * @Date 16:42 2025/8/15
     **/
    public static String addDoorWeekPlan() throws IOException, InterruptedException {
        AddDoorWeekPlanDTO dto = new AddDoorWeekPlanDTO();
        // 基础配置
        dto.setDeviceSerial("FX0889961");
        // 初始化payload
        AddDoorWeekPlanDTO.Payload payload = new AddDoorWeekPlanDTO.Payload();
        AddDoorWeekPlanDTO.WeekPlan weekPlan = new AddDoorWeekPlanDTO.WeekPlan();
        weekPlan.setDoorWeekId(1);
        weekPlan.setEnable(true);
        // 生成时间配置
        weekPlan.setTimeSegment(createTimeSegments1());
        payload.setWeekPlan(weekPlan);
        dto.setPayload(payload);
        return sendPostRequest(CONFIG_DOOR_WEEK_PLAN_URL, gson.toJson(dto), setHeaders());
    }
    private static List<AddDoorWeekPlanDTO.TimeSegment> createTimeSegments1() {
        List<AddDoorWeekPlanDTO.TimeSegment> segments = new ArrayList<>();

        List<String> days = Arrays.asList(
                "Monday", "Tuesday", "Wednesday", "Thursday",
                "Friday", "Saturday", "Sunday"
        );

        for (String day : days) {
            for (int i = 1; i <= 8; i++) {
                AddDoorWeekPlanDTO.TimeSegment segment = new AddDoorWeekPlanDTO.TimeSegment();
                segment.setDoorWeekTimeSegmentId(i);
                segment.setWeek(day);

                // 设置默认值
                segment.setBeginTime("01:00:00");
                segment.setEndTime("23:00:00");

                // 特殊配置
                if (i == 1 ) {
                    segment.setEnable(true);
                    segment.setBeginTime("06:00:00");
                    segment.setEndTime("23:00:00");
                } else {
                    segment.setEnable(false);
                }

                segments.add(segment);
            }
        }

        return segments;
    }

    /**
     * @Author SheepHy
     * @Description 配置门关联计划模板
     * @Date 16:48 2025/8/15
     **/
    public static String addDoorPlanTemplate() throws IOException, InterruptedException {
        String str = "{\n" +
                "    \"deviceSerial\": \"FX0889961\",\n" +
                "    \"payload\": {\n" +
                "        \"doorRightPlan\": {\n" +
                "            \"doorNo\": 1,\n" +
                "            \"planTemplateId\": 1\n" +
                "        }\n" +
                "    }\n" +
                "}";
        return sendPostRequest(CONFIG_DOOR_PLAN_TEMPLATE_URL, str, setHeaders());
    }

    /**
     * @Author SheepHy
     * @Description 配置门计划模板
     * @Date 16:51 2025/8/15
     **/
    public static String addDoorPlanTemplate1() throws IOException, InterruptedException {
        String str = "{\n" +
                "    \"deviceSerial\": \"FX0889961\",\n" +
                "    \"payload\": {\n" +
                "        \"planTemplate\": {\n" +
                "            \"doorPlanTemplateId\": 1,\n" +
                "            \"enable\": true,\n" +
                "            \"name\": \"全天常开计划模板\",\n" +
                "            \"doorWeekId\": 1,\n" +
                "            \"holidayGroupId\": [\n" +
                "                1\n" +
                "            ]\n" +
                "        }\n" +
                "    }\n" +
                "}";
        return sendPostRequest(CONFIG_DOOR_PLAN_TEMPLATE_URL2, str, setHeaders());
    }

    /**
     * @Author SheepHy
     * @Description 分页查询开门记录
     * @Date 10:05 2025/8/25
     **/
    public static JsonObject queryOpenDoorRecord(int page, int size, Date startOfDay) {
        Map<String, Object> queryOpenDoor = new HashMap<>();
        queryOpenDoor.put("page", page);
        queryOpenDoor.put("size", size);
        // 获取今天最早和最晚时间并格式化
        LocalDate today = LocalDate.now();
        if(null != startOfDay){
            queryOpenDoor.put("startDate", DateUtil.format(startOfDay, "yyyy-MM-dd HH:mm:ss"));
        }
//        queryOpenDoor.put("endDate", endOfDay.format(formatter));
        queryOpenDoor.put("authResults", new int[] {1});
//        queryOpenDoor.put("employeeNos", new String[] {employeeNos});
//        queryOpenDoor.put("deviceSerial", "FX0889961");
//        queryOpenDoor.put("deviceSerials", new String[] {"FX0889961"});
        return gson.fromJson(sendPostRequest(QUERY_OPEN_DOOR_RECORD_URL, gson.toJson(queryOpenDoor), setHeaders()), JsonObject.class);
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("========== 手动添加用户到海康门禁系统 ==========");
        
        // 订单信息
        String useDateStr = "2025-12-16";
        String name = "李帅";
        String employeeNo = "1998889706633400321";
        String frameTimeStr = "18:00:00-22:00:00";
        String faceUrl = "https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/tmp_ce50fb4c32b66f855f4899a6e24bd21fd57f42955aaa3295_1765631550971.jpg";
        
        // 两个设备序列号
        String[] deviceSerials = {"FZ0080597", "FZ0080608"};
        
        System.out.println("订单信息:");
        System.out.println("  用户名: " + name);
        System.out.println("  员工编号: " + employeeNo);
        System.out.println("  使用日期: " + useDateStr);
        System.out.println("  时间段: " + frameTimeStr);
        System.out.println("  人脸照片: " + faceUrl);
        System.out.println();
        
        // 解析日期
        LocalDate useDate = LocalDate.parse(useDateStr);
        Date inputDate = Date.from(useDate.atTime(12, 0).atZone(ZoneId.systemDefault()).toInstant());
        System.out.println("解析日期: " + useDateStr + " -> " + inputDate);
        System.out.println();
        
        // 遍历所有设备
        for (String deviceSerial : deviceSerials) {
            System.out.println("---------- 处理设备: " + deviceSerial + " ----------");
            
            try {
                // 1. 添加用户
                System.out.println("1. 调用addUser...");
                String addUserResult = addUser(inputDate, deviceSerial, name, employeeNo, inputDate, frameTimeStr);
                System.out.println("   addUser返回: " + addUserResult);
                
                JsonObject addUserJson = JsonParser.parseString(addUserResult).getAsJsonObject();
                if (addUserJson.get("code").getAsInt() == 0) {
                    System.out.println("   ✅ 用户添加成功");
                } else {
                    System.out.println("   ❌ 用户添加失败: " + addUserJson.get("msg").getAsString());
                }
                
                // 2. 添加人脸
                System.out.println("2. 调用addFace...");
                String addFaceResult = addFace(deviceSerial, employeeNo, faceUrl);
                System.out.println("   addFace返回: " + addFaceResult);
                
                JsonObject addFaceJson = JsonParser.parseString(addFaceResult).getAsJsonObject();
                if (addFaceJson.get("code").getAsInt() == 0) {
                    System.out.println("   ✅ 人脸添加成功");
                } else {
                    System.out.println("   ❌ 人脸添加失败: " + addFaceJson.get("msg").getAsString());
                }
                
            } catch (Exception e) {
                System.err.println("   ❌ 处理异常: " + e.getMessage());
                e.printStackTrace();
            }
            System.out.println();
        }
        
        System.out.println("========== 处理完成 ==========");
    }
}
