package com.lutao.cloud.oil.runner;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.lutao.cloud.common.core.util.MessageInfo;
import com.lutao.cloud.oil.pojo.entity.VideoInfo;
import com.lutao.cloud.oil.service.AppInfoService;
import com.lutao.cloud.oil.service.CollectLogService;
import com.lutao.cloud.oil.service.VideoInfoService;
import com.lutao.entity.AppInfo;
import com.lutao.entity.CollectLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class VideoInfoExecutor {

    @Resource
    private VideoInfoService videoInfoService;
    @Resource
    private AppInfoService appInfoService;

    @Resource
    private CollectLogService collectLogService;

    private static final String CLIENT_ID = "8a7b785f08d04d439b71bc2b415cb685";
    private static final String CLIENT_SECRET = "OA!Bq_P!";
    private static final String CONTENT_TYPE = "application/json";
    private static final String TOKEN_URL = "http://10.18.17.85:9090/oauth/token";
    private static final String ROOT_URL = "http://10.18.17.85:9090/service/api/api/resource/v1/regions/root";
    private static final String CHILD_URL = "http://10.18.17.85:9090/service/api/artemis/api/resource/v1/regions/subRegions";
    private static final String CAMERA_URL = "http://10.18.17.85:9090/service/api/artemis/api/resource/v1/regions/regionIndexCode/cameras";

    private static Map<String, AppInfo> APP_MAP = new HashMap<>();

    @Resource(name = "redisTemplateAlias")
    private RedisTemplate redisTemplate;

    private static final String LOCK_KEY = "scheduled_task_lock:SecurityRiskAssessmentSummaryInit";

    private boolean acquireLock() {
        // 尝试获取锁，设置超时时间为 1 分钟
        return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, "locked", 1, TimeUnit.MINUTES));
    }

    private void releaseLock() {
        // 释放锁
        redisTemplate.delete(LOCK_KEY);
    }

    public MessageInfo executeManually() {
        return this.execute();
    }


    @Transactional
    @Scheduled(cron = "0 0 1 1 * ?")
    public MessageInfo execute() {
        if (acquireLock()){
            try {

                appInfoService.list().forEach(o -> APP_MAP.put(o.getAppName(), o));

                //清空表
                videoInfoService.remove(null);

                // 获取accessToken
                String accessToken = getAccessToken();
                log.info("accessToken: {}", accessToken);

                // 获取根区域的indexCode
                String rootIndexCode = getRootIndexCode(accessToken);
                log.info("rootIndexCode: {}", rootIndexCode);

                // 获取三大油视频的indexCode
                String oilVideoIndexCode = threeOilIndex(rootIndexCode, accessToken);
                log.info("oilVideoIndexCode: {}", oilVideoIndexCode);

                // 获取子区域的indexCode
                Map<String, AppInfo> indexCodeMap = getChildIndexCodes(oilVideoIndexCode, accessToken);

                for (String indexCode : indexCodeMap.keySet()) {
                    List<String> subRegions = fetchSubRegions(indexCode, indexCodeMap.get(indexCode), accessToken);
                    for (String subRegion : subRegions) {
                        processCamera(subRegion, indexCodeMap.get(indexCode), accessToken);
                    }
                }
            } catch (Exception e) {
                log.error("视频信息采集失败", e);
                CollectLog collectLog = new CollectLog();
                collectLog.setCommand("error");
                collectLog.setTableName("video_info");
                collectLog.setData("视频信息采集失败::" + e.getMessage());
                collectLogService.save(collectLog);
                return MessageInfo.failed();
            }finally {
                releaseLock();
            }
        }
        return MessageInfo.ok();
    }

    private String getAccessToken() {


        String body = HttpUtil.createGet(TOKEN_URL)
                .header("client_id", CLIENT_ID)
                .header("client_secret", CLIENT_SECRET)
                .header("Content-Type", CONTENT_TYPE)

                .execute().body();

        JSONObject tokenBody = JSONUtil.parseObj(body);
        return tokenBody.getStr("access_token");
    }

    private String getRootIndexCode(String accessToken) {
        JSONObject newRequestBody = JSONUtil.createObj().putOnce("parentIndexCode", "parentIndexCode");

        String rootBody = HttpUtil.createPost(ROOT_URL)
                .header("client_id", CLIENT_ID)
                .header("access_token", accessToken)
                .body(newRequestBody.toString())
                .execute().body();


        return JSONUtil.parseObj(rootBody)
                .getJSONObject("data")
                .getJSONArray("list")
                .getJSONObject(0)
                .getStr("indexCode");
    }

    private String threeOilIndex(String parentIndexCode, String accessToken) {
        JSONObject newRequestBody = JSONUtil.createObj().putOnce("parentIndexCode", parentIndexCode);

        String childBody = HttpUtil.createPost(CHILD_URL)
                .header("client_id", "8a7b785f08d04d439b71bc2b415cb685")
                .header("access_token", accessToken)
                .body(newRequestBody.toString())
                .execute().body();

        JSONObject childJsonObject = JSONUtil.parseObj(childBody);
        JSONArray childList = childJsonObject.getJSONObject("data").getJSONArray("list");

        String oilVideoIndexCode = null;
        for (int i = 0; i < childList.size(); i++) {
            JSONObject item = childList.getJSONObject(i);
            if ("三大油视频".equals(item.getStr("name"))) {
                oilVideoIndexCode = item.getStr("indexCode");
                //存储 oilVideoIndexCode
                VideoInfo videoInfo = new VideoInfo();
                videoInfo.setName(item.get("name").toString());
                videoInfo.setIndexCode(item.get("indexCode").toString());
                videoInfo.setParentIndexCode(item.get("parentIndexCode").toString());
                //videoInfoService.save(videoInfo);
                break;
            }
        }

        return oilVideoIndexCode;
    }

    private Map<String, AppInfo> getChildIndexCodes(String parentIndexCode, String accessToken) {
        JSONObject requestBody = JSONUtil.createObj().putOnce("parentIndexCode", parentIndexCode);

        String childBody = HttpUtil.createPost(CHILD_URL)
                .header("client_id", CLIENT_ID)
                .header("access_token", accessToken)
                .body(requestBody.toString())
                .execute().body();

        JSONObject childJsonObject = JSONUtil.parseObj(childBody);
        JSONArray childList = childJsonObject.getJSONObject("data").getJSONArray("list");

        Map<String, AppInfo> indexCodeMap = new LinkedHashMap<>();
        for (int i = 0; i < childList.size(); i++) {
            JSONObject item = childList.getJSONObject(i);

            VideoInfo videoInfo = new VideoInfo();
            String name = item.getStr("name");
            switch (name) {
                case "中石油":
                    videoInfo.setCompanyCode(APP_MAP.get(name).getCompanyCode());
                    videoInfo.setCompanyName(APP_MAP.get(name).getCompanyName());
                    break;
                case "中石化":
                    videoInfo.setCompanyCode(APP_MAP.get(name).getCompanyCode());
                    videoInfo.setCompanyName(APP_MAP.get(name).getCompanyName());
                    break;
                case "中海油":
                    videoInfo.setCompanyCode(APP_MAP.get(name).getCompanyCode());
                    videoInfo.setCompanyName(APP_MAP.get(name).getCompanyName());
                    break;
                default:
                    break;
            }

            videoInfo.setName(item.get("name").toString());
            videoInfo.setIndexCode(item.get("indexCode").toString());
            videoInfo.setParentIndexCode(item.get("parentIndexCode").toString());
            videoInfoService.save(videoInfo);
            indexCodeMap.put(item.getStr("indexCode"), APP_MAP.get(name));

        }
        return indexCodeMap;
    }


    private void processCamera(String subRegion, AppInfo appInfo, String accessToken) {
        JSONObject cameraRequestBody = JSONUtil.createObj()
                .putOnce("regionIndexCode", subRegion)
                .putOnce("pageNo", 1)
                .putOnce("pageSize", 1000);

        String cameraBody = HttpUtil.createPost(CAMERA_URL)
                .header("client_id", CLIENT_ID)
                .header("access_token", accessToken)
                .body(cameraRequestBody.toString())
                .execute().body();
        log.info("cameraBody: {}", cameraBody);
        log.info("subRegion: {}", subRegion);

        JSONObject cameraJsonObject = JSONUtil.parseObj(cameraBody);
        //JSONArray cameraList = cameraJsonObject.getJSONObject("data").getJSONArray("list");
        JSONObject data = cameraJsonObject.getJSONObject("data");
        if (data != null) {
            JSONArray cameraList = data.getJSONArray("list");
            for (int i = 0; i < cameraList.size(); i++) {
                JSONObject cameraItem = cameraList.getJSONObject(i);

                String cameraIndexCode = cameraItem.getStr("cameraIndexCode");
                String name = cameraItem.getStr("name");

                VideoInfo videoInfo = new VideoInfo();
                videoInfo.setCompanyCode(appInfo.getCompanyCode());
                videoInfo.setCompanyName(appInfo.getCompanyName());
                videoInfo.setName(name);
                videoInfo.setCameraIndexCode(cameraIndexCode);
                videoInfo.setParentIndexCode(cameraItem.getStr("unitIndexCode"));
                videoInfo.setStatus(cameraItem.getStr("status"));
                videoInfoService.save(videoInfo);

            }
        }

    }

    public List<String> fetchSubRegions(String parentIndexCode, AppInfo appInfo, String accessToken) {
        List<String> indexCodes = new ArrayList<>();
        JSONObject requestBody = JSONUtil.createObj().putOnce("parentIndexCode", parentIndexCode);
        String body = HttpUtil.createPost(CHILD_URL)
                .header("client_id", CLIENT_ID)
                .header("access_token", accessToken)
                .body(requestBody.toString())
                .execute().body();

        JSONObject jsonObject = JSONUtil.parseObj(body);
        JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("list");
        int total = jsonObject.getJSONObject("data").getInt("total");

        if (total == 0) {
            indexCodes.add(parentIndexCode);
        } else {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject item = jsonArray.getJSONObject(i);
                String indexCode = item.getStr("indexCode");
                VideoInfo videoInfo = new VideoInfo();
                videoInfo.setCompanyCode(appInfo.getCompanyCode());
                videoInfo.setCompanyName(appInfo.getCompanyName());
                videoInfo.setName(item.get("name").toString());
                videoInfo.setIndexCode(item.get("indexCode").toString());
                videoInfo.setParentIndexCode(item.get("parentIndexCode").toString());
                videoInfoService.save(videoInfo);
                // 递归获取子区域
                indexCodes.addAll(fetchSubRegions(indexCode, appInfo, accessToken));
            }
        }
        return indexCodes;
    }


}
