import json
import os
import sys
from typing import Dict
import requests

sys.path.append(os.path.dirname(sys.path[0]))


class DolphinschedulerHelper(object):
    _admin_token = "2a761f0d17baac7ac6ac4a23fe6f33df"
    _ip_port = "http://113.100.143.162:12345"
    _project_map = {}
    _project_df_map = {}

    @classmethod
    def get_http_header(cls):
        return {
            "token": cls._admin_token,
        }
        pass

    @classmethod
    def get_project_map(cls):
        if len(cls._project_map) == 0:
            url = f"{cls._ip_port}/dolphinscheduler/projects"
            resp = requests.get(
                url,
                headers=cls.get_http_header(),
                params={
                    "pageNo": 1,
                    "pageSize": 10,
                }
            )
            resp_json = json.loads(resp.content.decode("utf-8"))

            for item in resp_json['data']['totalList']:
                cls._project_map[item['name']] = item['code']

        return cls._project_map

    @classmethod
    def get_project_df_map(cls, project_code):
        if cls._project_df_map.get(project_code) == None:
            url = f"{cls._ip_port}/dolphinscheduler/projects/{project_code}/process-definition/simple-list"
            resp = requests.get(
                url,
                headers=cls.get_http_header()
            )
            resp_json = json.loads(resp.content.decode("utf-8"))

            cls._project_df_map[project_code] = {}

            for item in resp_json['data']:
                cls._project_df_map[project_code][item['name']] = item['code']

        return cls._project_df_map[project_code]


    @classmethod
    def start_process_instance_common(cls, project_name: str,
                               process_df_name: str,
                               startParams: Dict,
                               # 警告类型
                               warning_Type: str = "NONE"
                               ):
        """
        启动一个海豚流程
        :param project_name:  项目名
        :param process_df_name: 流程名
        :param startParams: 启动全局参数
        :param warning_Type: 警告类型 NONE ALL
        :return:
        """
        print(f"startParams: {startParams}")
        start_params = startParams
        project_map = cls.get_project_map()
        project_code = project_map.get(project_name)
        process_df_map: Dict = cls.get_project_df_map(project_code)

        process_df_code = process_df_map.get(process_df_name)

        url = f"{cls._ip_port}/dolphinscheduler/projects/{project_code}/executors/start-process-instance"

        startParams['_sender'] = "api"
        # processDefinitionCode: 9651368013984
        # scheduleTime:
        # failureStrategy: CONTINUE
        # warningType: ALL
        # warningGroupId: 5
        # execType:
        # startNodeList:
        # taskDependType: TASK_POST
        # runMode: RUN_MODE_SERIAL
        # processInstancePriority: MEDIUM
        # workerGroup: default
        # environmentCode: 5769107604288
        # startParams: {"site_name":"us","date_type":"week","wx_user":"wujicang"}
        # expectedParallelismNumber:
        # dryRun: 0
        req_params = {
            "processDefinitionCode": process_df_code,
            "scheduleTime": "",
            # 失败策略
            "failureStrategy": "CONTINUE",
            "warningType": warning_Type,
            # 告警组 2 是http推送报警
            "warningGroupId": "2",
            "execType": "",
            "startNodeList": "",
            "taskDependType": "TASK_POST",
            "runMode": "RUN_MODE_SERIAL",
            "processInstancePriority": "MEDIUM",
            "workerGroup": "h5",
            # 环境组
            "environmentCode": "10337211525600",
            "startParams": json.dumps(startParams),
            "expectedParallelismNumber": "",
            "dryRun": "0",
        }
        print(req_params)
        resp = requests.post(
            url,
            headers=cls.get_http_header(),
            data=req_params
        )
        resp_json = json.loads(resp.content.decode("utf-8"))
        resp_state = bool(resp_json['success'])
        title = f"【海豚调度】调度api触发提示"

        if resp_state:
            DolphinschedulerHelper.send_startup_state_to_oa(project_name, f"{process_df_name}, 参数 {':'.join(start_params.values())}", resp_state)
            return True
        else:
            DolphinschedulerHelper.send_startup_state_to_oa(project_name, f"{process_df_name}, 参数 {':'.join(start_params.values())}", resp_state)
            raise Exception(f"任务【{project_name}/f'{process_df_name}, 参数 {':'.join(start_params.values())}'】调度失败！")

    @classmethod
    def send_wx_msg(cls, users: list, title: str, content: str, msgtype: str = "textcard"):
        """
        通过选品wx消息推送接口，推送消息到oa
        :param users: 填写需要推送的微信用户名list
        :param title: 推送的标题（如果msgtype采用markdown形式，则不附带标题）
        :param content: 推送的主体内容
        :param msgtype: 推送的消息类型（textcard：默认卡片类型；markdown：markdaown结构）
        """
        if users is not None:
            accounts = ",".join(users)
            # 排除users_list=[''] 无需发送
            if bool(accounts):
                host = "http://120.79.147.190:8080"
                url = f'{host}/soundasia_selection/dolphinScheduler/sendMessage'
                data = {
                    'account': accounts,
                    'title': title,
                    'content': content,
                    'msgtype': msgtype
                }
                try:
                    requests.post(url=url, data=data, timeout=15)
                except:
                    pass
        return True

    @classmethod
    def send_startup_state_to_oa(cls, project_name: str, process_df_name: str, resp_state: bool):
        """
        根据api触发海豚oa消息推送（推送人由维护在海豚调度任务中的wx_user决定）
        :param project_name:项目名称
        :param process_df_name:流程名称
        :param resp_state:任务调度启动状态
        :return
        """
        wx_user_list = DolphinschedulerHelper.get_process_df_manger(project_name, process_df_name)
        title = f"【海豚调度】调度api触发提示"
        if resp_state:
            msg = f"项目【{project_name}】,流程【{process_df_name}】api任务触发成功！"
        else:
            msg = f"项目【{project_name}】,流程【{process_df_name}】api任务触发异常，请查看日志！"
        if bool(wx_user_list):
            DolphinschedulerHelper.send_wx_msg(wx_user_list, title, msg)

    @classmethod
    def get_process_df_manger(cls, project_name: str, process_df_name: str):
        """
        获取海豚流程定义的全局变量对应的wx_user
        :param project_name:
        :param process_df_name:
        :return:
        """
        project_map = cls.get_project_map()
        project_code = project_map.get(project_name)
        process_df_map: Dict = cls.get_project_df_map(project_code)
        process_df_code = process_df_map.get(process_df_name)
        url = f"{cls._ip_port}/dolphinscheduler/projects/{project_code}/process-definition/{process_df_code}/view-variables"

        resp = requests.get(
            url,
            headers=cls.get_http_header(),
        )
        resp_json = json.loads(resp.content.decode("utf-8"))
        if bool(resp_json['success']):
            globalParams: list = resp_json['data']['globalParams']
            paramMap = {param['prop']: param['value'] for param in globalParams}
            wx_user = paramMap.get("wx_user") or ""
            return wx_user.split(",")
        return None
