import os
import tempfile
import threading
import time
import traceback

import django
import keyboard
import mouse
from django.db import close_old_connections
from django.db.models import Q, Value, F, Sum, Subquery, OuterRef, IntegerField, Count, ExpressionWrapper, BooleanField
from django.db.models.functions import Coalesce
from django.utils import timezone

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'futplus.settings')
django.setup()

from squad_battle import calculate_need_game
from accounts.console_bot_settings import allowed_discharge_time
from utils.public_moves import PublicMoves
from sbc.models import SBCWorker, SBCType, SBCProcess
from trade.models import ConsoleTradeOneCard, ConsoleTradeOneHistory
from sbc.public_methods import new_print, set_main_log, set_sub_log, focus_on_ps, has_image, get_screen_shot, \
    get_image_position, process_exists
from accounts.models import Console, FifaAccount, FifaAccountSquadGame, ConsoleBotSetting
from futplus.settings import CONSOLE_NAME, BASE_DIR
from squad_battle.squad_battle_bot import SquadBattleRunner
from trade.console_trade_bot import ConsoleTradeRunner
from sbc.pc_bots import start_pc_bots

fd, path = tempfile.mkstemp()
print(fd, path)

def run_worker(worker_id):
    print('run worker started with worker :', worker_id)
    uncompleted_worker = SBCWorker.objects.filter(id=worker_id).first()
    fifa_account = uncompleted_worker.fifa_account
    fifa_account.refresh_from_db()
    need_works = check_need_work_fifa_account(
        fifa_account,
        console_last_24_hour_played=get_console_last_24_hour_played(fifa_account.console),
        console=fifa_account.console,
        allowed_discharge_time_var=allowed_discharge_time()
    )
    account_works = need_works.first()
    uncompleted_worker.last_run_time = timezone.localtime()
    uncompleted_worker.must_done = False
    uncompleted_worker.save()
    fifa_account.last_run_time = timezone.localtime()
    fifa_account.need_captcha = 0
    fifa_account.active = True
    fifa_account.can_kill_by_mother = False
    fifa_account.save()

    # if not fifa_account.active:
    # print('start fifa account working : ', fifa_account)

    # new_print(fifa_account, 'run worker but can not start squad manager or trade manager')
    # worker_runner = FifaAccount
    # core = fifa_account.refresh_from_db
    lowest_run_hour = ConsoleBotSetting.objects.get(name='lowest_account_run_in_console_hour').int_value

    # default worker runner
    worker_runner = None

    core_list = []
    if not fifa_account.is_running_console_trade_one and (
            account_works.can_play_squad is True or
            account_works.can_discharge is True or
            account_works.can_sbc is True
    ):
        worker_runner = SquadBattleRunner(
            uncompleted_worker.id, fifa_account.id, fifa_account.user_name, fifa_account.password,
            fifa_account.platform, uncompleted_worker.manual_loyal)
        set_sub_log(uncompleted_worker, 'going for squad battle bot ...')
        new_print(fifa_account, 'going for squad battle bot ...')
        core_list.append(worker_runner.squad_battle_core)
    elif fifa_account.is_running_console_trade_one is True:
        last_trade_history = ConsoleTradeOneHistory.objects.filter(fifa_account=fifa_account).last()
        if (
                last_trade_history and
                ((0 <= last_trade_history.transfer_list_items_count <= 95 and
                  account_works.can_discharge is True and
                  last_trade_history.unassigned_item_count <= 0
                 ) or (last_trade_history.transfer_list_items_count <= 95 and
                       last_trade_history.unassigned_item_count <= 0 and
                       (account_works.can_discharge is True or
                        account_works.can_play_squad is True or
                        account_works.can_sbc is True)
                 ))):
            worker_runner = SquadBattleRunner(
                uncompleted_worker.id, fifa_account.id, fifa_account.user_name, fifa_account.password,
                fifa_account.platform, uncompleted_worker.manual_loyal)
            set_sub_log(uncompleted_worker, 'going for squad battle bot 2 ...')
            new_print(fifa_account, 'going for squad battle bot 2 ...')
            core_list.append(worker_runner.squad_battle_core)
    if (
            (fifa_account.run_console_trade_one is True and
             ConsoleTradeOneCard.objects.filter(
                 fifa_account__id=fifa_account.id,
                 create_time__gt=timezone.localtime() - timezone.timedelta(hours=lowest_run_hour)
             ).count() < 1 and
             ConsoleTradeOneHistory.objects.filter(
                 fifa_account__id=fifa_account.id,
                 create_time__gt=timezone.localtime() - timezone.timedelta(hours=lowest_run_hour)).count() < 1 and
             # fifa_account.credit > 10000 and
             fifa_account.is_running_console_trade_one is False) or
            ((ConsoleTradeOneCard.objects.filter(
                fifa_account__id=fifa_account.id,
                deleted=False,
                create_time__lt=timezone.localtime() - timezone.timedelta(hours=1)
            ).count() > 0 or
              fifa_account.is_running_console_trade_one is True) and
             ConsoleTradeOneHistory.objects.exclude(update_time=None).filter(
                 fifa_account__id=fifa_account.id,
                 update_time__gt=timezone.localtime() - timezone.timedelta(hours=lowest_run_hour)).count() < 1)
    ):
        # todo : uncomment bellow after ramin conversation
        # worker_runner = ConsoleTradeRunner(
        #     uncompleted_worker.id, fifa_account.id, fifa_account.user_name, fifa_account.password,
        #     fifa_account.platform, uncompleted_worker.manual_loyal)
        new_print(fifa_account, 'going for trade mode one...')
        # core_list.append(worker_runner.console_trade_bot_core)
    # try:
    #     worker_runner = SquadBattleRunner(
    #         uncompleted_worker.id, fifa_account.id, fifa_account.user_name, fifa_account.password,
    #         fifa_account.platform, uncompleted_worker.manual_loyal)
    # except AssertionError as e:
    #     if str(e) == "The virtual device could not connect to ViGEmBus.":
    #         new_print(fifa_account, e)
    #         uncompleted_worker.refresh_from_db()
    #         uncompleted_worker.status = 'gamepad error'
    #         uncompleted_worker.status_change_time = timezone.localtime()
    #         uncompleted_worker.save()
    #         time.sleep(1000)
    #     return ''
    try:
        # print('core list : ', core_list)
        # print('runner created ', worker_runner.__class__.__name__)
        # try:
        #     # todo : uncomment bellow
        #     # logout_login(worker_runner, uncompleted_worker, fifa_account)
        #     pass
        # except Exception as e:
        #     new_print(fifa_account, 'login in celery task error : ', traceback.format_exc())
        #     # handle_end_bot()

        # fifa_account.refresh_from_db()
        # if fifa_account.active:
        try:
            for core in core_list:
                fifa_account.refresh_from_db()
                fifa_account.active = True
                fifa_account.save()
                new_print(fifa_account, f'before worker {core.__name__} core manager')
                core()
                new_print(fifa_account, f'after worker {core.__name__} core manager')
                fifa_account.refresh_from_db()
                fifa_account.last_run_time = timezone.localtime()
                fifa_account.active = False
                fifa_account.save()
            uncompleted_worker.refresh_from_db()
            uncompleted_worker.is_done = True
            uncompleted_worker.save()
        except Exception as error:
            print('error 94 : ', error)
            traceback.print_exc()
            uncompleted_worker.has_error = True
            uncompleted_worker.error_description = str(error)
            uncompleted_worker.save()
            print('saving error complete')
        # else:
        #     print('fifa account is not active')
        #     uncompleted_worker.has_error = True
        #     uncompleted_worker.error_description = 'error in login'
        #     uncompleted_worker.save()

        print('account work done and want delete game pad')
        # todo : fix bellow code. for change user no need to put on rest mode
        if fifa_account.platform == 'ps' and worker_runner:
            print('need to put on rest mode')
            worker_runner.public_moves.put_on_rest_mode()
            print('sleep 60 sec before start next user')
            time.sleep(30)
    except:
        print('error 95: :', traceback.format_exc())

    if worker_runner:
        worker_runner.public_moves.ps4_buttons.__del__()
        print('game pad was successfully deleted')


def check_need_work_fifa_account(fifa_account: FifaAccount, **kwargs):
    # last_sbc_worker = kwargs.get('last_sbc_worker')
    console_last_24_hour_played = kwargs.get('console_last_24_hour_played')
    console = kwargs.get('console')
    allowed_discharge_time_var = kwargs.get('allowed_discharge_time_var')
    lowest_run_hour = ConsoleBotSetting.objects.get(name='lowest_account_run_in_console_hour').int_value
    need_some_work = FifaAccount.objects.filter(
        id=fifa_account.id
    ).annotate(
        uncompleted_sbc=Value(SBCType.objects.filter(console_can_use=True, must_done=1).exclude(
            id__in=SBCProcess.objects.filter(
                sbc_number__in=SBCType.objects.filter(
                    console_can_use=True, must_done=1
                ).values_list('sbc_number', flat=True),
                worker__fifa_account__id=fifa_account.id, is_done=True
            ).distinct('sbc_type').values_list('sbc_type__id', flat=True)
        ).count()),
        uncompleted_sbc_price=Coalesce(SBCType.objects.filter(console_can_use=True, must_done=1).exclude(
            id__in=SBCProcess.objects.filter(
                sbc_number__in=SBCType.objects.filter(
                    console_can_use=True, must_done=1
                ).values_list('sbc_number', flat=True),
                worker__fifa_account__id=fifa_account.id, is_done=True
            ).distinct('sbc_type').values_list('sbc_type__id', flat=True)
        ).aggregate(Sum('sbc_actual_price')).get('sbc_actual_price__sum'), Value(0)),
        completed_sbc=Value(SBCType.objects.filter(
            console_can_use=True, must_done=1,
            id__in=SBCProcess.objects.filter(
                sbc_number__in=SBCType.objects.filter(
                    console_can_use=True, must_done=1
                ).values_list('sbc_number', flat=True),
                worker__fifa_account__id=fifa_account.id, is_done=True
            ).distinct('sbc_type').values_list('sbc_type__id', flat=True)
        ).count()),
        can_play_1=Value(console_last_24_hour_played.count() < console.allowed_play_game_day),
        can_play_2=Value(calculate_need_game(
            console_last_24_hour_played.count(), fifa_account.account_played_games,
            console_limit=fifa_account.console.allowed_play_game_day,
            account_limit_play=fifa_account.allowed_play_game,
            account_play_day=fifa_account.fifaaccountsquadgame_set.filter(
                create_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
            ).count(),
            account_limit_day=fifa_account.allowed_play_game_day
        ) > 0),
        account_24_played_games=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
            fifa_account__id=OuterRef('pk'),
            create_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
        ).values('fifa_account').annotate(
            played_count=Count('id', output_field=IntegerField())
        ).values('played_count'), output_field=IntegerField()), Value(0)),
        account_play_31_days=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
            fifa_account__id=OuterRef('pk'),
            create_time__gt=timezone.localtime() - timezone.timedelta(days=31)
        ).values('fifa_account').annotate(
            played_count_31_day=Count('id', output_field=IntegerField())
        ).values('played_count_31_day'), output_field=IntegerField()), Value(0)),
        account_all_played_games=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
            fifa_account__id=OuterRef('pk'),
            # create_time__gt=now_local_time - timezone.timedelta(hours=24)
        ).values('fifa_account').annotate(
            played_count_all=Count('id', output_field=IntegerField())
        ).values('played_count_all'), output_field=IntegerField()), Value(0)),
        pro_and_semi_pro_played_count=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
            fifa_account__id=OuterRef('pk'),
            difficulty__in=['semi_pro', 'professional'],
        ).values('fifa_account').annotate(
            difficulty_played_count_all=Count('id', output_field=IntegerField())
        ).values('difficulty_played_count_all'), output_field=IntegerField()), Value(0)),
        trade_one_2_hour=Coalesce(Subquery(ConsoleTradeOneCard.objects.filter(
            fifa_account__id=OuterRef('pk'),
            create_time__gt=timezone.localtime() - timezone.timedelta(hours=lowest_run_hour)
        ).values('fifa_account').annotate(
            trade_one_6_count=Count('id', output_field=IntegerField())
        ).values('trade_one_6_count'), output_field=IntegerField()), Value(0)),
        trade_one_unsoled_items=Coalesce(Subquery(ConsoleTradeOneCard.objects.filter(
            fifa_account__id=OuterRef('pk'),
            deleted=False,
        ).values('fifa_account').annotate(
            unsoled_items=Count('id', output_field=IntegerField())
        ).values('unsoled_items'), output_field=IntegerField()), Value(0)),
        trade_one_1_hour_history=Coalesce(Subquery(ConsoleTradeOneHistory.objects.filter(
            fifa_account__id=OuterRef('pk'),
            create_time__gt=timezone.localtime() - timezone.timedelta(hours=lowest_run_hour)
        ).values('fifa_account').annotate(
            trade_one_history=Count('id', output_field=IntegerField())
        ).values('trade_one_history'), output_field=IntegerField()), Value(0)),
        trade_one_1_hour_history_update=Coalesce(Subquery(ConsoleTradeOneHistory.objects.filter(
            fifa_account__id=OuterRef('pk'),
            update_time__gt=timezone.localtime() - timezone.timedelta(hours=lowest_run_hour)
        ).values('fifa_account').annotate(
            trade_one_history_update=Count('id', output_field=IntegerField())
        ).values('trade_one_history_update'), output_field=IntegerField()), Value(0)),
        can_play_squad=ExpressionWrapper(Q(
            (Q(account_played_games__lt=F('allowed_play_game')) | Q(squad_special_game_one=False) |
             Q(squad_special_game_two=False)) &
            Q(run_squad_battle=True) & Q(can_play_1=True) & Q(can_play_2=True) &
            Q(allowed_play_game_day__gte=F('account_24_played_games')) &
            # Q(account_play_31_days__lt=Value(88))
            (Q(account_all_played_games__lt=Value(185)) | Q(account_all_played_games__gt=Value(200))
             # Q(console__name__in=[120, 2040, 2041, 2042, 2043, 2044, 2045])
             # Q(pro_and_semi_pro_played_count__gte=Value(70))
             )
            # Q(is_running_console_trade_one=False)
        ), output_field=BooleanField()),
        can_discharge=ExpressionWrapper(Q(
            Q(run_discharge=True) &
            Q(credit__gt=ConsoleBotSetting.objects.get(name='discharge_start_coin_greater').int_value) &
            Q(credit__lt=ConsoleBotSetting.objects.get(name='discharge_start_coin_lower').int_value)
            & Value(allowed_discharge_time_var)
            # Q(is_running_console_trade_one=False)
        ), output_field=BooleanField()),
        can_sbc=ExpressionWrapper(Q(
            Q(run_sbc=True) & Q(uncompleted_sbc__gt=0) &
            # todo : for now our sbc don't need coin , if need coin uncomment bellow
            (Q(credit__gt=F('uncompleted_sbc_price')) | (Q(credit__gt=5000) & Q(completed_sbc__gt=0)))

            # Q(is_running_console_trade_one=False)
        ), output_field=BooleanField()),
        can_console_trade=ExpressionWrapper(Q(
            (Q(run_console_trade_one=True) & Q(trade_one_2_hour__lt=1) & Q(trade_one_1_hour_history__lt=1) &
             # Q(credit__gt=10000) &
             Q(is_running_console_trade_one=False)) |
            ((Q(trade_one_unsoled_items__gt=0) | Q(is_running_console_trade_one=True)) &
             Q(trade_one_1_hour_history_update__lt=1))), output_field=BooleanField()),
        need_force_relist=ExpressionWrapper(Q(
            is_running_console_trade_one=True,
            run_console_invest_trade_one=False,
            last_run_time__lt=timezone.localtime() - timezone.timedelta(hours=1)), output_field=BooleanField())
    ).filter(
        Q(stop_for_update_game=False) & Q(
            last_run_time__lt=timezone.localtime() - timezone.timedelta(hours=lowest_run_hour)) &
        (Q(can_play_squad=True) | Q(can_discharge=True) | Q(can_sbc=True) | Q(can_console_trade=True) |
         Q(need_force_relist=True))
    )

    return need_some_work


def get_console_last_24_hour_played(console):
    return FifaAccountSquadGame.objects.filter(
        fifa_account__in=console.fifaaccount_set.filter(
            Q(delete_console_reason=None) | Q(delete_console_reason='')
        ),
        create_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
    )


# bellow for test query
# fifa_account = FifaAccount.objects.get(user_name='Zlatibram50@outlook.com')
# need_works = check_need_work_fifa_account(
#         fifa_account,
#         console_last_24_hour_played=get_console_last_24_hour_played(fifa_account.console),
#         console=fifa_account.console,
#         allowed_discharge_time_var=allowed_discharge_time()
#     ).values()
# print(need_works)
# exit(1)

def start_squad_manager():
    try:
        allowed_discharge_time_var = allowed_discharge_time()
        console = Console.objects.filter(name=CONSOLE_NAME).first()
        console_last_24_hour_played = get_console_last_24_hour_played(console=console)
        fifa_account_worked_in_24_hour = SBCWorker.objects.filter(
            fifa_account__console=console,
            status_change_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
        ).distinct('fifa_account__id').values_list('fifa_account__id', flat=True)[:console.allowed_account_work_day]
        if console:
            sane_console_fifa_accounts = FifaAccount.objects.filter(
                console=console,
                # todo : delete bellow line after captcha solver fixed
                need_captcha=False,
            ).filter(
                Q(delete_console_reason=None) | Q(delete_console_reason=''),
            ).exclude(name_in_console='key').order_by('last_run_time')
            if console.is_active is False and sane_console_fifa_accounts.first():
                console_first_account = sane_console_fifa_accounts.first()
                print('console deactive , pressing left and right for keep console alive , first account : ',
                      console_first_account)
                console_first_account.sbcworker_set.last()
                threading.Thread(target=focus_on_ps,
                                 kwargs={'fifa_account': console_first_account}).start()
                # using thread because ps4 maybe has error on focus
                # focus_on_ps(console_first_account)
                time.sleep(5)
                public_moves = PublicMoves(None, console_first_account.sbcworker_set.last(), None, {},
                                           None)
                print('check for errors')
                current_state = public_moves.just_find_state()
                if not current_state:
                    new_print(console_first_account, 'can not find current state : ', current_state)
                    try:
                        public_moves.xboxs_go_to_app()
                    except:
                        new_print(console_first_account, 'exception in open xbox app : ', traceback.format_exc())
                else:
                    new_print(console_first_account, 'opening ultimate , current state : ', current_state)
                    threading.Thread(target=public_moves.focus_on_ps).start()
                    time.sleep(10)
                new_print(console_first_account,
                          'console deactive , pressing left and right for keep console alive , ',
                          public_moves.just_find_state())
                public_moves.get_screen_shot()
                public_moves.errors()
                time.sleep(5)
                print('console deactive , pressing left and right for keep console alive 2')
                public_moves.ps4_buttons.left()
                time.sleep(1)
                public_moves.ps4_buttons.right()
                time.sleep(10)
                return
            # run force relist console trade one items
            force_relist_accounts = sane_console_fifa_accounts.filter(
                is_running_console_trade_one=True,
                run_console_invest_trade_one=False,
                last_run_time__lt=timezone.localtime() - timezone.timedelta(hours=1),
                stop_for_update_game=False,
            ).order_by('last_run_time')

            for relist_account in force_relist_accounts:
                need_work_3 = check_need_work_fifa_account(
                    relist_account, console_last_24_hour_played=console_last_24_hour_played,
                    console=console, allowed_discharge_time_var=allowed_discharge_time_var)
                need_work_3_account = need_work_3.first()
                if need_work_3_account and need_work_3_account.need_force_relist:
                    force_relist_sbc_worker = SBCWorker.objects.filter(
                        is_done=False, has_error=False,
                        running_platform='console',
                        fifa_account=relist_account,
                    ).last()
                    if force_relist_sbc_worker:
                        print('existed sbc worker found. worker id = ', force_relist_sbc_worker.id,
                              '\n account email = ', force_relist_sbc_worker.fifa_account.user_name,
                              '\n need work = force relist ')
                        new_print(force_relist_sbc_worker.fifa_account,
                                  'existed sbc worker found. worker id = ', force_relist_sbc_worker.id,
                                  '\n need work = force relist ')
                    else:
                        force_relist_sbc_worker = SBCWorker.objects.create(
                            is_done=False, has_error=False,
                            running_platform='console',
                            fifa_account=relist_account,
                        )
                        new_print(force_relist_sbc_worker.fifa_account,
                                  'new worker , worker id = ', force_relist_sbc_worker.id,
                                  '\n need work = force relist ', )
                    run_worker(worker_id=force_relist_sbc_worker.id)
                    return

            # if force_relist_accounts:
            #     force_relist_sbc_worker = SBCWorker.objects.filter(
            #         is_done=False, has_error=False,
            #         running_platform='console',
            #         fifa_account__in=force_relist_accounts,
            #     ).last()
            #     if not force_relist_sbc_worker:
            #         force_relist_sbc_worker, created = SBCWorker.objects.get_or_create(
            #             is_done=False, has_error=False,
            #             running_platform='console',
            #             fifa_account=force_relist_accounts.last(),
            #         )
            #     print('existed sbc worker found. worker id = ', force_relist_sbc_worker.id,
            #           '\n account email = ', force_relist_sbc_worker.fifa_account.user_name,
            #           '\n need work = force relist ')
            #     new_print(force_relist_sbc_worker.fifa_account,
            #               'existed sbc worker found. worker id = ', force_relist_sbc_worker.id,
            #               '\n need work = force relist ')
            #     run_worker(worker_id=force_relist_sbc_worker.id)
            #     return
            # run force discharge
            # force_discharge_fifa_accounts = FifaAccount.objects.filter(
            #     console=console
            # ).filter(
            #     Q(delete_console_reason=None) | Q(delete_console_reason=''),
            #     run_force_discharge=True
            # ).exclude(name_in_console='key').order_by('last_run_time')
            force_discharge_fifa_accounts = sane_console_fifa_accounts.filter(
                run_force_discharge=True,
                stop_for_update_game=False,
            ).order_by('last_run_time')
            if fifa_account_worked_in_24_hour.count() >= console.allowed_account_work_day:
                force_discharge_fifa_accounts = force_discharge_fifa_accounts.filter(
                    id__in=fifa_account_worked_in_24_hour
                )
            existed_force_discharge_worker = SBCWorker.objects.filter(
                is_done=False, has_error=False,
                running_platform='console',
                fifa_account__in=force_discharge_fifa_accounts,
            ).last()
            if existed_force_discharge_worker:
                print('existed sbc worker found. worker id = ', existed_force_discharge_worker.id,
                      '\n account email = ', existed_force_discharge_worker.fifa_account.user_name,
                      '\n need work = force discharge ')
                new_print(existed_force_discharge_worker.fifa_account,
                          'existed sbc worker found. worker id = ', existed_force_discharge_worker.id,
                          '\n need work = force discharge ')
                set_main_log(existed_force_discharge_worker, 'preparing for discharge...')
                set_sub_log(existed_force_discharge_worker, 'preparing for discharge with existed sbc worker...')
                run_worker(worker_id=existed_force_discharge_worker.id)
                return
            elif force_discharge_fifa_accounts:
                last_force_discharge_worker, created = SBCWorker.objects.get_or_create(
                    is_done=False, has_error=False,
                    running_platform='console',
                    fifa_account=force_discharge_fifa_accounts.last(),
                )
                print('new worker id = ', last_force_discharge_worker.id,
                      '\n account email = ', last_force_discharge_worker.fifa_account.user_name,
                      '\n need work = force discharge ')
                new_print(last_force_discharge_worker.fifa_account,
                          'new worker id = ', last_force_discharge_worker.id,
                          '\n need work = force discharge 2')
                set_main_log(last_force_discharge_worker, 'preparing for discharge ...')
                set_sub_log(last_force_discharge_worker, 'preparing for discharge with new sbc worker...')
                run_worker(worker_id=last_force_discharge_worker.id)
                return
            allowed_discharge_time_var = allowed_discharge_time()

            # run other works
            # fifa_accounts = FifaAccount.objects.filter(
            #     Q(delete_console_reason=None) | Q(delete_console_reason=''),
            #     console=console
            # ).exclude(name_in_console='key').order_by('last_run_time')
            fifa_accounts = sane_console_fifa_accounts.filter(
                stop_for_update_game=False,
            ).order_by('last_run_time')
            if fifa_account_worked_in_24_hour.count() >= console.allowed_account_work_day:
                fifa_accounts = fifa_accounts.filter(
                    id__in=fifa_account_worked_in_24_hour
                )

            for fifa_account_1 in fifa_accounts:
                existed_sbc_worker = SBCWorker.objects.filter(
                    is_done=False, has_error=False,
                    running_platform='console',
                    fifa_account=fifa_account_1,
                ).last()
                if existed_sbc_worker:
                    need_work = check_need_work_fifa_account(
                        fifa_account_1,
                        # last_sbc_worker=existed_sbc_worker,
                        console_last_24_hour_played=console_last_24_hour_played,
                        console=console,
                        allowed_discharge_time_var=allowed_discharge_time_var)

                    if need_work:
                        print('existed sbc worker found. worker id = ', existed_sbc_worker.id,
                              '\n account email = ', fifa_account_1.user_name,
                              '\n need work = ', need_work)
                        first_work = need_work.first().__dict__
                        new_print(fifa_account_1,
                                  'existed sbc worker found. worker id = ', existed_sbc_worker.id,
                                  '\n need work = ', {k: v for k, v in first_work.items()
                                                      if k not in ['_state', 'cookies', 'access_token']}
                                  )
                        set_main_log(existed_sbc_worker, 'preparing for work...')
                        set_sub_log(existed_sbc_worker, 'preparing for work with existed sbc worker...')
                        run_worker(worker_id=existed_sbc_worker.id)
                        return
            for fifa_account_2 in fifa_accounts:
                last_sbc_worker = SBCWorker.objects.filter(
                    running_platform='console',
                    fifa_account=fifa_account_2,
                    last_run_time__gt=timezone.localtime() - timezone.timedelta(days=2)
                ).order_by('status_change_time').last()
                created = False
                # print(f'fifa account : {fifa_account_2} \n sbc worker in two days : {last_sbc_worker}')
                if not last_sbc_worker:
                    last_sbc_worker, created = SBCWorker.objects.get_or_create(
                        is_done=False, has_error=False,
                        running_platform='console',
                        fifa_account=fifa_account_2,
                    )
                need_work_2 = check_need_work_fifa_account(
                    fifa_account_2,
                    # last_sbc_worker=last_sbc_worker,
                    console_last_24_hour_played=console_last_24_hour_played,
                    console=console,
                    allowed_discharge_time_var=allowed_discharge_time_var)

                if need_work_2.first():
                    if created is False:
                        last_sbc_worker, created = SBCWorker.objects.get_or_create(
                            is_done=False, has_error=False,
                            running_platform='console',
                            fifa_account=fifa_account_2,
                        )
                    print('start squad battle account email = ', fifa_account_2.user_name)
                    first_work = need_work_2.first().__dict__
                    new_print(fifa_account_2, 'start squad battle , need work 2 ',
                              '\n need work = ',
                              {k: v for k, v in first_work.items()
                               if k not in ['_state', 'cookies', 'access_token']})
                    # sbc_worker, created = SBCWorker.objects.get_or_create(
                    #     is_done=False, has_error=False,
                    #     running_platform='console',
                    #     fifa_account=fifa_account_2,
                    # )
                    set_main_log(last_sbc_worker, 'preparing for work...')
                    set_sub_log(last_sbc_worker, 'preparing for work with new sbc worker...')
                    run_worker(worker_id=last_sbc_worker.id)
                    print('run worker done')
                    return

            print('all accounts is done')
            SBCWorker.objects.filter(
                is_done=False, has_error=False,
                running_platform='console',
                fifa_account__in=console.fifaaccount_set.filter(
                    Q(delete_console_reason=None) | Q(delete_console_reason='')
                ),
            ).update(is_done=True)
            print('all workers make done')
            console_first_account = console.fifaaccount_set.first()
            first_play_game = FifaAccountSquadGame.objects.filter(
                fifa_account__in=console.fifaaccount_set.filter(
                    Q(delete_console_reason=None) | Q(delete_console_reason='')
                ),
                create_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
            ).first()
            if first_play_game:
                first_play_time = first_play_game.create_time
            else:
                first_play_time = timezone.localtime()
            need_rest_time = (first_play_time + timezone.timedelta(hours=24)) - timezone.localtime()
            console.refresh_from_db()
            if console_first_account:
                print('log will in account : ', console_first_account)
                if (console.turn_off_after_work and
                        console_last_24_hour_played.count() >= console.allowed_play_game_day and
                        need_rest_time.seconds > 60 * 60 * 3):
                    console_first_account.sbcworker_set.last()
                    print('i am complete all games and need turn off , log will in account : ', console_first_account)
                    threading.Thread(target=focus_on_ps, kwargs={'fifa_account': console_first_account}).start()
                    # using thread because ps4 maybe has error on focus
                    # focus_on_ps(console_first_account)
                    time.sleep(5)
                    public_moves = PublicMoves(None, console_first_account.sbcworker_set.last(), None, {}, None)
                    print('check for errors')
                    new_print(console_first_account, 'i am complete all games and need turn off')
                    public_moves.get_screen_shot()
                    public_moves.errors()
                    time.sleep(5)
                    print('shutting done console')
                    public_moves.ps4_buttons.ps(press_time=1)
                    time.sleep(1)
                    public_moves.ps4_buttons.up()
                    time.sleep(1)
                    public_moves.ps4_buttons.up()
                    time.sleep(1)
                    public_moves.ps4_buttons.cross()
                    time.sleep(10)
                    console.refresh_from_db()
                    console.pc_is_on = False
                    console.save()
                    time.sleep(1)
                    # turn of pc
                    os.system("shutdown /s /t 1")
                    return
                if console.restart_console_for_update:
                    console.restart_console_for_update = False
                    console.save()
                    threading.Thread(target=focus_on_ps, kwargs={'fifa_account': console_first_account}).start()
                    time.sleep(5)
                    public_moves = PublicMoves(None, console_first_account.sbcworker_set.last(), None, {}, None)
                    print('check for errors')
                    new_print(console_first_account, 'need to restart console for update')
                    public_moves.get_screen_shot()
                    public_moves.errors()
                    time.sleep(5)
                    public_moves.ps4_buttons.ps(press_time=1)
                    time.sleep(2)
                    public_moves.ps4_buttons.right()
                    time.sleep(1)
                    public_moves.ps4_buttons.right()
                    time.sleep(1)
                    public_moves.ps4_buttons.right()
                    time.sleep(1)
                    public_moves.ps4_buttons.cross()
                    time.sleep(2)
                    public_moves.ps4_buttons.left()
                    time.sleep(1)
                    public_moves.ps4_buttons.cross()
                    time.sleep(10)
                    return
                if console.restart_pc_for_update:
                    console.restart_pc_for_update = False
                    console.save()
                    new_print(console_first_account, 'console restart_pc_for_update , will restart pc')
                    os.system("shutdown /r /t 1")
                    return
                console_first_account.sbcworker_set.last()
                print('i am resting , log will in account : ', console_first_account,
                      ' rest seconds : ', need_rest_time.seconds)
                threading.Thread(target=focus_on_ps, kwargs={'fifa_account': console_first_account}).start()
                # using thread because ps4 maybe has error on focus
                # focus_on_ps(console_first_account)
                time.sleep(5)
                public_moves = PublicMoves(None, console_first_account.sbcworker_set.last(), None, {}, None)
                print('check for errors')
                new_print(console_first_account, 'pressing left and right for keep console alive , ',
                          public_moves.just_find_state())
                public_moves.get_screen_shot()
                public_moves.errors()
                time.sleep(5)
                print('pressing left and right for keep console alive')
                public_moves.ps4_buttons.left()
                time.sleep(1)
                public_moves.ps4_buttons.right()
                time.sleep(10)
                return
        else:
            print('console not found in database')
            return
            # except InterfaceError:
    #     print('exception happend 87')
    #     close_old_connections()
    #     print('connection error. retry and sleep 100 second')
    #     time.sleep(100)
    except:
        print('exception happened 88')
        traceback.print_exc()
    close_old_connections()
    return


def dynamic_allowed_play_game():
    try:
        console = Console.objects.filter(name=CONSOLE_NAME).first()
        console_accounts = FifaAccount.objects.filter(console=console)
        if console_accounts.count() == 0:
            print('no account found , console : ', console)
            time.sleep(10)
            return
        if console_accounts.count() == 10:
            console_accounts.update(allowed_play_game=25)
        else:
            can_played = int(245 / console_accounts.count())
            print('console : ', console, 'account counts : ', console_accounts.count(), ' can played : ', can_played)
            if can_played > 40:
                console_accounts.update(allowed_play_game=40)
            else:
                console_accounts.update(allowed_play_game=can_played)

    except:
        print('exception happened 89')
        traceback.print_exc()
    close_old_connections()
    return


def dynamic_force_discharge():
    try:
        console = Console.objects.filter(name=CONSOLE_NAME).first()
        console_accounts = FifaAccount.objects.filter(console=console)
        sum_credit = console_accounts.aggregate(sum_credit=Sum('credit')).get('sum_credit') or 0
        if sum_credit > 400 * 1000 and allowed_discharge_time() and console_accounts.first().run_discharge is True:
            print(f'sum credit {sum_credit} so run force discharge for console accounts')
            console_accounts.update(run_force_discharge=True)
        elif allowed_discharge_time() and console_accounts.first().run_discharge is True:
            for acc in console_accounts:
                if acc.credit > 100 * 1000:
                    print(f'account {acc} has {acc.credit} need force discharge')
                    acc.run_force_discharge = True
                    acc.save()
    except:
        print('exception happened 89')
        traceback.print_exc()
    close_old_connections()
    return


def check_update_console_games():
    try:
        console = Console.objects.get(name=CONSOLE_NAME)
        last_account = console.fifaaccount_set.last()
        las_sbc_worker = SBCWorker.objects.filter(fifa_account=last_account).last()
        if console.need_games_update:
            console.need_games_update = False
            console.save()
            squad_battle_runner = SquadBattleRunner(
                las_sbc_worker.id, last_account.id,
                last_account.user_name, last_account.password,
                last_account.platform, False)
            squad_battle_runner.public_moves.xbox_check_for_update()
    except:
        print('exception happened 90')
        traceback.print_exc()
    close_old_connections()
    return


def dynamic_console_allowed_play_day():
    try:
        console = Console.objects.get(name=CONSOLE_NAME)
        console.allowed_play_game_day = console.fifaaccount_set.filter(
            Q(delete_console_reason=None) | Q(delete_console_reason=''),
        ).annotate(
            account_play_31_days=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
                fifa_account__id=OuterRef('pk'),
                create_time__gt=timezone.localtime() - timezone.timedelta(days=31)
            ).values('fifa_account').annotate(
                played_count_31_day=Count('id', output_field=IntegerField())
            ).values('played_count_31_day'), output_field=IntegerField()), Value(0)),
            account_all_played_games=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
                fifa_account__id=OuterRef('pk'),
                # create_time__gt=now_local_time - timezone.timedelta(hours=24)
            ).values('fifa_account').annotate(
                played_count_all=Count('id', output_field=IntegerField())
            ).values('played_count_all'), output_field=IntegerField()), Value(0)),
            pro_and_semi_pro_played_count=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
                fifa_account__id=OuterRef('pk'),
                difficulty__in=['semi_pro', 'professional'],
            ).values('fifa_account').annotate(
                difficulty_played_count_all=Count('id', output_field=IntegerField())
            ).values('difficulty_played_count_all'), output_field=IntegerField()), Value(0)),
        ).filter(
            # account_play_31_days__lt=Value(88)
            (Q(account_all_played_games__lt=Value(185)) | Q(account_all_played_games__gt=Value(200))
             # Q(console__name__in=[120, 2040, 2041, 2042, 2043, 2044, 2045])
             # Q(pro_and_semi_pro_played_count__gte=Value(70))
             )
        ).aggregate(
            sum_account_day=Sum('allowed_play_game_day')).get('sum_account_day') or 0
        console.save()
    except:
        print('exception happened 91')
        traceback.print_exc()
    try:
        console = Console.objects.get(name=CONSOLE_NAME)
        console.pc_is_on = True
        console.save()
    except:
        print('exception happened 92')
        traceback.print_exc()
    close_old_connections()
    return


def check_xbox_turn_on():
    try:
        if Console.objects.get(name=CONSOLE_NAME).fifaaccount_set.first().platform == 'ps':
            print('this is ps')
            return
        if process_exists('XboxPcApp.exe'):
            print('xbox app already is open')
            return
        os.system("TASKKILL /F /IM xboxpcapp.exe")
        keyboard.press_and_release('win')
        time.sleep(1)
        keyboard.write('Xbox Console Companion')
        time.sleep(10)
        keyboard.press_and_release('enter')
        time.sleep(60)
        get_screen_shot()
        if has_image(
                os.path.join(BASE_DIR, f'utils/xbox_companion/connecting_menu_icon.png'),
                'screen_shot_tmp.jpg'
        ):
            connection_icon_pos = get_image_position('utils/xbox_companion/connecting_menu_icon.png',
                                                     'screen_shot_tmp.jpg')
        elif has_image(
                os.path.join(BASE_DIR, f'utils/xbox_companion/connecting_menu_icon2.png'),
                'screen_shot_tmp.jpg'):
            connection_icon_pos = get_image_position('utils/xbox_companion/connecting_menu_icon2.png',
                                                     'screen_shot_tmp.jpg')
        else:
            raise Exception('Can not find connection icon')
        mouse.move(connection_icon_pos['top_left'][0], connection_icon_pos['top_left'][1])
        mouse.click('left')
        time.sleep(60)
        get_screen_shot()
        if has_image(
                os.path.join(BASE_DIR, f'utils/xbox_companion/turn_on.png'),
                'screen_shot_tmp.jpg'):
            turn_on_icon_pos = get_image_position('utils/xbox_companion/turn_on.png',
                                                  'screen_shot_tmp.jpg')
            mouse.move(turn_on_icon_pos['top_left'][0], turn_on_icon_pos['top_left'][1])
            mouse.click('left')
            print('ok i found turn on')
            time.sleep(90)
        else:
            raise Exception('Can not find turn on icon')
    except:
        print('exception happened 93')
        traceback.print_exc()
        os.system("TASKKILL /F /IM xboxpcapp.exe")


# check_xbox_turn_on()
dynamic_console_allowed_play_day()
start_pc_bots_result = start_pc_bots()
if start_pc_bots_result != 'need update bot':
    start_squad_manager()
# dynamic_allowed_play_game()
# dynamic_force_discharge()
check_update_console_games()

try:
    print('try to close active program')
    os.system('TASKKILL /F /IM chrome.exe /FI "USERNAME eq %username%"')
    os.system('TASKKILL /F /IM python.exe /FI "USERNAME eq %username%"')
    # time.sleep(1)
    os.system('TASKKILL /F /IM run_console_manager.exe /FI "USERNAME eq %username%"')
    os.system('TASKKILL /F /IM run_console_manager.exe /FI "USERNAME eq %username%"')
    os.system('TASKKILL /F /IM run_console_manager.exe /FI "USERNAME eq %username%"')
    os.system('TASKKILL /F /IM console_squad_manager_2.exe /FI "USERNAME eq %username%"')
    os.system('TASKKILL /F /IM console_squad_manager_2.exe /FI "USERNAME eq %username%"')
    os.system('TASKKILL /F /IM console_squad_manager_2.exe /FI "USERNAME eq %username%"')
except:
    print('no active python program found ...')
# python -m PyInstaller --runtime-tmpdir "./s_temp" --add-data "ViGEmClient.dll;." ./console_squad_manager_2.py