package com.ruoyi.web.controller.config;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 工具类
 */
@Service
public class NumericIdGenerator {
    // 序列号（解决同一毫秒内的并发问题）
    private static final AtomicInteger SEQUENCE = new AtomicInteger(0);
    // 机器标识（分布式环境下可设置不同值，避免多机冲突）
    private static final int MACHINE_ID = 1; // 范围1-99
    // 序列号最大值（确保3位数字）
    private static final int MAX_SEQUENCE = 999;

    /**
     * 生成纯数字唯一ID
     * @return 18位数字唯一ID
     */
    public String createid() {
        // 1. 获取当前毫秒级时间戳（13位数字）
        long timestamp = Instant.now().toEpochMilli();

        // 2. 生成序列号（0-999，3位数字）
        int sequence = SEQUENCE.getAndIncrement();
        if (sequence > MAX_SEQUENCE) {
            SEQUENCE.set(0);
            sequence = 0;
        }

        // 3. 拼接组成18位数字ID
        // 格式：时间戳(13位) + 序列号(3位，不足补0) + 机器标识(2位，不足补0)
        String idStr = String.format("%d%03d%02d", timestamp, sequence, MACHINE_ID);

        // 转换为Long返回（如果ID可能超过Long最大值，可返回String）
        return idStr;
    }

        private long workerId;
        private long dataCenterId;
        private long sequence = 0L;
        private long lastTimestamp = -1L;

        public String nextId() {
            long timestamp = timeGen();
            if (timestamp < lastTimestamp) {
                throw new RuntimeException("Clock moved backwards!");
            }
            if (lastTimestamp == timestamp) {
                sequence = (sequence + 1) & 0xFFF;
                if (sequence == 0) {
                    timestamp = tilNextMillis(lastTimestamp);
                }
            } else {
                sequence = 0L;
            }
            lastTimestamp = timestamp;

            long id = ((timestamp - 1288834974657L) << 22)
                    | (dataCenterId << 17)
                    | (workerId << 12)
                    | sequence;

            return  ""+id; // 添加业务前缀 PAY 表示支付订单
        }

        protected long tilNextMillis(long lastTimestamp) {
            long timestamp = timeGen();
            while (timestamp <= lastTimestamp) {
                timestamp = timeGen();
            }
            return timestamp;
        }

        protected long timeGen() {
            return System.currentTimeMillis();
        }




    private String FIXED_SECRET="2555e45475a44818c6abecb1a1812847";

    // 解析Token中的openId（复用之前的固定密钥解析方法）
    public String parseOpenidFromToken(String token) {
        try {
            // 移除前缀 "basea"（注意区分大小写）
            if (token.startsWith("Bearer")) {
                token = token.substring("Bearer".length());
            }
            Claims claims = Jwts.parser()
                    .setSigningKey(FIXED_SECRET.getBytes()) // 使用生成Token时的固定密钥
                    .parseClaimsJws(token)
                    .getBody();
            return claims.get("openId", String.class);
        } catch (Exception e) {
            return null; // 解析失败返回null
        }
    }


    @Autowired // 注入JdbcTemplate，解决null问题
    private JdbcTemplate jdbcTemplate;

    @Transactional // 批量插入建议加事务，失败时回滚
    public int batchInsertYearDates(int targetYear) {
        LocalDate startDate = LocalDate.of(targetYear, 1, 1);
        LocalDate endDate = LocalDate.of(targetYear, 12, 31);

        List<Object[]> batchArgs = new ArrayList<>();
        LocalDate currentDate = startDate;

        while (!currentDate.isAfter(endDate)) {
            DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
            String weekdayName = getChineseWeekday(dayOfWeek); // 只保留星期名称

            // 构造参数：仅包含日期和星期名称（与SQL字段对应）
            Object[] args = {
                    currentDate, // 直接用LocalDate类型，数据库DATE字段可直接接收
                    weekdayName
            };
            batchArgs.add(args);

            currentDate = currentDate.plusDays(1);
        }

        // SQL语句：字段数量与参数数量一致（2个字段）
        String sql = "INSERT INTO sys_scheduling (scheduling_date, scheduling_todate) " +
                "VALUES (?, ?) ON DUPLICATE KEY UPDATE scheduling_id = scheduling_id";

        // 执行批量插入
        int[] result = jdbcTemplate.batchUpdate(sql, batchArgs);

        // 统计成功插入的记录数（排除重复的）
        int successCount = 0;
        for (int count : result) {
            // 批量插入时，count=1表示新增，count=0表示重复（因ON DUPLICATE KEY）
            successCount += count > 0 ? 1 : 0;
        }

        return successCount;
    }

    // 转换为中文星期名称
    private String getChineseWeekday(DayOfWeek dayOfWeek) {
        switch (dayOfWeek) {
            case MONDAY: return "星期一";
            case TUESDAY: return "星期二";
            case WEDNESDAY: return "星期三";
            case THURSDAY: return "星期四";
            case FRIDAY: return "星期五";
            case SATURDAY: return "星期六";
            case SUNDAY: return "星期日";
            default: return "";
        }
    }


//    @Resource
//    public WechatMessageController wechatMessageController;
    /**
     * 发送消息功能
     *
     *
     *
     *
     * 手机       （阿里云短信发送）
     *
     * 微信发送     （卡片发送功能）
     */
//
//    public void uptextmessage(String phone,
//                                    String wxopenId,
//                                    String workorderName,
//                                    String type,
//                                    String partenerNamer,
//                                    String currentTimeStr,
//                                    String workorderAddress){
//
//        if(phone!=null||!phone.equals("")){
//            //使用手机号发送短信
//
//        }else if (wxopenId!=null||!wxopenId.equals("")){
//            /**
//             * 使用微信进行短信发送
//             */
//            //获取设别名称
//            Map<String,Object> cardData=new HashMap<>();
//            //工单名称
//            cardData.put("thing10",workorderName);
//            //工单类型（1表示日常，2表示故障，3表示其他）
//            if (type.equals("1")) {
//                cardData.put("thing6","日常");
//            }else if (type.equals("2")){
//                cardData.put("thing6","故障");
//            }else if (type.equals("3")){
//                cardData.put("thing6","其他");
//            }
////            SysPartner sysPartner1=sysPartnerService.selectpartneropenId(workoderPartner);
//            //执行人名称
//            cardData.put("thing17",partenerNamer);
//            //发送时间
//            cardData.put("time18",currentTimeStr);
//            //地点
//            cardData.put("thing26",workorderAddress);
//            wechatMessageController.sendCardSubscribeMessage(wxopenId,"G_37RkJ_mwZeTdPv5A0fjBlYW6_lRQIW9_SywmUAX7Q","/pages/index/index",cardData);
//        }
//    }

    // 地球半径（单位：公里）
    private static final double EARTH_RADIUS = 6371.0;

    /**
     * 将角度转为弧度
     * @param degree 角度值
     * @return 弧度值
     */
    private static double rad(double degree) {
        return degree * Math.PI / 180.0;
    }

    public static double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
        // 转为弧度
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double radLng1 = rad(lng1);
        double radLng2 = rad(lng2);

        // 纬度差、经度差
        double deltaLat = radLat1 - radLat2;
        double deltaLng = radLng1 - radLng2;

        // 球面距离公式
        double distance = 2 * Math.asin(Math.sqrt(
                Math.pow(Math.sin(deltaLat / 2), 2) +
                        Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(deltaLng / 2), 2)
        ));
        distance = distance * EARTH_RADIUS;

        // 保留两位小数，避免精度冗余
        return new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP).doubleValue();
    }

}
