package com.bcrjl.miwifi.common.util;

import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bcrjl.miwifi.model.param.DeleteRedirectParam;
import com.bcrjl.miwifi.model.param.RangeRedirectParam;
import com.bcrjl.miwifi.model.param.RedirectParam;
import com.bcrjl.miwifi.model.result.PppoeStatusResult;
import com.bcrjl.miwifi.model.result.RangeRedirectResult;
import com.bcrjl.miwifi.model.result.RedirectResult;
import com.bcrjl.miwifi.model.result.StatusResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.HttpCookie;
import java.util.*;
import java.util.stream.Collectors;

import static com.bcrjl.miwifi.common.constant.ApiConstant.*;
import static com.bcrjl.miwifi.common.constant.AppConstant.HTTP;
import static com.bcrjl.miwifi.common.constant.AppConstant.INIT_MAP;

/**
 * 小米/红米路由器 工具类
 *
 * @author yanqs
 */
@Slf4j
@Component
public class MiWifiUtil {

    /**
     * 登录信息
     */
    public static Map<String, Object> loginInfo = null;
    /**
     * token
     */
    public static String token;
    /**
     * cookie
     */
    public static List<HttpCookie> cookie;
    /**
     * 路由器地址
     */
    @Value("${bmw.url:192.168.31.1}")
    private String WIFI_URL;
    /**
     * 路由器密码
     */
    @Value("${bmw.password:123456}")
    private String WIFI_PASSWORD;

    /**
     * 获取网关前缀
     *
     * @return 网关前缀
     */
    public String getGatewayPrefix() {
        String gateWay = "";
        List<String> gateWayStrList = Arrays.stream(WIFI_URL.split("\\.")).collect(Collectors.toList());
        int lastIndex = gateWayStrList.size() - 1;
        if (lastIndex >= 0) {
            gateWayStrList = gateWayStrList.subList(0, lastIndex);
        }
        for (String s : gateWayStrList) {
            gateWay += s + ".";
        }
        return gateWay;
    }

    /**
     * 外网状态
     *
     * @return
     */
    public PppoeStatusResult getPppoeStatus() {
        initLoginInfo();
        String url = HTTP + WIFI_URL + MIDDLE_URL + token + PPPOE_STATUS;
        HttpRequest request = HttpRequest.get(url).cookie(cookie);
        HttpResponse response = request.execute();
        log.info("外网状态：{}", response.body());
        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        if (jsonObject.getInt("code") == 0) {
            return JSONUtil.toBean(response.body(), PppoeStatusResult.class);
        }
        return null;
    }

    /**
     * 删除映射数据
     *
     * @param param 请求参数
     * @return map
     */
    public Map<String, Object> deleteRedirect(DeleteRedirectParam param) {
        Map<String, Object> result = new HashMap<>(INIT_MAP);
        initLoginInfo();
        String url = HTTP + WIFI_URL + MIDDLE_URL + token + NETWORK_DELETE_REDIRECT;
        HttpRequest request = HttpRequest.post(url)
                .cookie(cookie)
                .form("port", param.getPort())
                .form("proto", param.getProto());
        HttpResponse response = request.execute();
        log.info("删除端口转发：{}", response.body());
        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        if (jsonObject.getInt("code") == 0) {
            result.put("status", true);
        } else {
            result.put("status", false);
            result.put("msg", jsonObject.getStr("msg"));
        }
        return result;
    }

    /**
     * 添加端口(范围)转发
     *
     * @param param 参数
     * @return map
     */
    public Map<String, Object> addRangeRedirect(RangeRedirectParam param) {
        Map<String, Object> result = new HashMap<>(INIT_MAP);
        initLoginInfo();
        String url = HTTP + WIFI_URL + MIDDLE_URL + token + NETWORK_ADD_RANGE_REDIRECT;
        HttpRequest request = HttpRequest.post(url)
                .form("name", param.getName())
                .form("proto", param.getProto())
                .form("fport", param.getFport())
                .form("tport", param.getTport())
                .form("ip", param.getIp())
                .cookie(cookie);
        // 发送请求并获取响应
        HttpResponse response = request.execute();
        log.info("添加端口范围转发：{}", response.body());
        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        if (jsonObject.getInt("code") == 0) {
            result.put("status", true);
            result.put("data", jsonObject.get("data"));
        } else {
            result.put("status", false);
            result.put("msg", jsonObject.getStr("msg"));
        }
        return result;
    }


    /**
     * 添加端口(单端口)转发
     *
     * @param param 请求参数
     * @return map
     */
    public Map<String, Object> addRedirect(RedirectParam param) {
        Map<String, Object> result = new HashMap<>(INIT_MAP);
        initLoginInfo();
        String url = HTTP + WIFI_URL + MIDDLE_URL + token + NETWORK_ADD_REDIRECT;
        HttpRequest request = HttpRequest.post(url)
                .form("name", param.getName())
                .form("proto", param.getProto())
                .form("sport", param.getSport())
                .form("ip", param.getIp())
                .form("dport", param.getDport())
                .cookie(cookie);
        // 发送请求并获取响应
        HttpResponse response = request.execute();
        log.info("添加端口转发：{}", response.body());
        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        if (jsonObject.getInt("code") == 0) {
            result.put("status", true);
        } else {
            result.put("status", false);
            result.put("msg", jsonObject.getStr("msg"));
        }
        return result;
    }

    /**
     * 获取端口转发列表
     *
     * @param type 类型
     * @return List
     */
    public List portForward(Integer type) {
        initLoginInfo();
        String url = HTTP + WIFI_URL + MIDDLE_URL + token + NETWORK_PORT_FORWARD + "?ftype=" + type;
        HttpResponse execute = HttpRequest.get(url).cookie(cookie).execute();
        log.info("端口转发列表：{}", execute.body());
        JSONObject jsonObject = JSONUtil.parseObj(execute.body());
        if (jsonObject.getInt("code") == 0 && jsonObject.getInt("status") != 0) {
            String list = jsonObject.getStr("list");
            if (type.equals(1)) {
                // 单端口转发
                return JSONUtil.toList(list, RedirectResult.class);
            } else if (type.equals(2)) {
                // 范围端口转发
                return JSONUtil.toList(list, RangeRedirectResult.class);
            }
        }
        return null;
    }

    /**
     * 获取路由器信息
     *
     * @return StatusResult
     */
    public StatusResult getStatus() {
        initLoginInfo();
        String url = HTTP + WIFI_URL + MIDDLE_URL + token + SYSTEM_STATUS;
        HttpResponse execute = HttpRequest.get(url).cookie(cookie).execute();
        log.info("系统状态：{}", execute.body());
        StatusResult result = JSONUtil.toBean(execute.body(), StatusResult.class);
        if (result.getCode() == 0) {
            return result;
        } else {
            getLoginInfo();
            return getStatus();
        }
    }

    /**
     * 登录路由器 获取配置信息
     *
     * @return Map
     */
    public Map<String, Object> getLoginInfo() {
        Map<String, Object> formDate = new HashMap<>();
        formDate.put("username", "admin");
        formDate.put("password", WIFI_PASSWORD);
        String url = HTTP + WIFI_URL + SYSTEM_LOGIN;
        HttpResponse execute = HttpRequest.post(url).form(formDate)
                .header(Header.CONTENT_TYPE, ContentType.FORM_URLENCODED.toString())
                .execute();
        JSONObject jsonObject = JSONUtil.parseObj(execute.body());
        if (jsonObject.getInt("code") == 0) {
            loginInfo = new HashMap<>(INIT_MAP);
            loginInfo.put("token", jsonObject.getStr("token"));
            loginInfo.put("cookie", execute.getCookies());
            token = jsonObject.getStr("token");
            cookie = execute.getCookies();
            return loginInfo;
        }
        return null;
    }

    /**
     * 初始化登录信息
     */
    private void initLoginInfo() {
        if (Objects.isNull(MiWifiUtil.loginInfo)) {
            getLoginInfo();
        }
    }
}
