package com.jiayue.insu.incloud.controller;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.jiayue.insu.incloud.constants.CommonStant;
import com.jiayue.insu.incloud.entity.ForecastData;
import com.jiayue.insu.incloud.entity.Record;
import com.jiayue.insu.incloud.entity.Station;
import com.jiayue.insu.incloud.service.ApiService;
import com.jiayue.insu.incloud.service.ForecastDataService;
import com.jiayue.insu.incloud.service.RecordService;
import com.jiayue.insu.incloud.service.StationService;
import com.jiayue.insu.incloud.utils.JsonResultUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;

/**
 * 对外接口
 * ApiController
 *
 * @author zcl
 * @date 2023-03-24 15:48:48
 */
@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/pfserver")
public class ApiController {
    @Autowired
    ApiService apiService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    public StationService stationService;
    @Autowired
    public RecordService recordService;
    @Autowired
    public ForecastDataService forecastDataService;

    /**
     * 获取token
     *
     * @param request
     * @return
     */
    @PostMapping("/token")
    public JSONObject getToken(HttpServletRequest request) {
        //校验授权信息并返回用户名及密码
        JSONObject checkResult = checkAuthorization(request);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_COM_PERMISSON, null, null, null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        // 根据用户名密码获取token
        JSONObject result = apiService.getToken(checkResult.getJSONObject(JsonResultUtil.DATA_TAG));
        Record record = new Record(CommonStant.RECORD_TYPE_COM_PERMISSON, null, null, null, LocalDateTime.now(), LocalDateTime.now(), result.getStr(JsonResultUtil.MSG_TAG), result.getStr(JsonResultUtil.CODE_TAG));
        recordService.save(record);
        return result;
    }

    /**
     * 获取短期原始数据
     *
     * @param request
     * @return
     */
    @PostMapping("/getShortWpfData")
    public JSONObject getShortWpfData(HttpServletRequest request, @RequestBody JSONObject data) {
        Station station = new Station();
        // 入参验证
        JSONObject checkResult = checkRequest(request, data, station);
        String inCode = getInCode(station);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PULL_INIT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        // 返回短期数据json格式
        JSONObject result = apiService.getShortWpfData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PULL_INIT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr(JsonResultUtil.MSG_TAG), result.getStr(JsonResultUtil.CODE_TAG));
        recordService.save(record);
        return result;
    }

    /**
     * 获取nwp原始数据
     *
     * @param request
     * @return
     */
    @PostMapping("/getNwpData")
    public JSONObject getNwpData(HttpServletRequest request, @RequestBody JSONObject data) {
        Station station = new Station();
        // 入参验证
        JSONObject checkResult = checkRequest(request, data, station);
        String inCode = getInCode(station);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PULL_NWP_INIT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        // 返回短期数据json格式
        JSONObject result = apiService.getNwpData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PULL_NWP_INIT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr(JsonResultUtil.MSG_TAG), result.getStr(JsonResultUtil.CODE_TAG));
        recordService.save(record);
        return result;
    }

    /**
     * 接收短期预测修正数据
     *
     * @param request
     * @return
     */
    @PostMapping("/putShortWpfData")
    public JSONObject putShortWpfData(HttpServletRequest request, @RequestBody JSONObject data) {
        Station station = new Station();
        // 入参验证
        JSONObject checkResult = checkRequest(request, data, station);
        String inCode = getInCode(station);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PUT_DQ_CORRECT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        JSONObject result = apiService.putShortWpfData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PUT_DQ_CORRECT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr(JsonResultUtil.MSG_TAG), result.getStr(JsonResultUtil.CODE_TAG));
        recordService.save(record);
        // 返回短期数据json格式
        return result;
    }

    /**
     * 获取超短期原始数据
     *
     * @param request
     * @return
     */
    @PostMapping("/getSShortWpfData")
    public JSONObject getSShortWpfData(HttpServletRequest request, @RequestBody JSONObject data) {
        Station station = new Station();
        // 入参验证
        JSONObject checkResult = checkRequest(request, data, station);
        String inCode = getInCode(station);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PULL_CDQ, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        // 返回超短期数据json格式
        JSONObject result = apiService.getSShortWpfData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PULL_CDQ, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr(JsonResultUtil.MSG_TAG), result.getStr(JsonResultUtil.CODE_TAG));
        recordService.save(record);
        return result;
    }

    /**
     * 接收超短期预测修正数据
     *
     * @param request
     * @return
     */
    @PostMapping("/putSShortWpfData")
    public JSONObject putSShortWpfData(HttpServletRequest request, @RequestBody JSONObject data) {
        Station station = new Station();
        // 入参验证
        JSONObject checkResult = checkRequest(request, data, station);
        String inCode = getInCode(station);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PUT_CDQ_CORRECT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        // 返回短期数据json格式
        JSONObject result = apiService.putSShortWpfData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PUT_CDQ_CORRECT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr(JsonResultUtil.MSG_TAG), result.getStr(JsonResultUtil.CODE_TAG));
        recordService.save(record);
        return result;
    }

    /**
     * 校验授权信息并返回用户名密码
     *
     * @return
     */
    public JSONObject checkAuthorization(HttpServletRequest request) {
        // 获取授权信息
        String authorization = request.getHeader(CommonStant.AUTHORIZATION);
        // 如果授权信息不存在，返回失败
        if (authorization == null) {
            return JsonResultUtil.failure("authorization授权不存在");
        }
        // 将"用户名:密码"格式的数据拆分
        String[] authorizationArr = authorization.split(CommonStant.CHARACTER_COLON);
        // 如果根据冒号拆分后的数据长度小于2，则返回失败
        if (authorizationArr.length < 2) {
            return JsonResultUtil.failure("用户名:密码 格式不正确");
        }
        // 获取用户列表
        Map<String, String> userMap = redisTemplate.opsForHash().entries(CommonStant.REDIS_USERS);
        // 如果用户列表为空，返回失败
        if (userMap == null) {
            return JsonResultUtil.failure("用户列表为空");
        }
        // 根据用户名(authorizationArr[0])查找密码
        String password = userMap.get(authorizationArr[0]);
        // 如果密码为空，则证明用户不存在
        if (password == null) {
            return JsonResultUtil.failure("用户名不存在");
        }

        // 放入用户信息
        JSONObject userInfo = new JSONObject();
        // 请求的密码
        userInfo.set(CommonStant.REQUEST_USER_PASS, authorizationArr[1]);
        // 请求的用户名
        userInfo.set(CommonStant.REQUEST_USER_NAME, authorizationArr[0]);
        return JsonResultUtil.success(userInfo);
    }

    /**
     * 校验授权信息并返回用户名密码
     *
     * @return
     */
    public JSONObject checkToken(HttpServletRequest request) {
        // 授权校验结果
        JSONObject checkResult = checkAuthorization(request);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            return checkResult;
        }
        // 如果授权格式校验成功，获取用户名和token
        JSONObject userInfo = checkResult.getJSONObject(JsonResultUtil.DATA_TAG);
        // 校验token
        String requestUserName = userInfo.getStr(CommonStant.REQUEST_USER_NAME);
        // 用户传入的token
        String requestToken = userInfo.getStr(CommonStant.REQUEST_USER_PASS);
        // 拼接kdy名 例如：integration:cloud:userToken:user1
        String key = CommonStant.REDIS_USER_TOKEN + CommonStant.CHARACTER_COLON + requestUserName;
        // redis中存的token
        String token = String.valueOf(redisTemplate.opsForValue().get(key));
        // 如果token不同，校验失败
        if (!token.equals(requestToken)) {
            return JsonResultUtil.failure("token校验失败");
        }
        return JsonResultUtil.success();
    }

    /**
     * 入参校验
     *
     * @return
     */
    public JSONObject checkRequest(HttpServletRequest httpRequest, JSONObject requestJson, Station station) {
        // 验证token
        JSONObject tokenResult = checkToken(httpRequest);
        if (JsonResultUtil.Type.failure.value().equals(tokenResult.get(JsonResultUtil.CODE_TAG))) {
            return tokenResult;
        }

        if (requestJson == null) {
            log.info("接收到的数据为空");
            return JsonResultUtil.failure("接收到的数据为空");
        }

        JSONArray stationCodeArr = new JSONArray();
        // 获取场站id
        if ((requestJson.get("wfId") instanceof JSONArray)) {
            stationCodeArr = (requestJson.getJSONArray("wfId"));
        } else {
            stationCodeArr.add(requestJson.get("wfId"));
        }

        // 如果场站id为空
        if (stationCodeArr == null || stationCodeArr.size() == 0) {
            log.info("场站id为空");
            return JsonResultUtil.failure("场站id为空");
        }

        if (stationCodeArr.size() == 1) {
            // 根据场站编号查询场站信息
            station = stationService.findByStationCode(stationCodeArr.get(0).toString());
            // 如果场站信息为空
            if (station == null) {
                log.info("场站信息为空");
                return JsonResultUtil.failure("场站信息为空");
            }
        }
        return JsonResultUtil.success();
    }

    /**
     * 获取inCode
     *
     * @param station
     * @return
     */
    public String getInCode(Station station) {
        String inCode = "";
        if (station != null) {
            inCode = station.getInCode();
        }
        return inCode;
    }


    /*----------------------------------------------------------以下为新增-----------------------------------------------------------------*/

    /**
     * 获取短期修正数据（飔合科技）
     *
     * @param request
     * @return
     */
    @PostMapping("/getCorrectShort")
    public JSONObject getCorrectShort(HttpServletRequest request, @RequestBody JSONObject data) {

        // 飔合科技入参验证
        Station station = new Station();
        JSONObject checkResult = checkRequest(request, data, station);
        String inCode = getInCode(station);
        // 如果校验结果为失败
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PULL_CORRECT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        // 根据场站编号获取场站信息
        station = stationService.findByStationCode((String) data.get("wfId"));
        // 获取文件生成日期
        String initTime = (String) data.get("init_time");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串转换为LocalDateTime
        LocalDateTime dateTime = LocalDateTime.parse(initTime, formatter);
        // 返回短期数据json格式
        JSONObject result = apiService.getSHCorrect(station, dateTime);
        Record record = new Record(CommonStant.RECORD_TYPE_PULL_CORRECT, inCode, data.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr(JsonResultUtil.MSG_TAG), result.getStr(JsonResultUtil.CODE_TAG));
        recordService.save(record);
        return result;
    }

    /**
     * 获取武穴原始超短期数据
     *
     * @param request
     * @param data
     * @return
     */
    @PostMapping("/getUltraShortTermData")
    public JSONObject getUltraShortTermData(HttpServletRequest request, @RequestBody JSONObject data) {
        // 武穴一体化入参验证
        Station station = new Station();
        JSONObject checkResult = checkRequestForWX(request, data, station);
        // 如果校验结果为失败
        String inCode = getInCode(station);
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PUSH_INIT, inCode, data.getStr("stationIds"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        JSONObject result = apiService.getUltraShortTermData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PUSH_INIT, inCode, data.getStr("stationIds"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr("message"), result.getStr("statusCode"));
        recordService.save(record);
        return result;
    }


    /**
     * 接收武穴原始超短期
     *
     * @param request
     * @param data
     * @return
     */
    @PostMapping("/putUltraShortTermData")
    public JSONObject putUltraShortTermData(HttpServletRequest request, @RequestBody JSONObject data) {
        // 武穴一体化入参验证
        Station station = new Station();
        JSONObject checkResult = checkRequestForWX(request, data, station);
        // 如果校验结果为失败
        String inCode = getInCode(station);
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PUT_CDQ, inCode, data.getStr("stationIds"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        JSONObject result = apiService.putUltraShortTermData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PUT_CDQ, inCode, data.getStr("stationIds"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr("retMsg"), result.getStr("retCode"));
        recordService.save(record);
        return result;
    }


    /**
     * 接收浙江洋城光伏实际功率数据
     *
     * @param request
     * @param data
     * @return
     */
    @PostMapping("/putRealValueData")
    public JSONObject putRealValueData(HttpServletRequest request, @RequestBody JSONObject data) {
        // 武穴一体化入参验证
        Station station = new Station();
        JSONObject checkResult = checkRequestForWX(request, data, station);
        // 如果校验结果为失败
        String inCode = getInCode(station);
        if (JsonResultUtil.Type.failure.value().equals(checkResult.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PUT_REAL, inCode, data.getStr("stationIds"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
            return checkResult;
        }
        JSONObject result = apiService.putRealValueData(data);
        Record record = new Record(CommonStant.RECORD_TYPE_PUT_REAL, inCode, data.getStr("stationIds"), null, LocalDateTime.now(), LocalDateTime.now(), result.getStr("retMsg"), result.getStr("retCode"));
        recordService.save(record);
        return result;
    }

    /**
     * 入参校验(武穴/浙江中广核 共用)
     *
     * @return
     */
    public JSONObject checkRequestForWX(HttpServletRequest httpRequest, JSONObject requestJson, Station station) {

        // 校验用户名密码
        String authorization = httpRequest.getHeader(CommonStant.AUTHORIZATION);

        // 如果授权信息不存在，返回失败
        if (authorization == null) {
            return JsonResultUtil.failure("authorization授权不存在");
        }
        // 身份
        String[] info = authorization.split(CommonStant.SPACE1_CONSTANT);

        String identity = new String(Base64.getDecoder().decode(info[1]));
        if (identity.contains(CommonStant.CHARACTER_COLON)) {
            String passwordWx = identity.split(CommonStant.CHARACTER_COLON)[1];
            // 获取用户列表
            Map<String, String> userMap = redisTemplate.opsForHash().entries(CommonStant.REDIS_USERS);
            // 如果用户列表为空，返回失败
            if (userMap == null) {
                return JsonResultUtil.failure("用户列表为空");
            }
            // 根据用户名查找密码
            String password = userMap.get(identity.split(CommonStant.CHARACTER_COLON)[0]);
            // 如果密码为空，则证明用户不存在
            if (password == null) {
                return JsonResultUtil.failure("用户名不存在");
            }
            if (!password.equals(passwordWx)) {
                return JsonResultUtil.failure("密码不正确");
            }
        }

        if (requestJson == null) {
            log.info("接收到的数据为空");
            return JsonResultUtil.failure("接收到的数据为空");
        }

        JSONArray stationCodeArr = new JSONArray();
        // 获取场站id
        if ((requestJson.get("stationIds") instanceof JSONArray)) {
            stationCodeArr = (requestJson.getJSONArray("stationIds"));
        } else {
            stationCodeArr.add(requestJson.get("stationIds"));
        }

        // 如果场站id为空
        if (stationCodeArr == null || stationCodeArr.size() == 0) {
            log.info("场站id为空");
            return JsonResultUtil.failure("场站id为空");
        }
        if (stationCodeArr.size() == 1) {
            // 根据场站编号查询场站信息
            station = stationService.findByStationCode(stationCodeArr.get(0).toString());
            // 如果场站信息为空
            if (station == null) {
                log.info("场站信息为空");
                return JsonResultUtil.failure("场站信息为空");
            }
        }
        return JsonResultUtil.success();
    }
}
