package com.fjhx.common.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ExchangeRateUtil {

    private static final String redisKeyPrefix = "exchange_rate:";

    private static final RedisCache redisCache = SpringUtil.getBean(RedisCache.class);

    private static final String key = "30e278b715e986079edc17e4583d61f2";

    private static final Map<String, String> currencyMap = new HashMap<>();

    static {
        // currencyMap.put("CNY", "人民币");
        currencyMap.put("USD", "美元");
        currencyMap.put("JPY", "日元");
        currencyMap.put("EUR", "欧元");
        currencyMap.put("GBP", "英镑");
        currencyMap.put("KRW", "韩元");
        currencyMap.put("HKD", "港元");
        currencyMap.put("AUD", "澳大利亚元");
        currencyMap.put("CAD", "加拿大元");
        currencyMap.put("CHF", "瑞士法郎");
        currencyMap.put("AED", "阿联酋迪拉姆");
        currencyMap.put("ALL", "阿尔巴尼亚列克");
        currencyMap.put("AMD", "亚美尼亚德拉姆");
        currencyMap.put("ANG", "荷属安的列斯盾");
        currencyMap.put("AOA", "安哥拉宽扎");
        currencyMap.put("ARS", "阿根廷比索");
        currencyMap.put("AZN", "阿塞拜疆马纳特");
        currencyMap.put("BBD", "巴巴多斯元");
        currencyMap.put("BDT", "孟加拉塔卡");
        currencyMap.put("BGN", "保加利亚列弗");
        currencyMap.put("BHD", "巴林第纳尔");
        currencyMap.put("BIF", "布隆迪法郎");
        currencyMap.put("BMD", "百慕大元");
        currencyMap.put("BND", "文莱元");
        currencyMap.put("BOB", "玻利维亚币");
        currencyMap.put("BRL", "巴西雷阿尔");
        currencyMap.put("BSD", "巴哈马元");
        currencyMap.put("BWP", "博茨瓦纳普拉");
        currencyMap.put("BYN", "白俄罗斯卢布");
        currencyMap.put("BZD", "伯利兹元");
        currencyMap.put("CLP", "智利比索");
        currencyMap.put("COP", "哥伦比亚比索");
        currencyMap.put("CRC", "哥斯达黎加科郎");
        currencyMap.put("CUP", "古巴比索");
        currencyMap.put("CVE", "佛得角埃斯库多");
        currencyMap.put("CZK", "捷克克朗");
        currencyMap.put("DJF", "吉布提法郎");
        currencyMap.put("DKK", "丹麦克朗");
        currencyMap.put("DOP", "多米尼加比索");
        currencyMap.put("DZD", "阿尔及利亚第纳尔");
        currencyMap.put("EGP", "埃及镑");
        currencyMap.put("ETB", "埃塞俄比亚比尔");
        currencyMap.put("FJD", "斐济元");
        currencyMap.put("GEL", "格鲁吉亚拉里");
        currencyMap.put("GHS", "加纳塞地");
        currencyMap.put("GMD", "冈比亚达拉西");
        currencyMap.put("GNF", "几内亚法郎");
        currencyMap.put("GTQ", "危地马拉格查尔");
        currencyMap.put("HNL", "洪都拉斯伦皮拉");
        currencyMap.put("HRK", "克罗地亚库纳");
        currencyMap.put("HTG", "海地古德");
        currencyMap.put("HUF", "匈牙利福林");
        currencyMap.put("IDR", "印尼盾");
        currencyMap.put("ILS", "以色列新谢克尔");
        currencyMap.put("INR", "印度卢比");
        currencyMap.put("IQD", "伊拉克第纳尔");
        currencyMap.put("IRR", "伊朗里亚尔");
        currencyMap.put("ISK", "冰岛克朗");
        currencyMap.put("JMD", "牙买加元");
        currencyMap.put("JOD", "约旦第纳尔");
        currencyMap.put("KES", "肯尼亚先令");
        currencyMap.put("KGS", "吉尔吉斯斯坦索姆");
        currencyMap.put("KHR", "柬埔寨瑞尔");
        currencyMap.put("KWD", "科威特第纳尔");
        currencyMap.put("KYD", "开曼群岛元");
        currencyMap.put("KZT", "哈萨克斯坦坚戈");
        currencyMap.put("LAK", "老挝基普");
        currencyMap.put("LBP", "黎巴嫩镑");
        currencyMap.put("LKR", "斯里兰卡卢比");
        currencyMap.put("LSL", "莱索托洛蒂");
        currencyMap.put("LYD", "利比亚第纳尔");
        currencyMap.put("MAD", "摩洛哥迪拉姆");
        currencyMap.put("MDL", "摩尔多瓦列伊");
        currencyMap.put("MKD", "马其顿第纳尔");
        currencyMap.put("MMK", "缅甸缅元");
        currencyMap.put("MOP", "澳门帕塔卡");
        currencyMap.put("MUR", "毛里求斯卢比");
        currencyMap.put("MWK", "马拉维客瓦查");
        currencyMap.put("MXN", "墨西哥比索");
        currencyMap.put("MYR", "马来西亚令吉");
        currencyMap.put("NAD", "纳米比亚元");
        currencyMap.put("NGN", "尼日利亚奈拉");
        currencyMap.put("NIO", "尼加拉瓜新科多巴");
        currencyMap.put("NOK", "挪威克朗");
        currencyMap.put("NPR", "尼泊尔卢比");
        currencyMap.put("NZD", "新西兰元");
        currencyMap.put("OMR", "阿曼里亚尔");
        currencyMap.put("PAB", "巴拿马巴波亚");
        currencyMap.put("PEN", "秘鲁索尔");
        currencyMap.put("PHP", "菲律宾比索");
        currencyMap.put("PKR", "巴基斯坦卢比");
        currencyMap.put("PLN", "波兰兹罗提");
        currencyMap.put("PYG", "巴拉圭瓜拉尼");
        currencyMap.put("QAR", "卡塔尔里亚尔");
        currencyMap.put("RON", "罗马尼亚新列伊");
        currencyMap.put("RSD", "塞尔维亚第纳尔");
        currencyMap.put("RUB", "俄罗斯卢布");
        currencyMap.put("RWF", "卢旺达法郎");
        currencyMap.put("SAR", "沙特里亚尔");
        currencyMap.put("SCR", "塞舌尔卢比");
        currencyMap.put("SDG", "苏丹镑");
        currencyMap.put("SEK", "瑞典克朗");
        currencyMap.put("SGD", "新加坡元");
        currencyMap.put("SOS", "索马里先令");
        currencyMap.put("SZL", "斯威士兰埃马兰吉尼");
        currencyMap.put("THB", "泰国泰铢");
        currencyMap.put("TMT", "土库曼斯坦马纳特");
        currencyMap.put("TND", "突尼斯第纳尔");
        currencyMap.put("TRY", "土耳其新里拉");
        currencyMap.put("TTD", "特立尼达和多巴哥元");
        currencyMap.put("TWD", "新台币");
        currencyMap.put("TZS", "坦桑尼亚先令");
        currencyMap.put("UAH", "乌克兰格里夫纳");
        currencyMap.put("UGX", "乌干达先令");
        currencyMap.put("UYU", "乌拉圭比索");
        currencyMap.put("UZS", "乌兹别克斯坦索姆");
        currencyMap.put("VES", "委内瑞拉玻利瓦尔");
        currencyMap.put("VND", "越南盾");
        currencyMap.put("XAF", "中非金融合作法郎");
        currencyMap.put("XCD", "东加勒比元");
        currencyMap.put("XOF", "非洲金融共同体法郎");
        currencyMap.put("XPF", "太平洋金融共同体法郎");
        currencyMap.put("YER", "也门里亚尔");
        currencyMap.put("ZAR", "南非兰特");
        currencyMap.put("ZMW", "赞比亚克瓦查");
    }

    // 查询币种
    // public static void main(String[] args) {
    //     String body = HttpRequest.get("http://op.juhe.cn/onebox/exchange/list")
    //             .header("Content-Type", "application/x-www-form-urlencoded")
    //             .form("key", key)
    //             .form("version", "2")
    //             .execute()
    //             .body();
    //     System.out.println(body);
    // }

    // 打印币种map
    // public static void main(String[] args) {
    //     String str = "{\"reason\":\"查询成功\",\"result\":{\"list\":[{\"name\":\"美元\",\"code\":\"USD\"},{\"name\":\"人民币\",\"code\":\"CNY\"},{\"name\":\"日元\",\"code\":\"JPY\"},{\"name\":\"欧元\",\"code\":\"EUR\"},{\"name\":\"英镑\",\"code\":\"GBP\"},{\"name\":\"韩元\",\"code\":\"KRW\"},{\"name\":\"港元\",\"code\":\"HKD\"},{\"name\":\"澳大利亚元\",\"code\":\"AUD\"},{\"name\":\"加拿大元\",\"code\":\"CAD\"},{\"name\":\"瑞士法郎\",\"code\":\"CHF\"},{\"name\":\"阿联酋迪拉姆\",\"code\":\"AED\"},{\"name\":\"阿尔巴尼亚列克\",\"code\":\"ALL\"},{\"name\":\"亚美尼亚德拉姆\",\"code\":\"AMD\"},{\"name\":\"荷属安的列斯盾\",\"code\":\"ANG\"},{\"name\":\"安哥拉宽扎\",\"code\":\"AOA\"},{\"name\":\"阿根廷比索\",\"code\":\"ARS\"},{\"name\":\"阿塞拜疆马纳特\",\"code\":\"AZN\"},{\"name\":\"巴巴多斯元\",\"code\":\"BBD\"},{\"name\":\"孟加拉塔卡\",\"code\":\"BDT\"},{\"name\":\"保加利亚列弗\",\"code\":\"BGN\"},{\"name\":\"巴林第纳尔\",\"code\":\"BHD\"},{\"name\":\"布隆迪法郎\",\"code\":\"BIF\"},{\"name\":\"百慕大元\",\"code\":\"BMD\"},{\"name\":\"文莱元\",\"code\":\"BND\"},{\"name\":\"玻利维亚币\",\"code\":\"BOB\"},{\"name\":\"巴西雷阿尔\",\"code\":\"BRL\"},{\"name\":\"巴哈马元\",\"code\":\"BSD\"},{\"name\":\"博茨瓦纳普拉\",\"code\":\"BWP\"},{\"name\":\"白俄罗斯卢布\",\"code\":\"BYN\"},{\"name\":\"伯利兹元\",\"code\":\"BZD\"},{\"name\":\"智利比索\",\"code\":\"CLP\"},{\"name\":\"哥伦比亚比索\",\"code\":\"COP\"},{\"name\":\"哥斯达黎加科郎\",\"code\":\"CRC\"},{\"name\":\"古巴比索\",\"code\":\"CUP\"},{\"name\":\"佛得角埃斯库多\",\"code\":\"CVE\"},{\"name\":\"捷克克朗\",\"code\":\"CZK\"},{\"name\":\"吉布提法郎\",\"code\":\"DJF\"},{\"name\":\"丹麦克朗\",\"code\":\"DKK\"},{\"name\":\"多米尼加比索\",\"code\":\"DOP\"},{\"name\":\"阿尔及利亚第纳尔\",\"code\":\"DZD\"},{\"name\":\"埃及镑\",\"code\":\"EGP\"},{\"name\":\"埃塞俄比亚比尔\",\"code\":\"ETB\"},{\"name\":\"斐济元\",\"code\":\"FJD\"},{\"name\":\"格鲁吉亚拉里\",\"code\":\"GEL\"},{\"name\":\"加纳塞地\",\"code\":\"GHS\"},{\"name\":\"冈比亚达拉西\",\"code\":\"GMD\"},{\"name\":\"几内亚法郎\",\"code\":\"GNF\"},{\"name\":\"危地马拉格查尔\",\"code\":\"GTQ\"},{\"name\":\"洪都拉斯伦皮拉\",\"code\":\"HNL\"},{\"name\":\"克罗地亚库纳\",\"code\":\"HRK\"},{\"name\":\"海地古德\",\"code\":\"HTG\"},{\"name\":\"匈牙利福林\",\"code\":\"HUF\"},{\"name\":\"印尼盾\",\"code\":\"IDR\"},{\"name\":\"以色列新谢克尔\",\"code\":\"ILS\"},{\"name\":\"印度卢比\",\"code\":\"INR\"},{\"name\":\"伊拉克第纳尔\",\"code\":\"IQD\"},{\"name\":\"伊朗里亚尔\",\"code\":\"IRR\"},{\"name\":\"冰岛克朗\",\"code\":\"ISK\"},{\"name\":\"牙买加元\",\"code\":\"JMD\"},{\"name\":\"约旦第纳尔\",\"code\":\"JOD\"},{\"name\":\"肯尼亚先令\",\"code\":\"KES\"},{\"name\":\"吉尔吉斯斯坦索姆\",\"code\":\"KGS\"},{\"name\":\"柬埔寨瑞尔\",\"code\":\"KHR\"},{\"name\":\"科威特第纳尔\",\"code\":\"KWD\"},{\"name\":\"开曼群岛元\",\"code\":\"KYD\"},{\"name\":\"哈萨克斯坦坚戈\",\"code\":\"KZT\"},{\"name\":\"老挝基普\",\"code\":\"LAK\"},{\"name\":\"黎巴嫩镑\",\"code\":\"LBP\"},{\"name\":\"斯里兰卡卢比\",\"code\":\"LKR\"},{\"name\":\"莱索托洛蒂\",\"code\":\"LSL\"},{\"name\":\"利比亚第纳尔\",\"code\":\"LYD\"},{\"name\":\"摩洛哥迪拉姆\",\"code\":\"MAD\"},{\"name\":\"摩尔多瓦列伊\",\"code\":\"MDL\"},{\"name\":\"马其顿第纳尔\",\"code\":\"MKD\"},{\"name\":\"缅甸缅元\",\"code\":\"MMK\"},{\"name\":\"澳门帕塔卡\",\"code\":\"MOP\"},{\"name\":\"毛里求斯卢比\",\"code\":\"MUR\"},{\"name\":\"马拉维客瓦查\",\"code\":\"MWK\"},{\"name\":\"墨西哥比索\",\"code\":\"MXN\"},{\"name\":\"马来西亚令吉\",\"code\":\"MYR\"},{\"name\":\"纳米比亚元\",\"code\":\"NAD\"},{\"name\":\"尼日利亚奈拉\",\"code\":\"NGN\"},{\"name\":\"尼加拉瓜新科多巴\",\"code\":\"NIO\"},{\"name\":\"挪威克朗\",\"code\":\"NOK\"},{\"name\":\"尼泊尔卢比\",\"code\":\"NPR\"},{\"name\":\"新西兰元\",\"code\":\"NZD\"},{\"name\":\"阿曼里亚尔\",\"code\":\"OMR\"},{\"name\":\"巴拿马巴波亚\",\"code\":\"PAB\"},{\"name\":\"秘鲁索尔\",\"code\":\"PEN\"},{\"name\":\"菲律宾比索\",\"code\":\"PHP\"},{\"name\":\"巴基斯坦卢比\",\"code\":\"PKR\"},{\"name\":\"波兰兹罗提\",\"code\":\"PLN\"},{\"name\":\"巴拉圭瓜拉尼\",\"code\":\"PYG\"},{\"name\":\"卡塔尔里亚尔\",\"code\":\"QAR\"},{\"name\":\"罗马尼亚新列伊\",\"code\":\"RON\"},{\"name\":\"塞尔维亚第纳尔\",\"code\":\"RSD\"},{\"name\":\"俄罗斯卢布\",\"code\":\"RUB\"},{\"name\":\"卢旺达法郎\",\"code\":\"RWF\"},{\"name\":\"沙特里亚尔\",\"code\":\"SAR\"},{\"name\":\"塞舌尔卢比\",\"code\":\"SCR\"},{\"name\":\"苏丹镑\",\"code\":\"SDG\"},{\"name\":\"瑞典克朗\",\"code\":\"SEK\"},{\"name\":\"新加坡元\",\"code\":\"SGD\"},{\"name\":\"索马里先令\",\"code\":\"SOS\"},{\"name\":\"斯威士兰埃马兰吉尼\",\"code\":\"SZL\"},{\"name\":\"泰国泰铢\",\"code\":\"THB\"},{\"name\":\"土库曼斯坦马纳特\",\"code\":\"TMT\"},{\"name\":\"突尼斯第纳尔\",\"code\":\"TND\"},{\"name\":\"土耳其新里拉\",\"code\":\"TRY\"},{\"name\":\"特立尼达和多巴哥元\",\"code\":\"TTD\"},{\"name\":\"新台币\",\"code\":\"TWD\"},{\"name\":\"坦桑尼亚先令\",\"code\":\"TZS\"},{\"name\":\"乌克兰格里夫纳\",\"code\":\"UAH\"},{\"name\":\"乌干达先令\",\"code\":\"UGX\"},{\"name\":\"乌拉圭比索\",\"code\":\"UYU\"},{\"name\":\"乌兹别克斯坦索姆\",\"code\":\"UZS\"},{\"name\":\"委内瑞拉玻利瓦尔\",\"code\":\"VES\"},{\"name\":\"越南盾\",\"code\":\"VND\"},{\"name\":\"中非金融合作法郎\",\"code\":\"XAF\"},{\"name\":\"东加勒比元\",\"code\":\"XCD\"},{\"name\":\"非洲金融共同体法郎\",\"code\":\"XOF\"},{\"name\":\"太平洋金融共同体法郎\",\"code\":\"XPF\"},{\"name\":\"也门里亚尔\",\"code\":\"YER\"},{\"name\":\"南非兰特\",\"code\":\"ZAR\"},{\"name\":\"赞比亚克瓦查\",\"code\":\"ZMW\"}]},\"error_code\":0}\n";
    //     JSONObject jsonObject = JSONObject.parseObject(str);
    //     List<JSONObject> list = jsonObject.getJSONObject("result").getJSONArray("list").toJavaList(JSONObject.class);
    //     String a = "currencyMap.put(\"{}\",\"{}\");";
    //     for (JSONObject item : list) {
    //         System.out.println(StrUtil.format(a, item.getString("code"), item.get("name")));
    //     }
    // }

    /**
     * 获取实时汇率
     */
    public static BigDecimal getCnyToCodeRate(String code) {

        if (!currencyMap.containsKey(code)) {
            return BigDecimal.ONE;
        }

        BigDecimal redisRateByCode = getRedisRateByCode(code);
        if (redisRateByCode != null) {
            return redisRateByCode;
        }

        try {
            String body = HttpRequest.get("http://op.juhe.cn/onebox/exchange/currency")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .form("from", code)
                    .form("to", "CNY")
                    .form("version", "2")
                    .form("key", key)
                    .execute()
                    .body();

            JSONObject bodyObject = JSONObject.parseObject(body);

            String reason = bodyObject.getString("reason");
            if (ObjectUtil.notEqual(reason, "查询成功!") && ObjectUtil.notEqual(reason, "successed")) {
                return BigDecimal.ONE;
            }

            List<JSONObject> list = bodyObject.getJSONArray("result").toJavaList(JSONObject.class);

            for (JSONObject item : list) {
                if (ObjectUtil.equals(item.getString("currencyF"), code)) {
                    BigDecimal exchange = item.getBigDecimal("exchange");
                    setRedisRateByCode(code, exchange);
                    return exchange;
                }
            }

        } catch (Exception e) {
            log.error("查询汇率异常", e);
        }

        return BigDecimal.ONE;
    }

    /**
     * 赋值缓存汇率
     */
    private static void setRedisRateByCode(String code, BigDecimal rate) {
        JSONObject json = new JSONObject();
        json.put("rate", rate);
        json.put("date", new Date());
        redisCache.setCacheObject(redisKeyPrefix + code, json, 24, TimeUnit.HOURS);
    }

    /**
     * 获取缓存汇率
     */
    private static BigDecimal getRedisRateByCode(String code) {
        JSONObject json = redisCache.getCacheObject(redisKeyPrefix + code);

        if (json == null) {
            return null;
        }

        Date date = new Date();
        Date recordsDate = json.getDate("date");

        Integer h = Convert.toInt(DateUtil.format(date, "H"));
        Integer m = Convert.toInt(DateUtil.format(date, "m"));

        Integer rh = Convert.toInt(DateUtil.format(recordsDate, "H"));
        Integer rm = Convert.toInt(DateUtil.format(recordsDate, "m"));

        // 今天大于9点半
        if (h > 9 || (h == 9 && m >= 30)) {
            // 保存日期如果不是同一天或者是同一天但小于9点半，删除缓存
            if ((!DateUtil.isSameDay(date, recordsDate)) || (rh < 9 || (rh == 9 && rm < 30))) {
                redisCache.deleteObject(redisKeyPrefix + code);
                return null;
            }
        }
        // 不大于9点半
        else {
            // 保存时间如果不是同一天且小于9点半，删除缓存
            if ((!DateUtil.isSameDay(date, recordsDate)) && (rh < 9 || (rh == 9 && rm < 30))) {
                redisCache.deleteObject(redisKeyPrefix + code);
                return null;
            }
        }

        return json.getBigDecimal("rate");
    }

}
