#! /usr/bin/env python3
# -*- coding:utf-8 -*-

"""
执行task任务的脚本
"""

import sys
import os
import time
import datetime
import logging
import traceback


# task任务执行
def injector(level):
    import django
    from django.db import close_old_connections
    from django.db.utils import OperationalError

    sys.path.insert(0, "../..")
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', "apollo.settings")
    django.setup()
    from domain.injector import factory
    from domain.injector.value_object import TaskStatusValue
    from domain.injector.task_queue import TaskQueue
    from injector.models import TaskModel

    logger = logging.getLogger("django")
    queue = TaskQueue.get_queue(level)
    close_old_connections()
    for task_id, status in queue.items():
        # 执行注入流程
        if status in TaskStatusValue.pending():
            logger.info("task_id:{} status:{}".format(task_id, status))
            try:
                task = TaskModel.objects.filter(id=task_id).select_related("partner").first()
                partner = task.partner
                domain = factory.create_by_id(partner.id)
                status, flag = domain.injector(task)
                logger.info("执行注入:{} 状态:{}".format(task_id, status))
            except OperationalError:
                logger.error("OperationalError:{}".format("连接mysql报错"))
                break
            except Exception as e:
                logger.error("Exception:{} 任务{}执行报错,之后进行回收删除。".format(e, task_id))
                traceback.print_exc()
                status, flag = 0, 0
            if not flag:
                logger.error("队列中删除任务:{} 状态:{}".format(task_id, status))
                TaskQueue.delete(level, task_id)
            else:
                logger.error("队列中更新任务:{} 状态:{}".format(task_id, status))
                TaskQueue.update(level, task_id, status)

        # 删除回执失败的任务
        if status in TaskStatusValue.failed():
            TaskQueue.delete(level, task_id)


def cron_injector(level):
    import django
    from django.db import close_old_connections
    from django.db.utils import OperationalError

    sys.path.insert(0, "../..")
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', "apollo.settings")
    django.setup()
    from domain.injector import factory
    from domain.injector.value_object import TaskStatusValue
    from domain.injector.task_queue import TaskQueue
    from injector.models import TaskModel
    logger = logging.getLogger("django")
    queue = TaskQueue.get_cron_queue(level)
    close_old_connections()
    for task_id, cron_datetime in queue.items():
        try:
            cron_datetime = datetime.datetime.strptime(cron_datetime, "%Y-%m-%d %H:%M:%S")
        except Exception as e:
            logger.error("Exception:{} 任务{} 日期设置有问题。".format(e, task_id))
            continue
        now_datetime = datetime.datetime.today()
        status = TaskStatusValue.FILE_PENDING
        if now_datetime >= cron_datetime:
            logger.info("定时任务:{}时间到了:{}".format(task_id, cron_datetime))
            try:
                task = TaskModel.objects.filter(id=task_id).select_related("partner").first()
                TaskModel.objects.filter(id=task_id).update(create_time=now_datetime, update_time=now_datetime)
                partner = task.partner
                domain = factory.create_by_id(partner.id)
                status, flag = domain.injector(task)
            except OperationalError:
                logger.error("OperationalError:{}".format("连接mysql报错"))
                break
            except Exception as e:
                logger.error("Exception:{} 任务{}执行报错,之后进行回收删除。".format(e, task_id))
                status, flag = 0, 0
            if not flag:
                logger.error("定时队列中删除任务:{} 状态:{}".format(task_id, status))
                TaskQueue.delete(level, task_id)
            else:  # 还有其他阶段 转到其他队列
                TaskQueue.add(3, task_id, status)
                logger.error("向抢片队列中写入任务:{} 状态:{}".format(task_id, status))
                # 删除定时任务
                TaskQueue.delete(level, task_id)
                logger.error("定时队列中删除任务:{} 状态:{}".format(task_id, status))

        # 删除回执失败的任务
        if status in TaskStatusValue.failed():
            TaskQueue.delete(level, task_id)


# 注入循环
def main(tick):
    # 抢片 | 优先 | 普通
    cam_tick, priority_tick, common_tick = 2, 307, 601
    cam_lv, priority_lv, common_lv = 3, 2, 1
    cron_lv = 7
    while tick >= 1:
        if tick % cam_tick == 0:
            injector(cam_lv)
            cron_injector(cron_lv)
        if tick % priority_tick == 0:
            injector(priority_lv)
        if tick % common_tick == 0:
            injector(common_lv)
        time.sleep(1)
        tick += 1


if __name__ == '__main__':
    main(1)
