import datetime
import json
import os
import re
import socket

import jdatetime
import ntplib
import openpyxl
import pandas as pd
import six
from celery.result import AsyncResult
from dateutil.tz import gettz
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import MultipleObjectsReturned
from django.db.models import Sum, Value, Case, When, Q, F, Subquery, OuterRef, Count, IntegerField, FloatField, QuerySet
from django.db.models.functions import Coalesce, Cast
from django.forms import model_to_dict
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, HttpResponseNotAllowed
from django.shortcuts import redirect, render
from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.timezone import make_aware
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import FormView, TemplateView
from openpyxl import Workbook
from unidecode import unidecode

from accounts.models import FifaAccount, MuleAccounts, PC, Console, CloseWebAppSnipes, FifaAccountSearch, \
    ConsoleLastStatus, CloseWebAppTransfers
from futplus.settings import BASE_DIR
from sbc.public_methods import convert_club_players_to_solvation_format
from sbc.solvation_maker.optimize import SolvationCore
from squad_battle.models import FifaAccountSquadGame
from customrolepermissions.mixins import RequiredPermissionViewMixin
from customrolepermissions.permissions import has_permission_exactly
from futplus.celery_conf import app
from sbc.cach_data import get_console_worker_logs
from sbc.consts import SBC_TARGET_NATIONS, SBC_TARGET_CLUBS, SBC_TARGET_LEAGUES
from sbc.filters import InvestorPageFilter, ConsoleWorkersLogsFilter, NationsFilter, ConsoleWorkersLogs2Filter
from sbc.forms import StartSingleSBCForm, SbcWorkerUpdateForm
from sbc.models import SBCWorker, SBCOrder, SBCWorkerDetailsLog, AccountCheckHealthyWorker, AccountCheckHealthyOrder, \
    SBCType, SBCProcess, SBCSolvationModel
from sbc.tables import SbcOrdersTable, ActiveSBCTasksTable, CeleryActiveTasksTable, \
    PCListTable, CheckHealthyListTable, TemporarySbcWorkersLogs, ConsoleWorkersLogsTable, \
    InvestorConsolesListTable, NationsListTable, SBCProcessDoneListTable, PacksListTable, SbcWorkersLogsListTable, \
    SbcWorkerReportsListTable, SbcWorkersLastsListTable
# Create your views here.
from sniper.models import DischargeMode2
from trade.models import ConsoleInvestTradeItemsCountLog
from utils import number_convertor_to_milion
from utils.views import GenericListView, GenericFilterListView, GenericUpdateView2


class StartSingleSBC(LoginRequiredMixin, FormView):
    template_name = 'generic_views/form_view.html'
    form_class = StartSingleSBCForm
    success_url = reverse_lazy('start_sbs_single')

    def form_valid(self, form):
        fifa_account = form.cleaned_data['fifa_account']
        exist_sbc = check_last_sbc_workers(fifa_account)
        sbc_order = SBCOrder.objects.create(
            creator=self.request.user,
            file_name='manual_%s' % timezone.localtime().strftime('%Y-%m-%d_%H-%M-%S'),
            status=1)
        if not exist_sbc:
            SBCWorker.objects.create(fifa_account=fifa_account, sbc_order=sbc_order)
        # active_bot.delay(sbc_worker.id)
        # test_task.delay()

        return super(StartSingleSBC, self).form_valid(form)


class CeleryActiveTasks(GenericListView):
    model = FifaAccount
    table_class = CeleryActiveTasksTable

    def get_table_data(self):
        object_list = []
        all_tasks = app.control.inspect()
        active_tasks = all_tasks.active()
        if active_tasks:
            active_tasks_id = [{'id': task['id']} for task in six.next(six.itervalues(active_tasks))]
            object_list = active_tasks_id
        return object_list


@login_required
def force_stop_celery_task(request, task_id):
    AsyncResult(str(task_id)).revoke(terminate=True, signal='SIGKILL')
    return redirect(reverse_lazy('celery_active_tasks'))


class SBCAddFile(LoginRequiredMixin, TemplateView):
    template_name = 'sbc/add_sbc_file.html'
    page_header = 'Add SBC File'

    def get_extra_buttons(self):
        buttons = []
        range_number_min = int(self.request.GET.get('range_number_min', 0))
        range_number_max = int(self.request.GET.get('range_number_max', 0))
        range_number = ''
        if range_number_max and range_number_max and range_number_min < range_number_max:
            range_number = f'&range_number_min={range_number_min}&range_number_max={range_number_max}'
        if has_permission_exactly(self.request.user, 'add_auto_sbc'):
            # buttons.append({
            #     'url': f'{reverse_lazy("action-console")}?action=discharge_all&state=active' + range_number,
            #     'text': f'Active Discharge({range_count})',
            #     'color': 'btn-success'
            #
            # })
            buttons.append({
                'url': f'{reverse_lazy("sbc-add-file")}?action=active_xbox360',
                'text': 'Xbox360 Order',
                'color': 'btn-info'

            })
            buttons.append({
                'url': f'{reverse_lazy("sbc-add-file")}?action=active_xboxs',
                'text': 'Xboxs Order',
                'color': 'btn-success'

            })
            buttons.append({
                'url': f'{reverse_lazy("sbc-add-file")}?action=active_all',
                'text': 'All Xbox Order',
                'color': 'btn-info'

            })
            buttons.append({
                'url': f'{reverse_lazy("sbc-add-file")}?action=active_open_web',
                'text': 'Open Web Order',
                'color': 'btn-info'

            })
        return buttons

    def get(self, request, *args, **kwargs):
        context = super().get(request, *args, **kwargs)
        action = request.GET.get('action')
        from .tasks import create_automated_360_sbc, create_automated_series_sbc
        if action == 'active_xbox360':
            create_automated_360_sbc()
            # sbc_workers = []
            # sbc_order = SBCOrder.objects.create(creator=request.user, file_name='automated_xbox360_sbc.xlsx', status=1)
            # for fifa_account in FifaAccount.objects.filter(
            #         Q(delete_console_reason=None) | Q(delete_console_reason=''),
            #         console__is_active=True, platform='xbox360'
            # ):
            #     sbc_workers.append(SBCWorker(
            #         fifa_account=fifa_account, sbc_order=sbc_order,
            #         last_run_time=timezone.localtime() - datetime.timedelta(hours=4),
            #         status_change_time=timezone.localtime() - datetime.timedelta(hours=1),
            #         manual_loyal=False, running_platform='console_web_pc',
            #         order_active_squad=False,
            #         order_active_squad_formation=False,
            #     ))
            # SBCWorker.objects.bulk_create(sbc_workers)
            messages.success(request, "Xbox 360 SBC File Added")
            return redirect(reverse_lazy('sbc-add-file'))
        elif action == 'active_xboxs':
            create_automated_series_sbc()
            # sbc_workers = []
            # sbc_order = SBCOrder.objects.create(creator=request.user, file_name='automated_xboxs_sbc.xlsx', status=1)
            # for fifa_account in FifaAccount.objects.filter(
            #         Q(delete_console_reason=None) | Q(delete_console_reason=''),
            #         console__is_active=True, platform='xboxs'
            # ):
            #     sbc_workers.append(SBCWorker(
            #         fifa_account=fifa_account, sbc_order=sbc_order,
            #         last_run_time=timezone.localtime() - datetime.timedelta(hours=4),
            #         status_change_time=timezone.localtime() - datetime.timedelta(hours=1),
            #         manual_loyal=False, running_platform='console_web_pc',
            #         order_active_squad=False,
            #         order_active_squad_formation=False,
            #     ))
            # SBCWorker.objects.bulk_create(sbc_workers)
            messages.success(request, "Xbox Series SBC File Added")
            return redirect(reverse_lazy('sbc-add-file'))
        elif action == 'active_all':
            create_automated_360_sbc()
            create_automated_series_sbc()
            # sbc_workers = []
            # sbc_order = SBCOrder.objects.create(creator=request.user, file_name='automated_all_xbox_sbc.xlsx', status=1)
            # for fifa_account in FifaAccount.objects.filter(
            #         Q(delete_console_reason=None) | Q(delete_console_reason=''),
            #         Q(platform='xboxs') | Q(platform='xbox360'),
            #         console__is_active=True,
            # ):
            #     sbc_workers.append(SBCWorker(
            #         fifa_account=fifa_account, sbc_order=sbc_order,
            #         last_run_time=timezone.localtime() - datetime.timedelta(hours=4),
            #         status_change_time=timezone.localtime() - datetime.timedelta(hours=1),
            #         manual_loyal=False, running_platform='console_web_pc',
            #         order_active_squad=False,
            #         order_active_squad_formation=False,
            #     ))
            # SBCWorker.objects.bulk_create(sbc_workers)
            messages.success(request, "All Xbox SBC File Added")
            return redirect(reverse_lazy('sbc-add-file'))
        elif action == 'active_open_web':
            sbc_workers = []
            sbc_order = SBCOrder.objects.create(creator=request.user, file_name='automated_open_web_sbc.xlsx', status=1)
            for fifa_account in FifaAccount.objects.filter(
                    Q(delete_console_reason='opened_web'),
                    Q(platform='xboxs') | Q(platform='xbox360'),
                    console__is_active=True,
            ):
                sbc_workers.append(SBCWorker(
                    fifa_account=fifa_account, sbc_order=sbc_order,
                    last_run_time=timezone.localtime() - datetime.timedelta(hours=4),
                    status_change_time=timezone.localtime() - datetime.timedelta(hours=1),
                    manual_loyal=False, running_platform='web',
                    order_active_squad=False,
                    order_active_squad_formation=False,
                ))
            SBCWorker.objects.bulk_create(sbc_workers)
            sbc_order.workers_count = len(sbc_workers)
            sbc_order.save(update_fields=['workers_count'])
            messages.success(request, "Open Web SBC File Added")
            return redirect(reverse_lazy('sbc-add-file'))

        return context
        # return render(request, 'sbc/add_sbc_file.html',
        #               {
        #                'columns': ['Email', 'Password', 'Platform', 'App Code', 'Backup Code', 'Manual Loyal',
        #                            'Running Platform', 'Order Active Squad', 'Squad Formation']
        #                })

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['columns'] = ['Email', 'Password', 'Platform', 'App Code', 'Backup Code', 'Manual Loyal',
                              'Running Platform', 'Order Active Squad', 'Squad Formation']
        return context

    def post(self, request, *args, **kwargs):
        sbc_file = request.FILES.get('file')
        sbc_order = SBCOrder.objects.create(creator=request.user, file_name=sbc_file.name, status=1)
        wb_obj = openpyxl.load_workbook(sbc_file)
        sheet_obj = wb_obj.active
        max_row = sheet_obj.max_row
        sbc_workers = []
        user_name_list = [sheet_obj.cell(row=nn, column=1).value for nn in range(2, max_row + 1)]
        fifa_account_dict = {ii.user_name: ii for ii in FifaAccount.objects.filter(user_name__in=user_name_list)}
        for i in range(2, max_row + 1):
            ea_email = sheet_obj.cell(row=i, column=1).value
            exist_fifa_acc = fifa_account_dict.get(str(ea_email))
            if not exist_fifa_acc:
                continue
            # exist_fifa_acc = FifaAccount.objects.filter(user_name=ea_email).last()
            # last_backup = None
            # if exist_fifa_acc:
            #     # todo : uncomment
            #     # last_backup = exist_fifa_acc.account_backup_code.last()
            #     ea_pass = exist_fifa_acc.password
            #     platform = exist_fifa_acc.platform
            #     # todo : uncomment
            #     # app_code = last_backup.app_code
            #     # backup_code = last_backup.app_code
            # else:
            #     # print('ea email = ', ea_email)
            #     ea_pass = sheet_obj.cell(row=i, column=2).value
            #     platform = sheet_obj.cell(row=i, column=3).value
            #     app_code = sheet_obj.cell(row=i, column=4).value
            #     backup_code = sheet_obj.cell(row=i, column=5).value
            # try:
            #     manual_loyal = sheet_obj.cell(row=i, column=6).value or False
            # except:
            #     manual_loyal = False
            manual_loyal = False
            running_platform = sheet_obj.cell(row=i, column=7).value
            if not running_platform:
                running_platform = 'web'
            try:
                order_active_squad = int(sheet_obj.cell(row=i, column=8).value)
            except:
                order_active_squad = 0
            try:
                order_active_squad_formation = sheet_obj.cell(row=i, column=9).value
            except:
                order_active_squad_formation = None

            if ea_email:
                fifa_account = fifa_account_dict[ea_email]
                # if not exist_fifa_acc:
                #     fifa_account, created = FifaAccount.objects.get_or_create(
                #         user_name=ea_email
                #     )
                # else:
                #     fifa_account = exist_fifa_acc
                #     created = False
                # if fifa_account.platform in ['', None]:
                #     fifa_account.platform = platform
                #     fifa_account.save()
                # if created:
                #     fifa_account.creator = request.user
                #     fifa_account.password = ea_pass
                #     fifa_account.save()
                # todo : uncomment
                # if not last_backup:
                #     account_backup, created_2 = FifaAccountBackupCode.objects.get_or_create(fifa_account=fifa_account)
                #     if created_2:
                #         account_backup.app_code = app_code
                #         account_backup.backup_code = backup_code
                #         account_backup.save()

                # exist_sbc = False
                if running_platform in ['web', 'mule_web_sell_items']:
                    SBCWorker.objects.filter(
                        fifa_account=fifa_account, is_done=False, has_error=False,
                        running_platform=['web', 'mule_web_sell_items']
                    ).update(has_error=True, error_description='new order replaced', must_done=True)
                    # exist_sbc = check_last_sbc_workers(fifa_account)
                # if not exist_sbc:
                sbc_workers.append(SBCWorker(
                    fifa_account=fifa_account, sbc_order=sbc_order,
                    last_run_time=timezone.localtime() - datetime.timedelta(hours=4),
                    status_change_time=timezone.localtime() - datetime.timedelta(hours=1),
                    manual_loyal=manual_loyal, running_platform=running_platform,
                    order_active_squad=bool(order_active_squad),
                    order_active_squad_formation=order_active_squad_formation,
                ))
        SBCWorker.objects.bulk_create(sbc_workers)
        sbc_order.workers_count = len(sbc_workers)
        sbc_order.save(update_fields=['workers_count'])

        messages.success(request, "SBC File added")
        return redirect(reverse_lazy('sbc-add-file'))


def check_last_sbc_workers(fifa_account):
    last_sbc_workers = SBCWorker.objects.filter(fifa_account=fifa_account, is_done=False, has_error=False,
                                                running_platform='web').first()
    # for last_sbc_worker in last_sbc_workers:
    #     last_sbc_worker.has_error = True
    #     last_sbc_worker.error_description = 'exist in a new file'
    #     last_sbc_worker.save()
    #     data = {'terminate': True,
    #             'signal': 'SIGKILL'}
    #     link = '/api/task/revoke/{}?terminate=true'.format(last_sbc_worker.task_id)
    #     api_root = FLOWER_ADDRESS
    #     requests.post(api_root + link, data=data)
    return last_sbc_workers


class SbcOrdersListView(RequiredPermissionViewMixin, GenericListView):
    required_permission__ = 'sbc_workers__read'
    model = SBCOrder
    table_class = SbcOrdersTable

    def get_queryset(self) -> QuerySet:
        return super().get_queryset().annotate(
            sum_accounts=Coalesce(Subquery(SBCWorker.objects.filter(
                sbc_order__id=OuterRef('pk'),
            ).values('sbc_order_id').annotate(
                count_all=Count('id', output_field=IntegerField())
            ).values('count_all')[:1], output_field=IntegerField()), Value(0)),
            sum_fail=Coalesce(Subquery(SBCWorker.objects.filter(
                sbc_order__id=OuterRef('pk'),
                has_error=True,
            ).values('sbc_order_id').annotate(
                count_all=Count('id', output_field=IntegerField())
            ).values('count_all')[:1], output_field=IntegerField()), Value(0)),
            sum_success=Coalesce(Subquery(SBCWorker.objects.filter(
                sbc_order__id=OuterRef('pk'),
                is_done=True,
            ).values('sbc_order_id').annotate(
                count_all=Count('id', output_field=IntegerField())
            ).values('count_all')[:1], output_field=IntegerField()), Value(0)),
            # sum_current_credit=Coalesce(Subquery(SBCWorker.objects.filter(
            #     sbc_order__id=OuterRef('pk'),
            #     is_done=True,
            # ).values('sbc_order_id').annotate(
            #     count_all=Sum('fifa_account__credit', output_field=IntegerField())
            # ).values('count_all')[:1], output_field=IntegerField()), Value(0)),
        )

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)


class PCListView(GenericListView):
    model = PC
    table_class = PCListTable
    export_key = 'pc_list'

    def get_queryset(self):
        return super().get_queryset()


class NationsListView(GenericFilterListView):
    filterset_class = NationsFilter
    table_class = NationsListTable
    export_key = 'nations_list'
    page_header = 'Nations'

    def get_table_data(self):
        id_filter = self.request.GET.get('id_filter', None)
        name_filter = self.request.GET.get('name_filter', None)
        table_data = [{'id': i[0], 'name': i[1]} for i in SBC_TARGET_NATIONS]
        if id_filter:
            int_id_filter = int(id_filter)
            table_data = [i for i in table_data if i['id'] == int_id_filter]
        if name_filter:
            table_data = [i for i in table_data if name_filter.lower() in i['name'].lower()]
        return table_data


class LeaguesListView(GenericFilterListView):
    filterset_class = NationsFilter
    table_class = NationsListTable
    export_key = 'leagues_list'
    page_header = 'Leagues'

    def get_table_data(self):
        id_filter = self.request.GET.get('id_filter', None)
        name_filter = self.request.GET.get('name_filter', None)
        table_data = [{'id': i[0], 'name': i[1]} for i in SBC_TARGET_LEAGUES]
        if id_filter:
            int_id_filter = int(id_filter)
            table_data = [i for i in table_data if i['id'] == int_id_filter]
        if name_filter:
            table_data = [i for i in table_data if name_filter.lower() in i['name'].lower()]
        return table_data


class ClubsListView(GenericFilterListView):
    filterset_class = NationsFilter
    table_class = NationsListTable
    export_key = 'clubs_list'
    page_header = 'Clubs'

    def get_table_data(self):
        id_filter = self.request.GET.get('id_filter', None)
        name_filter = self.request.GET.get('name_filter', None)
        table_data = [{'id': i[0], 'name': i[1]} for i in SBC_TARGET_CLUBS]
        if id_filter:
            int_id_filter = int(id_filter)
            table_data = [i for i in table_data if i['id'] == int_id_filter]
        if name_filter:
            table_data = [i for i in table_data if name_filter.lower() in i['name'].lower()]
        return table_data


class PacksDescriptionListView(GenericListView):
    page_header = 'Packs Description'
    table_class = PacksListTable
    model = FifaAccount

    def get_table_data(self):
        with open(os.path.join(BASE_DIR, 'accounts/packs_data.xhtml'), 'r', encoding='utf') as packs_file:
            packs_data = packs_file.read()
        packs_searches = re.findall(f'PACK_(\d+)_NAME\">(\s+)<source>([^<]+)</source>', packs_data)
        packs_data_list = []
        packs_data_dict = {}
        for pack_item in packs_searches:
            pack_name = re.search(f'PACK_{pack_item[0]}_NAME\">(\s+)<source>([^<]+)</source>', packs_data).group(2)
            pack_mobile_name = re.search(f'PACK_{pack_item[0]}_NAME_MOBILE\">(\s+)<source>([^<]+)</source>', packs_data)
            if pack_mobile_name:
                pack_mobile_name = pack_mobile_name.group(2)
            pack_desc = re.search(f'PACK_{pack_item[0]}_DESC\">(\s+)<source>([^<]+)</source>', packs_data)
            if pack_desc:
                pack_desc = pack_desc.group(2)
            pack_item_data = {
                'id': pack_item[0],
                'pack_name': pack_name,
                'pack_mobile_name': pack_mobile_name,
                'pack_desc': pack_desc
            }
            packs_data_list.append(pack_item_data)
            packs_data_dict[pack_item[0]] = pack_item_data
        packs_data_list = [ii for ii in packs_data_list if ii.get('pack_desc')]
        return packs_data_list
        # return {'packs_data_list': packs_data_list, 'packs_data_dict': packs_data_dict}


class SbcWorkerUpdateView(LoginRequiredMixin, RequiredPermissionViewMixin, GenericUpdateView2):
    required_permission__ = 'sbc_worker__update'
    model = SBCWorker
    form_class = SbcWorkerUpdateForm
    back_url = reverse_lazy('console-worker-logs')

    @property
    def page_header(self):
        return 'Update %s' % self.object.fifa_account.user_name

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)

    def get_success_url(self):
        return reverse_lazy('sbc-worker-update', kwargs={'pk': self.object.id})

    def get_success_message(self, cleaned_data):
        return f'worker {self.object.id} successfully updated'

    # this bellow added because rel users get multiple object on get_queryset
    def get_queryset(self) -> QuerySet:
        return super().get_queryset().distinct('pk')


class SbcWorkersLogsListView(RequiredPermissionViewMixin, GenericListView):
    required_permission__ = 'sbc_workers_log__read'
    template_name = 'sbc/sbs_workers_report_list.html'
    model = SBCWorker
    table_class = SbcWorkersLogsListTable

    # filterset_class = SbcWorkersLogsFilter

    def get_card_data(self):
        cards_data = []
        sum_mule_credits = MuleAccounts.objects.all().aggregate(
            sum_credit=Sum('fifa_account__credit')).get('sum_credit')
        sum_produced_coin_24_hours = SBCWorker.objects.filter(
            end_time__gt=timezone.localtime() - datetime.timedelta(hours=24),
            produced_coins__gt=50000, is_done=True).aggregate(
            sum_produced_coin_24_hours=Sum('produced_coins')).get('sum_produced_coin_24_hours')
        count_done_worker_in_24_hours = SBCWorker.objects.filter(
            end_time__gt=timezone.localtime() - datetime.timedelta(hours=24),
            produced_coins__gt=50000, is_done=True).count()
        if not sum_produced_coin_24_hours:
            sum_produced_coin_24_hours = 0
        if not sum_mule_credits:
            sum_mule_credits = 0
        if count_done_worker_in_24_hours:
            average_done_worker_in_24_hours = number_convertor_to_milion(
                sum_produced_coin_24_hours / float(count_done_worker_in_24_hours))
        else:
            average_done_worker_in_24_hours = 0
        active_workers_count = self.get_queryset().filter(
            is_done=False, has_error=False, running_platform='console'
        ).count()
        all_active_console_workers = self.get_queryset().count()

        accounts_credit = FifaAccount.objects.filter(
            Q(delete_console_reason=None) | Q(delete_console_reason=''),
            console__is_active=True,
        ).only('credit').values_list('credit', flat=True)
        # accounts_credit = Console.objects.filter(
        #     is_active=True
        # ).exclude(
        #     fifaaccount__credit=None
        # ).values_list('fifaaccount__credit', flat=True)
        active_consoles = Console.objects.filter(is_active=True).count()
        cards_data.append({'name': 'Workers',
                           'info': f'{all_active_console_workers} - {active_workers_count}'})
        cards_data.append({'name': 'Active Consoles',
                           'info': f'{active_consoles}'})
        cards_data.append({'name': 'Sum Mule',
                           'info': number_convertor_to_milion(sum_mule_credits)})
        cards_data.append({'name': 'Sum Credit',
                           'info': number_convertor_to_milion(sum(accounts_credit))})
        # cards_data.append({'name': 'Sum Produced Coins In Last 24 Hours',
        #                    'info': number_convertor_to_milion(sum_produced_coin_24_hours)})
        # cards_data.append({'name': 'Sum Mule Coins',
        #                    'info': count_done_worker_in_24_hours})
        # cards_data.append({'name': 'Average Done Workers In 24 Hours',
        #                    'info': average_done_worker_in_24_hours})

        completed_40_games = FifaAccount.objects.filter(account_played_games__gte=F('allowed_play_game')).count()
        cards_data.append({'name': 'Accounts all games done',
                           'info': completed_40_games})
        games_done = FifaAccount.objects.aggregate(sum_games=Sum('account_played_games')).get('sum_games')
        cards_data.append({'name': 'all games done',
                           'info': games_done})
        cards_data.append({'name': 'games forcast',
                           'info': number_convertor_to_milion((games_done * 500) + (completed_40_games * 30000))})

        return cards_data

    def get_queryset(self):
        main_query = super().get_queryset()
        query_set = main_query.filter(
            is_done=False, has_error=False, running_platform='console'
        ).values_list('id', flat=True)
        query_set_2 = main_query.filter(
            running_platform='console',
            fifa_account__console__is_active=True,
        ).exclude(
            fifa_account__console__id__in=query_set.values_list('fifa_account__console__id', flat=True)
        ).order_by(
            'fifa_account__console',
            '-status_change_time'
        ).distinct('fifa_account__console').values_list('id', flat=True)
        query_set_4 = main_query.filter(
            id__in=list(query_set) + list(query_set_2),
        ).annotate(
            status_color=Case(
                When(id__in=query_set_2, then=Value('gray')),
                default=Value(''),
            )

        )
        return query_set_4.order_by('fifa_account__console__name')

    #     return super().get_queryset().filter(running_platform='console')

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)


class ConsoleWorkersLogsListView(RequiredPermissionViewMixin, GenericFilterListView):
    required_permission__ = 'console_log__read'
    template_name = 'sbc/sbs_workers_report_list.html'
    model = Console
    table_class = ConsoleWorkersLogsTable
    only_active_consoles = True
    page_header = 'Consoles Worker Log'
    filterset_class = ConsoleWorkersLogsFilter

    # def get_card_data(self):
    #     t1 = time.time()
    #     cards_data = []
    #     query_set = self.object_list
    #     sum_mule_credits = MuleAccounts.objects.filter(
    #         deleted=False,
    #         investors__in=query_set.values_list('investor', flat=True)
    #     )
    #     sum_mule_credits = MuleAccounts.objects.filter(id__in=sum_mule_credits.values_list('id', flat=True)).aggregate(
    #         sum_credit=Sum('fifa_account__credit')).get('sum_credit')
    #     if not sum_mule_credits:
    #         sum_mule_credits = 0
    #     active_workers_count = SBCWorker.objects.filter(
    #         is_done=False, has_error=False, running_platform='console',
    #         fifa_account__console__in=query_set,
    #     ).count()
    #     all_active_console_workers = self.get_queryset().filter(is_active=True).count()
    #
    #     accounts_credit = query_set.exclude(
    #         fifaaccount__credit=None
    #     ).filter(
    #         Q(fifaaccount__delete_console_reason=None) | Q(fifaaccount__delete_console_reason=''),
    #     ).values_list('fifaaccount__credit', flat=True)
    #     active_consoles = query_set.count()
    #     cards_data.append({'name': 'Workers',
    #                        'info': f'{all_active_console_workers} - {active_workers_count}',
    #                        'box_css_class': 'fw-bold'})
    #     cards_data.append({'name': 'Active Consoles',
    #                        'info': f'{active_consoles}',
    #                        'box_css_class': 'fw-bold'})
    #     cards_data.append({'name': 'Sum Mule',
    #                        'info': number_convertor_to_milion(sum_mule_credits),
    #                        'box_css_class': 'fw-bold'})
    #     cards_data.append({'name': 'Sum Credit',
    #                        'info': number_convertor_to_milion(sum(accounts_credit)),
    #                        'box_css_class': 'fw-bold'})
    #
    #     completed_40_games = FifaAccount.objects.exclude(
    #         allowed_play_game=0
    #     ).filter(
    #         account_played_games__gte=F('allowed_play_game'),
    #         console__in=query_set
    #     ).count()
    #     cards_data.append({'name': 'Accounts games complete',
    #                        'info': completed_40_games,
    #                        'box_css_class': 'fw-bold'})
    #     games_done = FifaAccount.objects.filter(
    #         console__in=query_set
    #     ).aggregate(
    #         sum_games=Sum('account_played_games'),
    #     ).get('sum_games') or 0
    #     cards_data.append({'name': 'games week',
    #                        'info': games_done,
    #                        'box_css_class': 'fw-bold'})
    #     games_done_24_hour = FifaAccountSquadGame.objects.filter(
    #         fifa_account__console__in=query_set,
    #         create_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
    #     ).count()
    #     forcast_games_24_hour = FifaAccount.objects.annotate(
    #         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)),
    #     ).filter(
    #         Q(delete_console_reason=None) | Q(delete_console_reason=''),
    #         (Q(account_all_played_games__lt=Value(100)) | Q(account_all_played_games__gt=Value(200))),
    #         console__in=query_set,
    #     ).aggregate(
    #         sum_forcast_games=Sum('allowed_play_game_day')
    #     ).get('sum_forcast_games') or 0
    #     cards_data.append({'name': 'games 24 h',
    #                        'info': f'{number_convertor_to_milion(forcast_games_24_hour)}-{number_convertor_to_milion(games_done_24_hour)}',
    #                        'box_css_class': 'fw-bold'})
    #     games_done_1_hour = FifaAccountSquadGame.objects.filter(
    #         fifa_account__console__in=query_set,
    #         create_time__gt=timezone.localtime() - timezone.timedelta(hours=1)
    #     ).count()
    #     cards_data.append({'name': 'games 1 h',
    #                        'info': number_convertor_to_milion(games_done_1_hour),
    #                        'box_css_class': 'fw-bold'})
    #     cards_data.append({'name': 'games forcast',
    #                        'info': number_convertor_to_milion((games_done * 500) + (completed_40_games * 30000)),
    #                        'box_css_class': 'fw-bold'})
    #
    #     if self.request.user.id not in [18, ]:
    #         fifa_accounts = FifaAccount.objects.filter(
    #             Q(delete_console_reason=None) | Q(delete_console_reason='')
    #         ).exclude(
    #             Q(console=None) | Q(console__investor=None)
    #         ).filter(
    #             console__name__in=self.object_list.values_list('name', flat=True)
    #         )
    #         cards_data.append({'name': 'All Accounts',
    #                            'info': f'{fifa_accounts.count()}',
    #                            'box_css_class': 'fw-bold'})
    #         sbc_process = SBCProcess.objects.filter(
    #             worker__fifa_account__console__in=self.object_list,
    #             sbc_number__in=SBCType.objects.exclude(
    #                 Q(sbc_number=1) | Q(sbc_number=2) | Q(sbc_number=3) | Q(sbc_number=4)
    #             ).filter(
    #                 console_can_use=True, must_done=1
    #             ).values_list('sbc_number', flat=True),
    #             is_done=True
    #         ).distinct('worker__fifa_account', 'sbc_type')
    #         completed_account = sbc_process.distinct('worker__fifa_account').count()
    #         completed_process = sbc_process.count()
    #         cards_data.append({'name': 'SBC Completed',
    #                            'info': f'{completed_account} - {completed_process}',
    #                            'box_css_class': 'fw-bold'})
    #         invest_trade_24_hour = ConsoleInvestTradeItemsCountLog.objects.filter(
    #             fifa_account__console__in=self.object_list,
    #             create_time__gt=timezone.localtime() - timezone.timedelta(hours=24),
    #         )
    #         invest_trade_24_hour_account = invest_trade_24_hour.distinct('fifa_account').count()
    #         invest_trade_24_hour_round = invest_trade_24_hour.aggregate(
    #             sum_complete_trade_count_new=Sum('complete_trade_count_new')
    #         ).get('sum_complete_trade_count_new') or 0
    #         cards_data.append({'name': 'Trade Round',
    #                            'info': f'{invest_trade_24_hour_account} - {invest_trade_24_hour_round}',
    #                            'box_css_class': 'fw-bold'})
    #     t2 = time.time()
    #     print(' cards data : ', t2-t1)
    #     return cards_data

    def get_card_data(self):
        return []

    def allowed_discharge_time(self):
        # get current time
        try:
            ntp_client = ntplib.NTPClient()
            ntp_response = ntp_client.request('uk.pool.ntp.org', version=3)
            current_time = datetime.datetime.fromtimestamp(ntp_response.tx_time, datetime.timezone.utc).astimezone(
                gettz('Asia/Tehran'))
        except (ntplib.NTPException, socket.gaierror):
            current_time = timezone.localtime()
        return 3 <= current_time.hour < 15

    def get_table_data(self):
        # now_local_time = timezone.localtime()
        # hours_24_ago = now_local_time - timezone.timedelta(hours=24)
        return []
        result_data = []
        consoles_id = self.get_queryset().values_list('id', flat=True)
        cached_data = get_console_worker_logs(return_result=True)
        for item_data in cached_data.get('data', []):
            if item_data['console_id'] in consoles_id:
                result_data.append(item_data)
        result_data = sorted(result_data, key=lambda d: d['console_name'])
        # query = super().get_table_data()
        # query = self.get_queryset().annotate(
        # allowed_discharge_time_var = self.allowed_discharge_time()
        # lowest_account_run_in_console_hour = ConsoleBotSetting.objects.get(name='lowest_account_run_in_console_hour').int_value
        # discharge_start_coin_greater = ConsoleBotSetting.objects.get(name='discharge_start_coin_greater').int_value
        # discharge_start_coin_lower = ConsoleBotSetting.objects.get(name='discharge_start_coin_lower').int_value
        # t1 = time.time()
        # query = query.annotate(
        #     # console_last_24_hour_played=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
        #     #     fifa_account__console__id=OuterRef('pk'),
        #     #     create_time__gt=now_local_time - timezone.timedelta(hours=24)
        #     # ).values('fifa_account__console').annotate(
        #     #     played_count=Count('id', output_field=IntegerField())
        #     # ).values('played_count'), output_field=IntegerField()), Value(0)),
        #     console_credit=Coalesce(Subquery(FifaAccount.objects.filter(
        #         console__id=OuterRef('pk'),
        #     ).values('console').annotate(
        #         sum_accounts_credit=Sum('credit', output_field=IntegerField())
        #     ).values('sum_accounts_credit'), output_field=IntegerField()), Value(0)),
        #     last_accounts_worker_id=Subquery(SBCWorker.objects.filter(
        #         fifa_account__console__id=OuterRef('pk'),
        #     ).order_by('status_change_time').values('id').reverse()[:1]),
        #     last_console_worker_id=Subquery(SBCWorker.objects.filter(
        #         # Q(fifa_account__delete_console_reason=None) | Q(fifa_account__delete_console_reason=''),
        #         fifa_account__console__id=OuterRef('pk'),
        #         running_platform__in=['console', 'console_web_pc'],
        #     ).order_by('status_change_time').values('id').reverse()[:1]),
        #     last_active_account_worker_id=Subquery(SBCWorker.objects.filter(
        #         Q(fifa_account__delete_console_reason=None) | Q(fifa_account__delete_console_reason=''),
        #         id__gte=OuterRef('last_accounts_worker_id'),
        #         fifa_account__console__id=OuterRef('pk'),
        #         is_done=False, has_error=False, running_platform__in=['console', 'console_web_pc'],
        #     ).order_by('status_change_time').values('id').reverse()[:1]),
        # )
        # query_values_list = query.values_list('last_active_account_worker_id', 'last_console_worker_id')
        # last_1 = []
        # last_2 = []
        # for item in query_values_list:
        #     last_1.append(item[0])
        #     last_2.append(item[1])
        # t12 = time.time()
        # print('t12 : ', t12 - t1)
        # related_quieries = list(SBCWorker.objects.filter(
        #     id__in=last_1
        # ).annotate(
        #     fifa_acc_id=F('fifa_account__id'),
        #     fifa_acc_user_name=F('fifa_account__user_name'),
        #     fifa_acc_name_in_console=F('fifa_account__name_in_console'),
        #     fifa_acc_platform=F('fifa_account__platform'),
        #     fifa_acc_any_desk=F('fifa_account__pc__any_desk_code'),
        # ))
        # print('len rel 1 ', len(related_quieries))
        # related_quieries_2 = list(SBCWorker.objects.filter(
        #     id__in=last_2
        # ).annotate(
        #     fifa_acc_id=F('fifa_account__id'),
        #     fifa_acc_user_name=F('fifa_account__user_name'),
        #     fifa_acc_name_in_console=F('fifa_account__name_in_console'),
        #     fifa_acc_platform=F('fifa_account__platform'),
        #     fifa_acc_any_desk=F('fifa_account__pc__any_desk_code'),
        # ))
        # print('len rel2 ', len(related_quieries_2))
        # t14 = time.time()
        # print('t14 : ', t14 - t1)
        # must_done_sbc_numbers = list(SBCType.objects.filter(
        #                             console_can_use=True, must_done=1
        #                         ).values_list('sbc_number', flat=True))
        # # all_fifa_account_worked_in_24_hour = list(SBCWorker.objects.filter(
        # #     Q(fifa_account__delete_console_reason=None) | Q(fifa_account__delete_console_reason='')
        # # ).exclude(
        # #     fifa_account__name_in_console='key'
        # # ).filter(
        # #     status_change_time__gt=now_local_time - timezone.timedelta(hours=24)
        # # ).distinct('fifa_account__id').values_list('fifa_account__console__id', 'fifa_account__id'))
        # t2 = time.time()
        # print('t2 ', t2 - t1)
        # for item in query:
        #     # console_credit = item.fifaaccount_set.aggregate(console_credit=Sum('credit')).get('console_credit')
        #     # last_worker = SBCWorker.objects.filter(
        #     #     is_done=False, has_error=False, running_platform='console',
        #     #     fifa_account__in=item.fifaaccount_set.filter(
        #     #         Q(delete_console_reason=None) | Q(delete_console_reason=''),
        #     #     )
        #     # ).order_by('status_change_time').last()
        #     # fifa_account_worked_in_24_hour = SBCWorker.objects.select_related('fifa_account').filter(
        #     #     fifa_account__in=item.fifaaccount_set.filter(
        #     #         Q(delete_console_reason=None) | Q(delete_console_reason=''),
        #     #     ).exclude(name_in_console='key'),
        #     #     status_change_time__gt=now_local_time - timezone.timedelta(hours=24)
        #     # ).distinct('fifa_account__id').values_list('fifa_account__id', flat=True)[:item.allowed_account_work_day]
        #     # todo : merge bellow query to queryset with subquery . to make it faster
        #     # console_last_24_hour_played = FifaAccountSquadGame.objects.filter(
        #     #     fifa_account__console=item,
        #     #     create_time__gt=now_local_time - timezone.timedelta(hours=24)
        #     # ).count()
        #     status_color = ''
        #     last_worker = None
        #     if item.pc_is_on is False:
        #         # last_worker = SBCWorker.objects.filter(
        #         #     fifa_account__console=item
        #         # ).order_by('status_change_time').last()
        #         # last_worker = SBCWorker.objects.select_related('fifa_account', 'fifa_account__pc').get(id=item.last_accounts_worker_id)
        #         last_active_id = item.last_active_account_worker_id
        #         if last_active_id:
        #             for item_3 in related_quieries:
        #                 if item_3.id == item.last_active_account_worker_id:
        #                     last_worker = item_3
        #                     break
        #         else:
        #             for item_3 in related_quieries_2:
        #                 if item_3.id == item.last_console_worker_id:
        #                     last_worker = item_3
        #                     break
        #         status_color = 'light-green2'
        #         last_status = 'PC Off'
        #         # if item.console_last_24_hour_played >= item.allowed_play_game_day:
        #         #     first_play_game = FifaAccountSquadGame.objects.filter(
        #         #         fifa_account__console=item,
        #         #         create_time__gt=now_local_time - 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()
        #         #     hours, remainder = divmod(need_rest_time.seconds, 3600)
        #         #     minutes, seconds = divmod(remainder, 60)
        #         #     last_status += '- need rest {} H : {} M'.format(int(hours), int(minutes))
        #         #     # last_status += f" - need rest {':'.join(str(need_rest_time).split(':')[:2])}"
        #         #     status_color = 'light-green'
        #     elif item.last_active_account_worker_id:
        #         for item_2 in related_quieries:
        #             if item_2.id == item.last_active_account_worker_id:
        #                 last_worker = item_2
        #                 last_status = last_worker.status
        #                 break
        #     else:
        #         # fifa_account_worked_in_24_hour = []
        #         # for nnntt in all_fifa_account_worked_in_24_hour:
        #         #     if nnntt[0] == item.id:
        #         #         fifa_account_worked_in_24_hour.append(nnntt[1])
        #         last_worker = SBCWorker.objects.filter(
        #             running_platform__in=['console', 'console_web_pc'],
        #             fifa_account__console=item,
        #             status_change_time__gt=hours_24_ago,
        #             # fifa_account__id__in=fifa_account_worked_in_24_hour
        #         ).annotate(
        #             fifa_acc_id=F('fifa_account__id'),
        #             fifa_acc_user_name=F('fifa_account__user_name'),
        #             fifa_acc_name_in_console=F('fifa_account__name_in_console'),
        #             fifa_acc_platform=F('fifa_account__platform'),
        #             fifa_acc_any_desk=F('fifa_account__pc__any_desk_code'),
        #         ).order_by('status_change_time').last()
        #         if last_worker:
        #             need_work_2 = FifaAccount.objects.filter(
        #                 console=item,
        #                 last_run_time__gt=hours_24_ago,
        #                 # id__in=fifa_account_worked_in_24_hour
        #             ).annotate(
        #                 # can_play=Value(item.console_last_24_hour_played < item.allowed_play_game_day),
        #                 # last_sbc_worker_id=Coalesce(Subquery(SBCWorker.objects.filter(
        #                 #     running_platform='console',
        #                 #     fifa_account__id=OuterRef('pk')
        #                 # ).order_by('status_change_time').last().values('id'))),
        #                 # console_last_24_hour_played__lt=Value(item.allowed_play_game_day),
        #                 uncompleted_sbc=Value(SBCType.objects.filter(console_can_use=True, must_done=1).exclude(
        #                     id__in=SBCProcess.objects.filter(
        #                         sbc_number__in=must_done_sbc_numbers,
        #                         worker__fifa_account__console=item,
        #                         worker__status_change_time__gt=hours_24_ago,
        #                         is_done=True
        #                     ).distinct('sbc_type').values_list('sbc_type__id', flat=True)
        #                 ).count()),
        #                 account_24_played_games=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
        #                     fifa_account__id=OuterRef('pk'),
        #                     create_time__gt=hours_24_ago
        #                 ).values('fifa_account').annotate(
        #                     played_count=Count('id', output_field=IntegerField())
        #                 ).values('played_count'), output_field=IntegerField()), Value(0)),
        #                 account_31_day_played_games=Coalesce(Subquery(FifaAccountSquadGame.objects.filter(
        #                     fifa_account__id=OuterRef('pk'),
        #                     create_time__gt=now_local_time - 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)),
        #             ).filter(
        #                 Q(last_run_time__lt=now_local_time -
        #                                     timezone.timedelta(hours=lowest_account_run_in_console_hour)) &
        #                 (((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(allowed_play_game_day__gt=F('account_24_played_games')) &
        #                   # Q(account_played_games__lt=F('allowed_play_game')) &
        #                   # Q(account_31_day_played_games__lt=Value(88))
        #                   (Q(account_all_played_games__lt=Value(12)) | Q(account_all_played_games__gt=Value(400)) |
        #                    Q(console__name__in=list(range(9000, 9500))))
        #                   ) |
        #                  (Q(run_discharge=True) & Q(credit__gt=discharge_start_coin_greater) &
        #                   Q(credit__lt=discharge_start_coin_lower) & Value(allowed_discharge_time_var)) |
        #                  (Q(run_sbc=True) & Q(credit__gt=8000) & Q(uncompleted_sbc__gt=0)) |
        #                  (Q(trade_access__in=['0', '1', '3']) & (Q(run_console_trade_one=True) & Q(credit__gt=10000) &
        #                    Q(is_running_console_trade_one=False)) | Q(is_running_console_trade_one=True))
        #                  )
        #             ).exclude(
        #                 name_in_console='key'
        #             ).order_by('last_run_time')
        #             if need_work_2:
        #                 if last_worker.status_change_time < now_local_time - timezone.timedelta(minutes=5):
        #                     status_color = 'red'
        #                 else:
        #                     status_color = 'gray'
        #                 last_status = 'resting ...'
        #             else:
        #                 # if 0 < item.allowed_play_game_day <= item.console_last_24_hour_played:
        #                 #     status_color = 'gray'
        #                 #     last_status = 'resting 3 ...'
        #                 # else:
        #                 #     status_color = 'dark-gray'
        #                 #     last_status = 'all account is done'
        #                 status_color = 'dark-gray'
        #                 last_status = 'all account is done'
        #         else:
        #             last_worker = SBCWorker.objects.filter(
        #                 Q(fifa_account__delete_console_reason=None) | Q(fifa_account__delete_console_reason='')
        #             ).exclude(
        #                 fifa_account__name_in_console='key'
        #             ).annotate(
        #                 fifa_acc_id=F('fifa_account__id'),
        #                 fifa_acc_user_name=F('fifa_account__user_name'),
        #                 fifa_acc_name_in_console=F('fifa_account__name_in_console'),
        #                 fifa_acc_platform=F('fifa_account__platform'),
        #                 fifa_acc_any_desk=F('fifa_account__pc__any_desk_code'),
        #             ).filter(
        #                 fifa_account__console=item,
        #                 running_platform__in=['console', 'console_web_pc'],
        #             ).order_by('status_change_time').last()
        #             # last_worker = SBCWorker.objects.get(id=item.last_console_worker_id)
        #             if last_worker:
        #                 status_color = 'dark-gray'
        #                 last_status = 'resting 2 ...'
        #             else:
        #                 continue
        #             # last_worker = SBCWorker.objects.last()
        #             # last_status = 'Fake Status'
        #     if last_worker:
        #         a = {
        #             'id': last_worker.id,
        #             'status': last_status,
        #             'status_change_time': last_worker.status_change_time,
        #             'status_color': status_color,
        #             # 'fifa_account': last_worker.fifa_account,
        #             'fifa_account_id': last_worker.fifa_acc_id,
        #             'fifa_account_user_name': last_worker.fifa_acc_user_name,
        #             'name_in_console': f'{last_worker.fifa_acc_name_in_console} - {last_worker.fifa_acc_platform}',
        #             'console_name': item.name,
        #             'any_desk': last_worker.fifa_acc_any_desk,
        #             'description': last_worker.description,
        #             'console_credit': item.console_credit,
        #         }
        #     else:
        #         continue
        #
        #     result_data.append(a)
        # t4 = time.time()
        # print('t4 ', t4 - t1)
        return result_data

    def get_queryset(self):
        if self.only_active_consoles:
            main_query = super().get_queryset().filter(is_active=True).order_by('name')
        else:
            main_query = super().get_queryset().order_by('name')
        range_number_min = int(self.request.GET.get('range_number_min') or 0)
        range_number_max = int(self.request.GET.get('range_number_max') or 0)
        if range_number_max and range_number_max and range_number_min < range_number_max:
            main_query = main_query.filter(name__in=list(range(range_number_min, range_number_max)))
        return main_query

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)

    def get_filterset_kwargs(self, filterset_class):
        kwargs = super().get_filterset_kwargs(filterset_class)
        kwargs['request'] = self.request
        return kwargs


class ConsoleWorkersLogs2ListView(RequiredPermissionViewMixin, GenericFilterListView):
    required_permission__ = 'console_log__read'
    template_name = 'sbc/sbs_workers_report_list.html'
    model = ConsoleLastStatus
    table_class = ConsoleWorkersLogsTable
    only_active_consoles = True
    page_header = 'Consoles Worker Log'
    filterset_class = ConsoleWorkersLogs2Filter

    def get_card_data(self):
        return []

    def get_table_data(self):
        result_data = []
        query = super().get_table_data()
        consoles_status = ConsoleLastStatus.objects.annotate(
            helth_account_count=Count(
                'console__fifaaccount',
                filter=Q(Q(console__fifaaccount__delete_console_reason=None) |
                         Q(console__fifaaccount__delete_console_reason=''))),
            console_credit=Sum(
                'console__fifaaccount__credit',
                filter=Q(Q(console__fifaaccount__delete_console_reason=None) |
                         Q(console__fifaaccount__delete_console_reason='')))

        ).filter(
            console__in=query.values('console'),
            helth_account_count__gte=1
        ).select_related(
            'console', 'fifa_account', 'fifa_account__pc', 'sbc_worker'
        ).order_by('console__name')
        for item in consoles_status.iterator():
            if not item.sbc_worker:
                print('what?? no worker??', item.console)
                continue
            console_data = {
                'id': item.sbc_worker.id,
                'console_id': item.console.id,
                'status': item.status,
                'status_change_time': item.status_change_time,
                'status_color': 1,
                'running_platform': 'pc' if item.sbc_worker.running_platform in ['console_web_pc',] else 'console',
                'fifa_account_id': item.fifa_account.id,
                'fifa_account_user_name': item.fifa_account.user_name,
                'name_in_console': f'{item.fifa_account.name_in_console} - {item.fifa_account.platform}',
                'console_name': item.console.name,
                'any_desk': item.fifa_account.pc.any_desk_code,
                'any_desk_2': item.fifa_account.pc.any_desk_code_2,
                'location_code': item.fifa_account.pc.location_code,
                'description': item.description,
                'console_credit': item.console_credit,
            }
            if item.status == 'all account is done':
                status_color = 'dark-gray'
            elif item.status in ['PC Turned off', 'PC is asleep']:
                status_color = 'light-green'
            elif item.status in ['Waiting for sbc', 'Console is asleep']:
                status_color = 'gray-blue'
            elif item.status in ['Waiting for sbc', 'Console is asleep']:
                status_color = 'blue-gray'
            elif item.status in ['Add Accounts Done.', 'Adding Accounts', 'removing accounts', 'stop after add accounts']:
                status_color = 'yellow'
            else:
                status_color = ''
            console_data.update({'status_color': status_color})
            result_data.append(console_data)
        self.page_header = self.page_header + f'   {len(result_data)}'
        return result_data

    def get_queryset(self):
        if self.only_active_consoles:
            main_query = super().get_queryset().filter(
                console__is_active=True
            ).select_related('console').order_by('console__name')
        else:
            main_query = super().get_queryset().select_related('console').order_by('console__name')
        range_number_min = int(self.request.GET.get('range_number_min') or 0)
        range_number_max = int(self.request.GET.get('range_number_max') or 0)
        if range_number_max and range_number_max and range_number_min < range_number_max:
            main_query = main_query.filter(console__name__in=list(range(range_number_min, range_number_max)))
        return main_query

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)

    def get_filterset_kwargs(self, filterset_class):
        kwargs = super().get_filterset_kwargs(filterset_class)
        kwargs['request'] = self.request
        return kwargs


class ConsoleWorkersDataListView(ConsoleWorkersLogsListView):
    page_header = 'Consoles Workers Data'

    def get_card_data(self):
        cards_data = []
        query_set = self.object_list
        sum_mule_credits = MuleAccounts.objects.filter(
            deleted=False,
            investors__in=query_set.values_list('investor', flat=True)
        )
        sum_mule_credits = MuleAccounts.objects.filter(id__in=sum_mule_credits.values_list('id', flat=True)).aggregate(
            sum_credit=Sum('fifa_account__credit')).get('sum_credit')
        if not sum_mule_credits:
            sum_mule_credits = 0
        active_workers_count = SBCWorker.objects.filter(
            is_done=False, has_error=False, running_platform='console',
            fifa_account__console__in=query_set,
        ).count()
        all_active_console_workers = self.get_queryset().filter(is_active=True).count()

        accounts_credit = query_set.exclude(
            fifaaccount__credit=None
        ).filter(
            Q(fifaaccount__delete_console_reason=None) | Q(fifaaccount__delete_console_reason=''),
        ).values_list('fifaaccount__credit', flat=True)
        active_consoles = query_set.filter(is_active=True).count()
        cards_data.append({'name': 'Workers',
                           'info': f'{all_active_console_workers} - {active_workers_count}',
                           'box_css_class': 'fw-bold'})
        cards_data.append({'name': 'Active Consoles',
                           'info': f'{active_consoles}',
                           'box_css_class': 'fw-bold'})
        cards_data.append({'name': 'Sum Mule',
                           'info': number_convertor_to_milion(sum_mule_credits),
                           'box_css_class': 'fw-bold'})
        cards_data.append({'name': 'Sum Credit',
                           'info': number_convertor_to_milion(sum(accounts_credit)),
                           'box_css_class': 'fw-bold'})

        completed_40_games = FifaAccount.objects.exclude(
            allowed_play_game=0
        ).filter(
            account_played_games__gte=F('allowed_play_game'),
            console__in=query_set
        ).count()
        cards_data.append({'name': 'Accounts games complete',
                           'info': completed_40_games,
                           'box_css_class': 'fw-bold'})
        games_done = FifaAccount.objects.filter(
            console__in=query_set
        ).aggregate(
            sum_games=Sum('account_played_games'),
        ).get('sum_games') or 0
        cards_data.append({'name': 'games week',
                           'info': games_done,
                           'box_css_class': 'fw-bold'})
        games_done_24_hour = FifaAccountSquadGame.objects.filter(
            fifa_account__console__in=query_set,
            create_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
        ).count()
        forcast_games_24_hour = FifaAccount.objects.annotate(
            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)),
        ).filter(
            Q(delete_console_reason=None) | Q(delete_console_reason=''),
            (Q(account_all_played_games__lt=Value(12)) | Q(account_all_played_games__gt=Value(400))),
            console__in=query_set,
        ).aggregate(
            sum_forcast_games=Sum('allowed_play_game_day')
        ).get('sum_forcast_games') or 0
        cards_data.append({'name': 'games 24 h',
                           'info': f'{number_convertor_to_milion(forcast_games_24_hour)}-{number_convertor_to_milion(games_done_24_hour)}',
                           'box_css_class': 'fw-bold'})
        games_done_1_hour = FifaAccountSquadGame.objects.filter(
            fifa_account__console__in=query_set,
            create_time__gt=timezone.localtime() - timezone.timedelta(hours=1)
        ).count()
        cards_data.append({'name': 'games 1 h',
                           'info': number_convertor_to_milion(games_done_1_hour),
                           'box_css_class': 'fw-bold'})
        cards_data.append({'name': 'games forcast',
                           'info': number_convertor_to_milion((games_done * 500) + (completed_40_games * 30000)),
                           'box_css_class': 'fw-bold'})

        if self.request.user.id not in [18, ]:
            fifa_accounts = FifaAccount.objects.filter(
                Q(delete_console_reason=None) | Q(delete_console_reason='') | Q(delete_console_reason='no_console')
            ).exclude(
                Q(console=None) | Q(console__investor=None)
            ).filter(
                console__name__in=self.object_list.values_list('name', flat=True)
            )
            cards_data.append({'name': 'All Accounts',
                               'info': f'{fifa_accounts.count()}',
                               'box_css_class': 'fw-bold'})
            sbc_process = SBCProcess.objects.filter(
                # worker__fifa_account__console__in=self.object_list,
                worker__fifa_account__in=fifa_accounts,
                sbc_number__in=SBCType.objects.exclude(
                    # Q(sbc_number=1) | Q(sbc_number=2) | Q(sbc_number=3) | Q(sbc_number=4)
                ).filter(
                    console_can_use=True, must_done=1
                ).values_list('sbc_number', flat=True),
                is_done=True
            ).distinct('worker__fifa_account', 'sbc_type')
            completed_account = sbc_process.distinct('worker__fifa_account').count()
            completed_process = sbc_process.count()
            cards_data.append({'name': 'SBC Completed',
                               'info': f'{completed_account} - {completed_process}',
                               'box_css_class': 'fw-bold'})
            invest_trade_24_hour = ConsoleInvestTradeItemsCountLog.objects.filter(
                fifa_account__console__in=self.object_list,
                create_time__gt=timezone.localtime() - timezone.timedelta(hours=24),
            )
            invest_trade_24_hour_account = invest_trade_24_hour.distinct('fifa_account').count()
            invest_trade_24_hour_round = invest_trade_24_hour.aggregate(
                sum_complete_trade_count_new=Sum('complete_trade_count_new')
            ).get('sum_complete_trade_count_new') or 0
            cards_data.append({'name': 'Trade Round',
                               'info': f'{invest_trade_24_hour_account} - {invest_trade_24_hour_round}',
                               'box_css_class': 'fw-bold'})
        return cards_data


    def get_table_data(self):
        result_data = []
        return result_data


class TemporarySbcWorkersLogsListView(RequiredPermissionViewMixin, GenericListView):
    required_permission__ = 'sbc_workers_log__read'
    template_name = 'sbc/sbs_workers_report_list.html'
    model = SBCWorker
    table_class = TemporarySbcWorkersLogs

    def get_queryset(self):
        return super().get_queryset().filter(
            running_platform='console',
            has_error=True,
            status_change_time__gt=timezone.localtime() - timezone.timedelta(hours=24)
        ).order_by('fifa_account__console__name')

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)


class SbcWorkersLastsListView(GenericListView):
    template_name = 'sbc/sbs_workers_done_list.html'
    model = SBCWorker
    table_class = SbcWorkersLastsListTable
    export_key = 'sbc_worker_lasts'

    def get_consoles_data(self):
        consoles_number = SBCWorker.objects.filter(end_time__gt=timezone.localtime() - datetime.timedelta(hours=48),
                                                   produced_coins__gt=2000, is_done=True).values_list(
            'fifa_account__console', flat=True).distinct().count()
        # print('sum_produced_coin_24_hours = ',sum_produced_coin_24_hours)
        return {'sum_console_number': consoles_number,
                }

    def get_queryset(self):
        return super().get_queryset().filter(end_time__gt=timezone.localtime() - datetime.timedelta(hours=48),
                                             produced_coins__gt=2000, is_done=True)


class AddWorkerDescription(LoginRequiredMixin, TemplateView):
    template_name = 'public/success.html'

    def get_context_data(self, **kwargs):
        return {'message': 'Save Description Success', 'back_url': reverse_lazy("console-worker-logs")}

    def get(self, request, *args, **kwargs):
        if request.GET.get('clear'):
            sbc_worker = SBCWorker.objects.get(id=kwargs.get('sbc_worker_id'))
            console_last_status = ConsoleLastStatus.objects.filter(console=sbc_worker.fifa_account.console).last()
            console_last_status.status = 'clear'
            console_last_status.status_change_time = timezone.localtime()
            console_last_status.save(update_fields=['status', 'status_change_time'])
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        sbc_worker = SBCWorker.objects.get(id=kwargs.get('sbc_worker_id'))
        console_last_status = ConsoleLastStatus.objects.filter(console=sbc_worker.fifa_account.console).last()
        sbc_worker.description = self.request.POST.get("record_description")
        sbc_worker.description_editor = self.request.user
        sbc_worker.save(update_fields=['description', 'description_editor'])
        if console_last_status:
            console_last_status.description = self.request.POST.get("record_description")
            console_last_status.description_editor = self.request.user
            console_last_status.save(update_fields=['description', 'description_editor'])
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)


@login_required
def add_description_to_worker(request, sbc_worker_id):
    sbc_worker = SBCWorker.objects.get(id=sbc_worker_id)
    sbc_worker.description = request.POST.get("record_description")
    sbc_worker.description_editor = request.user
    sbc_worker.save()
    # todo : fix bellow. one form with two redirect url
    # return redirect(reverse_lazy("sbc-worker-logs"))
    return redirect(reverse_lazy("console-worker-logs"))


class SbcWorkersReportsListView(GenericListView):
    template_name = 'sbc/sbs_workers_report_list.html'
    model = SBCWorkerDetailsLog
    table_class = SbcWorkerReportsListTable
    export_key = 'sbc_workers'

    def get_queryset(self):
        sbc_worker_id = self.kwargs.get('sbc_worker_id')
        return super().get_queryset().filter(worker__id=sbc_worker_id).order_by('id')


class AccountLastSbcWorkersListView(GenericListView):
    template_name = 'sbc/sbs_workers_report_list.html'
    model = SBCWorkerDetailsLog
    table_class = SbcWorkerReportsListTable
    export_key = 'last_sbc_workers'

    def get_queryset(self):
        fifa_account_id = self.kwargs.get('pk')
        return super().get_queryset().filter(
            Q(worker__fifa_account__id=fifa_account_id) |
            Q(worker__fifa_account__user_name=fifa_account_id)
        ).order_by('pk')


class AccountLastMainSBCWorkersDetailListView(GenericListView):
    template_name = 'sbc/sbs_workers_report_list.html'
    model = SBCWorkerDetailsLog
    table_class = SbcWorkerReportsListTable
    export_key = 'last_sbc_workers'

    def get_queryset(self):
        fifa_account_id = self.kwargs.get('pk')
        return super().get_queryset().filter(
            Q(worker__fifa_account__id=fifa_account_id) |
            Q(worker__fifa_account__user_name=fifa_account_id),
            main_job=True,
        ).order_by('pk')


class ConsoleLastMainSBCWorkersDetailListView(GenericListView):
    template_name = 'sbc/sbs_workers_report_list.html'
    model = SBCWorkerDetailsLog
    table_class = SbcWorkerReportsListTable
    export_key = 'last_console_log'

    def get_queryset(self):
        fifa_account_id = self.kwargs.get('pk')
        console = FifaAccount.objects.only('console').get(id=fifa_account_id).console

        return super().get_queryset().filter(
            worker__fifa_account__console=console,
            main_job=True,
        ).select_related(
            'worker__fifa_account'
        ).annotate(
            account_user_name=F('worker__fifa_account__user_name')
        ).order_by('pk')

# class SbcWorkersReportsListView(GenericListView):
#     model = SBCWorker
#     table_class = SbcWorkerReports
#
#     def get_table_data(self):
#         sbc_worker_id = self.kwargs.get('sbc_worker_id')
#         object_list = []
#         sbc_worker = SBCWorker.objects.get(id=sbc_worker_id)
#
#         sbc_processes = SBCProcess.objects.filter(worker=sbc_worker).all().order_by('id')
#         worker_times = []
#         worker_times.append(['preparing ...', sbc_worker.start_time])
#         temp_time = timezone.localtime()
#         for sbc_process in sbc_processes:
#             worker_times.append([sbc_process.sbc_type.name, sbc_process.start_time])
#             temp_time = sbc_process.start_time
#         worker_times.append([sbc_worker.status, sbc_worker.status_change_time])
#         if temp_time > sbc_worker.end_time:
#             worker_times.append(['end', timezone.localtime()])
#         else:
#             worker_times.append(['end', sbc_worker.end_time])
#         average_sbc = 0
#         sum_count = 0
#         all_average = 0
#         all_average_count = 0
#         for i in range(1, len(worker_times)):
#             process_time = (worker_times[i][1] - worker_times[i - 1][1]).total_seconds() / 60
#             # print(worker_times[i - 1][0], process_time)
#             object_list.append({'status': worker_times[i - 1][0], 'time': process_time})
#             if i != len(worker_times) - 1:
#                 all_average += process_time
#                 all_average_count += 1
#                 if 1 < process_time < 100:
#                     average_sbc += process_time
#                     sum_count += 1
#         if sum_count:
#             # print('sbc average time = ',average_sbc/sum_count)
#             object_list.append({'status': 'sbc average time', 'time': average_sbc / sum_count})
#             object_list.append({'status': 'all average time', 'time': all_average / all_average_count})
#         return object_list

@login_required
def sbc_orders_excel(request, order_id):
    order = SBCOrder.objects.get(id=order_id)
    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = f'attachment; filename="download_{order.file_name}"'
    wb = Workbook()
    ws = wb.active
    worker_list = SBCWorker.objects.filter(sbc_order__id=order_id).select_related(
        'fifa_account'
    ).order_by('id').values(
        'fifa_account__console__name',
        'fifa_account__id',
        'fifa_account__user_name',
        'fifa_account__password',
        'fifa_account__platform',
        'fifa_account__account_backup_code__app_code',
        'fifa_account__account_backup_code__backup_code',
        'fifa_account__account_backup_code__backup_codes_str',
        'fifa_account__credit',
        'fifa_account__active',
        'fifa_account__need_captcha',
        'is_done', 'has_error', 'error_description', 'complete_number',
        'manual_loyal', 'start_coin', 'last_run_time', 'end_time', 'status'
    )
    ws.append(
        ['console', 'user name', 'password', 'platform', 'app code', 'backup code', 'backup codes',
         'manual loyal', 'search number', 'credit',
         'start credit', 'active', 'is done', 'has error',
         'error description', 'complete number', 'captcha', 'start time', 'end time'])
    for item in worker_list:
        ws.append([
            item.get('fifa_account__console__name'),
            item.get('fifa_account__user_name'), item.get('fifa_account__password'),
            item.get('fifa_account__platform'),
            item.get('fifa_account__account_backup_code__app_code'),
            item.get('fifa_account__account_backup_code__backup_code'),
            item.get('fifa_account__account_backup_code__backup_codes_str'),
            item.get('manual_loyal'),
            FifaAccountSearch.objects.filter(
                fifa_account__id=item.get('fifa_account__id'),
                search_time__gt=timezone.localtime() - timezone.timedelta(hours=24)).count(),
            item.get('fifa_account__credit'), item.get('start_coin'),
            item.get('fifa_account__active'),
            item.get('is_done'), item.get('has_error'), item.get('error_description'),
            item.get('complete_number'),
            item.get('fifa_account__need_captcha'),
            str(item.get('last_run_time')),
            str(item.get('end_time')),
            item.get('status') or '',
        ])
    wb.save(response)
    return response


class ActiveSBCTasks(GenericListView):
    model = SBCWorker
    table_class = ActiveSBCTasksTable

    def get_extra_buttons(self):
        return [{'text': 'Cancel All', 'color': 'btn-danger',
                 'url': reverse_lazy('cancel-sbc-task', kwargs={'sbc_worker_id': 0})}]

    def get_queryset(self):
        return super(ActiveSBCTasks, self).get_queryset().filter(fifa_account__active=True)


class CancelSBCTask(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        print(kwargs.get('sbc_worker_id'))
        if str(kwargs.get('sbc_worker_id')) == '0':
            sbc_workers = SBCWorker.objects.filter(fifa_account__active=True)
            for sbc_worker in sbc_workers:
                sbc_worker.must_done = True
                sbc_worker.save()
                sbc_worker.fifa_account.active = False
                sbc_worker.fifa_account.login_status = 0
                sbc_worker.fifa_account.driver = False
                sbc_worker.fifa_account.save()
                app.control.revoke(sbc_worker.task_id, terminate=True, signal='SIGKILL')
        else:
            sbc_worker = SBCWorker.objects.get(id=kwargs.get('sbc_worker_id'))
            sbc_worker.must_done = True
            sbc_worker.save()
            sbc_worker.fifa_account.active = False
            sbc_worker.fifa_account.login_status = 0
            sbc_worker.fifa_account.driver = False
            sbc_worker.fifa_account.save()
            app.control.revoke(sbc_worker.task_id, terminate=True, signal='SIGKILL')
        messages.add_message(self.request, messages.SUCCESS, 'Successful stopped')
        return redirect(reverse_lazy('active-tasks-list'))


class CancelOrder(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        order = SBCOrder.objects.get(id=kwargs.get('order_id'))
        sbc_workers = SBCWorker.objects.filter(sbc_order=order, is_done=False, has_error=False)
        for sbc_worker in sbc_workers:
            sbc_worker.has_error = True
            sbc_worker.must_done = True
            sbc_worker.error_description = 'manual deactivated'
            sbc_worker.save()
            app.control.revoke(sbc_worker.task_id, terminate=True, signal='SIGKILL')
            sbc_worker.fifa_account.active = False
            sbc_worker.fifa_account.login_status = 0
            sbc_worker.fifa_account.driver = False
            sbc_worker.fifa_account.save()

        messages.add_message(self.request, messages.SUCCESS, 'Successful stopped')
        return redirect(reverse_lazy('sbc-orders-list'))


@login_required
def account_healthy_excel(request, order_id):
    order = AccountCheckHealthyOrder.objects.get(id=order_id)
    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = f'attachment; filename="download_{order.file_name}"'
    wb = Workbook()
    ws = wb.active
    worker_list = AccountCheckHealthyWorker.objects.filter(request_order__id=order_id).order_by('id')
    ws.append(
        ['user name', 'password', 'platform', 'running platform', 'app code', 'backup code', 'search number',
         'credit', 'sellable players', 'trade access', 'active', 'is done', 'has error', 'error description',
         'worker error', 'worker status'])
    for item in worker_list:
        account_backup_code = item.fifa_account.account_backup_code.first()
        if account_backup_code:
            backup_code = account_backup_code.backup_code
            app_code = account_backup_code.app_code
        else:
            backup_code = ''
            app_code = ''
        ws.append([item.fifa_account.user_name, item.fifa_account.password, item.fifa_account.platform,
                   item.running_platform,
                   app_code,
                   backup_code,
                   item.fifa_account.account_search.count(), item.fifa_account.credit,
                   item.sellable_players,
                   {'-1': 'None', '0': 'not yet', '1': 'console transfer ban',
                    '2': 'full permision', '3': 'web transfer ban'}.get(item.fifa_account.trade_access or -1),
                   item.fifa_account.active,
                   item.is_done, item.has_error, item.error_description,
                   item.sbc_worker.error_description if item.sbc_worker else '',
                   item.sbc_worker.status if item.sbc_worker else '',
                   ])
    wb.save(response)
    return response


class CheckHealthyListView(RequiredPermissionViewMixin, GenericListView):
    required_permission__ = 'account_check_healthy_workers__read'
    model = AccountCheckHealthyOrder
    table_class = CheckHealthyListTable

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)


class CancelCheckHealthyOrder(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        order = AccountCheckHealthyOrder.objects.get(id=kwargs.get('order_id'))
        accounts_worker = AccountCheckHealthyWorker.objects.filter(request_order=order, is_done=False, has_error=False)
        for account_worker in accounts_worker:
            account_worker.has_error = True
            account_worker.must_done = True
            account_worker.error_description = 'manual deactivated'
            account_worker.save()
            app.control.revoke(account_worker.task_id, terminate=True, signal='SIGKILL')
            account_worker.fifa_account.active = False
            account_worker.fifa_account.login_status = 0
            account_worker.fifa_account.driver = False
            account_worker.fifa_account.save()

        messages.add_message(self.request, messages.SUCCESS, 'Successful stopped')
        return redirect(reverse_lazy('check-healthy-list'))


class CheckHealthyAddFile(LoginRequiredMixin, TemplateView):
    template_name = 'sbc/add_sbc_file.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({'page_header': 'Add SBC File',
                        'columns': ['Email', 'Password', 'Platform', 'App Code', 'Backup Code', 'Running Platform',
                                    'Open Preview Gold Pack', 'Sell Items', 'Sell Club Items', 'Open Packs',
                                    'Create Club', 'Order Active Squad', 'Squad Formation']})
        return context

    def post(self, request, *args, **kwargs):
        sbc_file = request.FILES.get('file')
        request_order = AccountCheckHealthyOrder.objects.create(creator=request.user, file_name=sbc_file.name, status=1)
        wb_obj = openpyxl.load_workbook(sbc_file)
        sheet_obj = wb_obj.active
        max_row = sheet_obj.max_row
        account_counter = 0
        new_worker_counter = 0
        for i in range(2, max_row + 1):
            ea_email = sheet_obj.cell(row=i, column=1).value
            # ea_pass = sheet_obj.cell(row=i, column=2).value
            # platform = sheet_obj.cell(row=i, column=3).value
            # app_code = sheet_obj.cell(row=i, column=4).value
            # backup_code = sheet_obj.cell(row=i, column=5).value
            running_platform = sheet_obj.cell(row=i, column=6).value
            if not running_platform:
                running_platform = 'web'
            open_preview_gold_pack = sheet_obj.cell(row=i, column=7).value
            sell_items = sheet_obj.cell(row=i, column=8).value
            sell_club_items = sheet_obj.cell(row=i, column=9).value
            open_packs = sheet_obj.cell(row=i, column=10).value
            create_club = sheet_obj.cell(row=i, column=11).value
            order_active_squad = sheet_obj.cell(row=i, column=12).value
            order_active_squad_formation = sheet_obj.cell(row=i, column=13).value

            if ea_email:
                account_counter += 1
                try:
                    fifa_account = FifaAccount.objects.get(
                        user_name=ea_email
                    )
                except MultipleObjectsReturned:
                    messages.error(request, f'two account with {ea_email}, fix it first.')
                    break
                except FifaAccount.DoesNotExist:
                    messages.error(request, f'account with email {ea_email} does not exists. add it first.')
                    continue
                # if fifa_account.platform in ['', None]:
                #     fifa_account.platform = platform
                # fifa_account.creator = request.user
                # fifa_account.password = ea_pass
                # fifa_account.save()
                # account_backup, created = FifaAccountBackupCode.objects.get_or_create(fifa_account=fifa_account)
                # account_backup.app_code = app_code
                # account_backup.backup_code = backup_code
                # account_backup.save()

                exist_worker = AccountCheckHealthyWorker.objects.filter(
                    fifa_account=fifa_account, is_done=False, has_error=False, must_done=False).last()
                if not exist_worker:
                    new_worker_counter += 1
                    AccountCheckHealthyWorker.objects.create(
                        fifa_account=fifa_account, request_order=request_order,
                        running_platform=running_platform,
                        open_preview_gold_pack=open_preview_gold_pack,
                        sell_items=sell_items, sell_club_items=sell_club_items, open_packs=open_packs,
                        create_club=create_club, order_active_squad=order_active_squad,
                        order_active_squad_formation=order_active_squad_formation,
                    )

        messages.success(request, f"Check Healthy File added, "
                                  f"rows : {max_row}, "
                                  f"accounts: {account_counter}, "
                                  f"new workers: {new_worker_counter}")
        return HttpResponseRedirect(reverse_lazy('check-healthy-add-file'))


class InvestorPageListView(ConsoleWorkersLogs2ListView):
    required_permission__ = 'investor_log__read'
    table_class = InvestorConsolesListTable
    filterset_class = InvestorPageFilter

    def get_context_data(self, *args, **kwargs):
        if not has_permission_exactly(self.request.user, self.required_permission__all):
            kwargs.update({'filter': None})
        context = super().get_context_data(*args, **kwargs)
        return context

    def get_card_data(self):
        data = super().get_card_data()
        new_data = []
        for item in data:
            if item['name'] not in ['Workers', 'Sum Mule', 'Sum Credit']:
                new_data.append(item)
        query = self.get_queryset()
        console_query = Console.objects.filter(id__in=query.values_list('console__id', flat=True))

        start_date = self.request.GET.get('start_date', None)
        end_date = self.request.GET.get('end_date', None)
        discharge_query_pure = CloseWebAppSnipes.objects.filter(
                first_account__previous_console__in=console_query,
            ).exclude(
                winner_account=None
            )
        discharge_query_mode2_pure = DischargeMode2.objects.filter(
            fifa_account__previous_console__in=console_query,
            status__in=['failed', 'success']
        )
        discharge_query_mode3_pure = CloseWebAppTransfers.objects.filter(
            second_account__previous_console__in=console_query,
            second_side_done=True,
            for_discharge=True
        )
        if start_date and end_date:
            start_date_time = make_aware(timezone.localtime().strptime(unidecode(start_date), '%Y-%m-%d %H:%M'))
            end_date_time = make_aware(timezone.localtime().strptime(unidecode(end_date), '%Y-%m-%d %H:%M'))
            discharge_query = discharge_query_pure.filter(
                insert_time__gt=start_date_time,
                insert_time__lt=end_date_time,
            )
            discharge_query_mode2 = discharge_query_mode2_pure.filter(
                create_time__gt=start_date_time,
                create_time__lt=end_date_time,
            )
            discharge_query_mode3 = discharge_query_mode3_pure.filter(
                create_time__gt=start_date_time,
                create_time__lt=end_date_time,
            )
        else:
            discharge_query = discharge_query_pure
            discharge_query_mode2 = discharge_query_mode2_pure
            discharge_query_mode3 = discharge_query_mode3_pure.filter()

        accounts_credit = console_query.exclude(
            fifaaccount__credit=None
        ).values_list('fifaaccount__credit', flat=True)
        new_data.append({'name': 'Sum Credit',
                         'info': number_convertor_to_milion(sum(accounts_credit)),
                         'box_css_class': 'fw-bold'})

        success_discharge = discharge_query.annotate(
            transfer_coin=(F('player_price') - F('player_min_price_from_futbin')) - (
                    (F('player_price') + F('player_min_price_from_futbin')) * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')

        if not has_permission_exactly(self.request.user, self.required_permission__all):
            discharge_query_mode2 = discharge_query_mode2.filter(
                create_time__gte=make_aware(jdatetime.datetime.today().replace(year=1403, month=7, day=1).togregorian())
            )
        success_discharge_mode2 = discharge_query_mode2.annotate(
            transfer_coin=(F('end_price') - F('avg_price')) - (F('end_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        mydgn_success_discharge_mode2 = discharge_query_mode2.filter(mule__site_name='mydgn').annotate(
            transfer_coin=(F('end_price') - F('avg_price')) - (F('end_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        success_discharge_mode3 = discharge_query_mode3.annotate(
            transfer_coin=(F('buy_now_price') - F('start_price')) - (F('buy_now_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        new_data.append({'name': 'Discharge',
                         'info': f'{number_convertor_to_milion((success_discharge or 0) + (success_discharge_mode2 or 0) + (success_discharge_mode3 or 0))} - {number_convertor_to_milion((success_discharge or 0) + (mydgn_success_discharge_mode2 or 0) + (success_discharge_mode3 or 0))}',
                         'box_css_class': 'fw-bold'})
        success_discharge_mode2_euro = discharge_query_mode2
        if not has_permission_exactly(self.request.user, self.required_permission__all):
            success_discharge_mode2_euro = discharge_query_mode2.filter(
                create_time__gte=make_aware(jdatetime.datetime.today().replace(day=1, hour=0, minute=1).togregorian())
            )
        success_discharge_mode2_euro = success_discharge_mode2_euro.annotate(
            income_credit_float=Cast('income_credit', output_field=FloatField())
        ).aggregate(
            sum_success_discharge=Sum('income_credit_float')
        ).get('sum_success_discharge')
        new_data.append({'name': 'Discharge(euro)',
                         'info': f'{"{:,}".format(int(success_discharge_mode2_euro or 0))}',
                         'box_css_class': 'fw-bold'})
        success_discharge_31_days = CloseWebAppSnipes.objects.filter(
            first_account__previous_console__in=console_query,
            insert_time__gte=make_aware(jdatetime.datetime.today().replace(day=1, hour=0, minute=1).togregorian())
        ).exclude(
            winner_account=None
        ).annotate(
            transfer_coin=(F('player_price') - F('player_min_price_from_futbin')) - (
                    (F('player_price') + F('player_min_price_from_futbin')) * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        success_discharge_mode2_31_days = discharge_query_mode2_pure.filter(
            create_time__gte=make_aware(jdatetime.datetime.today().replace(day=1, hour=0, minute=1).togregorian())
        ).annotate(
            transfer_coin=(F('end_price') - F('avg_price')) - (F('end_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        mydgn_success_discharge_mode2_31_days = discharge_query_mode2_pure.filter(
            mule__site_name='mydgn',
            create_time__gte=make_aware(jdatetime.datetime.today().replace(day=1, hour=0, minute=1).togregorian())
        ).annotate(
            transfer_coin=(F('end_price') - F('avg_price')) - (F('end_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        success_discharge_mode3_31_days = discharge_query_mode3_pure.filter(
            create_time__gte=make_aware(jdatetime.datetime.today().replace(day=1, hour=0, minute=1).togregorian())
        ).annotate(
            transfer_coin=(F('buy_now_price') - F('start_price')) - (F('buy_now_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        new_data.append({'name': 'Month Discharge',
                         'info': f'{number_convertor_to_milion((success_discharge_31_days or 0) + (success_discharge_mode2_31_days or 0) + (success_discharge_mode3_31_days or 0))} - {number_convertor_to_milion((success_discharge_31_days or 0) + (mydgn_success_discharge_mode2_31_days or 0) + (success_discharge_mode3_31_days or 0))}',
                         'box_css_class': 'fw-bold'})
        last_day_of_prev_month = jdatetime.datetime.today().replace(
            day=1, hour=23, minute=1) - jdatetime.timedelta(days=1)
        start_day_of_prev_month = last_day_of_prev_month.replace(day=1, hour=0, minute=1)
        success_discharge_last_month = CloseWebAppSnipes.objects.filter(
            first_account__previous_console__in=console_query,
            insert_time__gte=make_aware(start_day_of_prev_month.togregorian()),
            insert_time__lte=make_aware(last_day_of_prev_month.togregorian()),
        ).exclude(
            winner_account=None
        ).annotate(
            transfer_coin=(F('player_price') - F('player_min_price_from_futbin')) - (
                    (F('player_price') + F('player_min_price_from_futbin')) * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        success_discharge_mode2_last_month = discharge_query_mode2_pure.filter(
            create_time__gte=make_aware(start_day_of_prev_month.togregorian()),
            create_time__lte=make_aware(last_day_of_prev_month.togregorian()),
        ).annotate(
            transfer_coin=(F('end_price') - F('avg_price')) - (F('end_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        mydgn_success_discharge_mode2_last_month = discharge_query_mode2_pure.filter(
            mule__site_name='mydgn',
            create_time__gte=make_aware(start_day_of_prev_month.togregorian()),
            create_time__lte=make_aware(last_day_of_prev_month.togregorian()),
        ).annotate(
            transfer_coin=(F('end_price') - F('avg_price')) - (F('end_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        success_discharge_mode3_last_month = discharge_query_mode3_pure.filter(
            create_time__gte=make_aware(start_day_of_prev_month.togregorian()),
            create_time__lte=make_aware(last_day_of_prev_month.togregorian()),
        ).annotate(
            transfer_coin=(F('buy_now_price') - F('start_price')) - (F('buy_now_price') * .05)
        ).aggregate(
            sum_success_discharge=Sum('transfer_coin')
        ).get('sum_success_discharge')
        new_data.append({'name': 'Pre-Month Discharge',
                         'info': f'{number_convertor_to_milion((success_discharge_last_month or 0) + (success_discharge_mode2_last_month or 0) + (success_discharge_mode3_last_month or 0))} - {number_convertor_to_milion((success_discharge_last_month or 0) + (mydgn_success_discharge_mode2_last_month or 0) + (success_discharge_mode3_last_month or 0))}',
                         'box_css_class': 'fw-bold'})
        return new_data

    def get_queryset(self):
        investor_selected = self.request.GET.get('investor', None)
        is_investor = not has_permission_exactly(self.request.user, self.required_permission__all)
        # if investor_selected or is_investor:
        #     self.only_active_consoles = False
        self.only_active_consoles = False
        return super().get_queryset()

    def get_table_data(self):
        table_data = super().get_table_data()
        start_date = self.request.GET.get('start_date', None)
        end_date = self.request.GET.get('end_date', None)
        for item in table_data:
            item.update({
                'start_date': start_date,
                'end_date': end_date,
            })
        return table_data

    def is_rel(self):
        return has_permission_exactly(self.request.user, self.required_permission__rel)


@csrf_exempt
def solvation_preprocess_view(request):
    if request.method == 'POST':
        request_json = json.loads(request.body.decode("utf-8"))
        solvation_model_id = request_json.get('solvation_model_id')
        json_players_data = request_json.get('json_players_data')
        sbc_number = request_json.get('sbc_number')
        challenge_data = request_json.get('challenge_data')
        required_positions = request_json.get('required_positions')
        if not sbc_number and not solvation_model_id:
            return JsonResponse({
                    'status_bool': False, 'status': 'failed',
                    'solve_status_text': 'solvation_model_id or sbc_number required'},
                    safe=False)
        if not json_players_data:
            return JsonResponse({
                    'status_bool': False, 'status': 'failed',
                    'solve_status_text': 'club players needed'},
                    safe=False)
        if sbc_number:
            solvation_model = create_solvation_instance(
                challenge_data=challenge_data, required_positions=required_positions,
            )
            # solvation_model = SBCSolvationModel.objects.filter(sbc_type__sbc_number=sbc_number).last()
            # if not solvation_model:
            #     return JsonResponse({
            #         'status_bool': False, 'status': 'failed',
            #         'solve_status_text': f'no model found with sbc number {sbc_number}'},
            #         safe=False)
        else:
            solvation_model = SBCSolvationModel.objects.get(id=solvation_model_id)
        solvation = SolvationCore()
        solvation.set_conditions(solvation_model)
        exists_items = pd.DataFrame(convert_club_players_to_solvation_format(json_players_data))
        exists_items.rename(columns=exists_items.iloc[0], inplace=True)
        exists_items.drop(exists_items.index[0], inplace=True)
        data_frame = solvation.preprocess_data_3(exists_items)
        result = data_frame.to_json(orient='records')
        return JsonResponse({
            'status_bool': True, 'status': 'success', 'json_data_frame': result,
            'solvation_instance_dict': model_to_dict(solvation_model),
        }, safe=False)
    else:
        return HttpResponseNotAllowed(['POST'])


@csrf_exempt
def get_solvation_view(request):
    if request.method == 'POST':
        request_json = json.loads(request.body.decode("utf-8"))
        solvation_model_id = request_json.get('solvation_model_id')
        json_players_data = request_json.get('json_players_data')
        fifa_account_id = request_json.get('fifa_account_id')
        sbc_number = request_json.get('sbc_number')
        challenge_data = request_json.get('challenge_data')
        required_positions = request_json.get('required_positions')
        from sbc.tasks import get_solvation
        if not sbc_number and not solvation_model_id:
            return JsonResponse({
                    'status_bool': False, 'status': 'failed',
                    'solve_status_text': 'solvation_model_id or sbc_number required'},
                    safe=False)
        if not json_players_data or json_players_data == str([]):
            return JsonResponse({
                    'status_bool': False, 'status': 'failed',
                    'solve_status_text': 'club players needed'},
                    safe=False)
        if sbc_number:
            solvation_model = create_solvation_instance(
                challenge_data=challenge_data, required_positions=required_positions,
            )
            # solvation_model = json.dumps(model_to_dict(solvation_model))
            # return JsonResponse({
            #             'status_bool': False, 'status': 'failed',
            #             'solve_status_text': f'no model found with sbc number {sbc_number}'},
            #             safe=False)
        else:
            solvation_model = SBCSolvationModel.objects.get(id=solvation_model_id)
            # solvation_model = SBCSolvationModel.objects.filter(sbc_type__sbc_number=sbc_number).last()
            # if not solvation_model:
            #     return JsonResponse({
            #         'status_bool': False, 'status': 'failed',
            #         'solve_status_text': f'no model found with sbc number {sbc_number}'},
            #         safe=False)
            # solvation_model_id = solvation_model.id
        solvation_model = json.dumps(model_to_dict(solvation_model))
        result = get_solvation.delay(solvation_model, json_players_data, fifa_account_id, 290, 'cost').get(timeout=300)
        # result = get_solvation(solvation_model, json_players_data, fifa_account_id, 290, 'cost')
        return JsonResponse(result, safe=False)
    else:
        return HttpResponseNotAllowed(['POST'])


@csrf_exempt
def get_challenge_difficulty(request):
    if request.method == 'POST':
        request_json = json.loads(request.body.decode("utf-8"))
        challenge_data = request_json.get('challenge_data')
        required_positions = request_json.get('required_positions')
        solvation_model = create_solvation_instance(
            challenge_data=challenge_data, required_positions=required_positions,
        )
        return JsonResponse({
            'difficulty_level': solvation_model.difficulty,
            'solvation_instance_dict': model_to_dict(solvation_model),
        }, safe=False)
    else:
        return HttpResponseNotAllowed(['POST'])


def create_solvation_instance(challenge_data, required_positions):

    # todo : fix formation for f433a
    challenge_formation = '-'.join(
        challenge_data.get('formation').replace('f', '')
    ).replace('-a', '[2]').replace('-b', '[3]').replace('-c', '[4]')
    solvation_object = SBCSolvationModel()
    solvation_object.formation = challenge_formation
    solvation_object.difficulty = 0
    solvation_object.num_players = 11
    if required_positions:
        solvation_object.num_players = len(required_positions)
        solvation_object.required_positions = ','.join(map(str, required_positions))
    solvation_object.use_preferred_position = False
    solvation_object.use_alternate_positions = True
    grouped_conditions = {}
    for condition in challenge_data.get('elgReq'):
        slot = condition["eligibilitySlot"]
        if slot not in grouped_conditions:
            grouped_conditions[slot] = []
        grouped_conditions[slot].append(condition)

    readable_requirements = []

    countries_special_names = []
    countries_special_count = []
    leagues_special_names = []
    leagues_special_count = []
    clubs_special_names = []
    clubs_special_count = []

    rarity_2 = []
    num_rarity_2 = []
    min_overall = []
    num_min_overall = []
    group_rarity = []
    num_group_rarity = []
    solvation_object.difficulty = 1
    all_min_max_exactly_dict = {}

    for slot, conditions in grouped_conditions.items():
        scope = next((c for c in conditions if c["type"] == "SCOPE"), None)
        min_max_exactly = scope and scope["eligibilityValue"]  # Min 0 , Max 1 , Exactly 2
        min_max_exactly_text = {0: 'Min', 1: 'Max', 2: 'Exactly'}.get(scope and scope["eligibilityValue"])
        types_list = [kk['type'] for kk in conditions]
        if 'NATION_ID' in types_list:
            special_countries_name = [str(kk.get('eligibilityValue')) for kk in conditions if kk.get('type') == 'NATION_ID']
            special_countries_num = next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None)
            countries_special_names.append(special_countries_name)
            countries_special_count.append(special_countries_num)
            solvation_object.difficulty += 1
        elif 'LEAGUE_ID' in types_list:
            special_leagues_name = [str(kk.get('eligibilityValue')) for kk in conditions if kk.get('type') == 'LEAGUE_ID']
            special_leagues_num = next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None)
            leagues_special_names.append(special_leagues_name)
            leagues_special_count.append(special_leagues_num)
            solvation_object.difficulty += 1
        elif 'CLUB_ID' in types_list:
            special_clubs_name = [str(kk.get('eligibilityValue')) for kk in conditions if kk.get('type') == 'CLUB_ID']
            special_clubs_num = next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None)
            clubs_special_names.append(special_clubs_name)
            clubs_special_count.append(special_clubs_num)
            solvation_object.difficulty += 1
        elif 'SAME_NATION_COUNT' in types_list:
            num_nation = next((c['eligibilityValue'] for c in conditions if c["type"] == "SAME_NATION_COUNT"), None)
            all_min_max_exactly_dict.update({'same_nation_count': num_nation, 'same_nation_type': min_max_exactly})
            if min_max_exactly == 0:
                solvation_object.min_num_country = num_nation
            else:
                solvation_object.max_num_country = num_nation
            solvation_object.difficulty += 1
        elif 'SAME_LEAGUE_COUNT' in types_list:
            num_league = next((c['eligibilityValue'] for c in conditions if c["type"] == "SAME_LEAGUE_COUNT"), None)
            all_min_max_exactly_dict.update({'same_league_count': num_league, 'same_league_type': min_max_exactly})
            if min_max_exactly == 0:
                solvation_object.min_num_league = num_league
            else:
                solvation_object.max_num_league = num_league
            solvation_object.difficulty += 1
        elif 'SAME_CLUB_COUNT' in types_list:
            num_club = next((c['eligibilityValue'] for c in conditions if c["type"] == "SAME_CLUB_COUNT"), None)
            all_min_max_exactly_dict.update({'same_club_count': num_club, 'same_club_type': min_max_exactly})
            if min_max_exactly == 0:
                solvation_object.min_num_club = num_club
            else:
                solvation_object.max_num_club = num_club
            solvation_object.difficulty += 1
        elif 'NATION_COUNT' in types_list:
            uniq_nation_count = next((c['eligibilityValue'] for c in conditions if c["type"] == "NATION_COUNT"), None)
            solvation_object.num_unique_country = str([uniq_nation_count, min_max_exactly_text])
            solvation_object.difficulty += 1
        elif 'LEAGUE_COUNT' in types_list:
            uniq_league_count = next((c['eligibilityValue'] for c in conditions if c["type"] == "LEAGUE_COUNT"), None)
            solvation_object.num_unique_league = str([uniq_league_count, min_max_exactly_text])
            solvation_object.difficulty += 1
        elif 'CLUB_COUNT' in types_list:
            uniq_club_count = next((c['eligibilityValue'] for c in conditions if c["type"] == "CLUB_COUNT"), None)
            solvation_object.num_unique_club = str([uniq_club_count, min_max_exactly_text])
            solvation_object.difficulty += 1
        elif 'PLAYER_QUALITY' in types_list:
            player_quality_code = next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_QUALITY"), None)
            quality_color = {1: 'Bronze', 2: 'Silver', 3: 'Gold'}.get(player_quality_code)
            if quality_color:
                solvation_object.uniq_quality = str([quality_color, min_max_exactly_text])
        elif 'PLAYER_LEVEL' in types_list:
            player_quality_code = next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_LEVEL"), None)
            quality_color = {1: 'Bronze', 2: 'Silver', 3: 'Gold'}.get(player_quality_code)
            if quality_color:
                rarity_2.append([quality_color, min_max_exactly_text])
                num_rarity_2.append(next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None))
            solvation_object.difficulty += 1
        elif 'PLAYER_RARITY_GROUP' in types_list:
            group_rare_id = next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_RARITY_GROUP"), None)
            group_rarity.append([group_rare_id, min_max_exactly_text])
            num_group_rarity.append(next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None))
            solvation_object.difficulty += 1
        elif 'PLAYER_RARITY' in types_list:
            rare_number = next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_RARITY"), None)
            if rare_number == 0:
                rarity_2.append(['Common', min_max_exactly_text])
            elif rare_number == 1:
                rarity_2.append(['Rare', min_max_exactly_text])
            else:
                rarity_2.append([str(rare_number), min_max_exactly_text])
            num_rarity_2.append(next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None))
            solvation_object.difficulty += 1
        elif 'PLAYER_OVERALL_RATING_MIN' in types_list:
            min_overall.append(next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_OVERALL_RATING_MIN"), None))
            num_min_overall.append(next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None))
            solvation_object.difficulty += 1
        elif 'PLAYER_OVERALL_RATING_EXACT' in types_list:
            min_overall.append(next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_OVERALL_RATING_EXACT"), None))
            num_min_overall.append(next((c['eligibilityValue'] for c in conditions if c["type"] == "PLAYER_COUNT"), None))
            solvation_object.difficulty += 1
        elif 'ALL_PLAYERS_CHEMISTRY_POINTS' in types_list:
            solvation_object.chem_per_player = next((c['eligibilityValue'] for c in conditions if c["type"] == "ALL_PLAYERS_CHEMISTRY_POINTS"), 0)
            solvation_object.difficulty += solvation_object.chem_per_player or 0
            if solvation_object.chem_per_player > 0:
                solvation_object.players_in_position = True
        elif 'CHEMISTRY_POINTS' in types_list:
            solvation_object.chemistry = next((c['eligibilityValue'] for c in conditions if c["type"] == "CHEMISTRY_POINTS"), None)
            if solvation_object.chemistry >= 30:
                solvation_object.difficulty += 2
            elif solvation_object.chemistry >= 15:
                solvation_object.difficulty += 1
        elif 'TEAM_RATING_1_TO_100' in types_list:
            solvation_object.squad_rating = next((c['eligibilityValue'] for c in conditions if c["type"] == "TEAM_RATING_1_TO_100"), None)
            solvation_object.difficulty += 1
            # solvation_object.min_rating_players = solvation_object.squad_rating - 4


    if countries_special_names:
        solvation_object.country = str(countries_special_names)
        solvation_object.num_country = str(countries_special_count)
    if leagues_special_names:
        solvation_object.league = str(leagues_special_names)
        solvation_object.num_league = str(leagues_special_count)
    if clubs_special_names:
        solvation_object.club = str(clubs_special_names)
        solvation_object.num_club = str(clubs_special_count)
    if rarity_2:
        solvation_object.rarity_2 = str(rarity_2)
        solvation_object.num_rarity_2 = str(num_rarity_2)
    if min_overall:
        solvation_object.min_overall = str(min_overall)
        solvation_object.num_min_overall = str(num_min_overall)
    if group_rarity:
        solvation_object.group_rarity = str(group_rarity)
        solvation_object.num_group_rarity = str(num_group_rarity)

    if solvation_object.num_players == all_min_max_exactly_dict.get('same_nation_count') and all_min_max_exactly_dict.get('same_nation_type', -1) == 2:
        solvation_object.max_num_country = 0
        solvation_object.min_num_country = solvation_object.num_players
    if solvation_object.num_players == all_min_max_exactly_dict.get('same_league_count') and all_min_max_exactly_dict.get('same_league_type', -1) == 2:
        solvation_object.max_num_league = 0
        solvation_object.min_num_league = solvation_object.num_players
    if solvation_object.num_players == all_min_max_exactly_dict.get('same_club_count') and all_min_max_exactly_dict.get('same_club_type', -1) == 2:
        solvation_object.max_num_club = 0
        solvation_object.min_num_club = solvation_object.num_players

    # this bug from ea , for some special sbcs
    if solvation_object.num_players < 11 and solvation_object.squad_rating:
        solvation_object.squad_rating = solvation_object.squad_rating + 2

    return solvation_object


class SBCProcessDoneListView(GenericListView):
    model = SBCProcess
    table_class = SBCProcessDoneListTable

    def get_table_data(self):
        queryset = (
            SBCType.objects
            .filter(must_done=1)
            .order_by('id')
            .annotate(
                done_process_count=Count(
                    'sbcprocess__worker__fifa_account',
                    distinct=True,
                    filter=Q(sbcprocess__is_done=True, sbcprocess__has_error=False)
                )
            )
        )

        data = []
        for sbc in queryset:
            expire_time = (
                timezone.localtime(sbc.expire_time).strftime("%Y-%m-%d")
                if sbc.expire_time else "-"
            )
            data.append({
                'sbc_number': sbc.sbc_number,
                'sbc_name': sbc.name,
                'done_process': f'{sbc.done_process_count:,}',
                'expire_time': expire_time
            })

        return data
