# %%
import os, sys
from dotenv import load_dotenv
load_dotenv()

# %%

if os.environ.get('SERVER', None):
    PROJECT_PATH = '/home/django/leagues/'
else:
    PROJECT_PATH = '/home/md/Work/ligalytics/leagues_stable/'

import os, sys
import json
from numpyencoder import NumpyEncoder


sys.path.insert(0, PROJECT_PATH)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "leagues.settings")
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"

from leagues import settings
# settings.DATABASES['default']['NAME'] = PROJECT_PATH+'/db.sqlite3'
if os.environ.get('SERVER', None):
    settings.DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql'
    settings.DATABASES['default']['HOST'] = '0.0.0.0'
    settings.DATABASES['default']['PORT'] = '5433'
    settings.DATABASES['default']['USER'] = 'leagues_user'
    settings.DATABASES['default']['PASSWORD'] = 'ligalytics'
    settings.DATABASES['default']['NAME'] = 'prod_16'
else:
    settings.DATABASES['default']['NAME'] = PROJECT_PATH+'/db.sqlite3'
    settings.DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql'
    settings.DATABASES['default']['HOST'] = '0.0.0.0'
    settings.DATABASES['default']['PORT'] = '5432'
    settings.DATABASES['default']['USER'] = 'postgres'
    settings.DATABASES['default']['PASSWORD'] = 'secret123'
    settings.DATABASES['default']['NAME'] = 'mypgsqldb'
    settings.DATABASES['default']['ATOMIC_REQUESTS'] = False
    settings.DATABASES['default']['AUTOCOMMIT'] = True
    settings.DATABASES['default']['CONN_MAX_AGE'] = 0
    settings.DATABASES['default']['CONN_HEALTH_CHECKS'] = False
    settings.DATABASES['default']['OPTIONS'] = {}

os.environ["XPRESSDIR"] = "/opt/xpressmp"
os.environ["XPRESS"] = "/opt/xpressmp/bin"
os.environ["LD_LIBRARY_PATH"] = os.environ["XPRESSDIR"] + "/lib"
os.environ["DYLD_LIBRARY_PATH"] = os.environ["XPRESSDIR"] + "/lib"
os.environ["SHLIB_PATH"] = os.environ["XPRESSDIR"] + "/lib"
os.environ["LIBPATH"] = os.environ["XPRESSDIR"] + "/lib"
os.environ["PYTHONPATH"] = os.environ["XPRESSDIR"] + "/lib"
os.environ["CLASSPATH"] = os.environ["XPRESSDIR"] + "/lib/xprs.jar"
os.environ["CLASSPATH"] = os.environ["XPRESSDIR"] + "/lib/xprb.jar" + os.pathsep + os.environ["CLASSPATH"]
os.environ["CLASSPATH"] = os.environ["XPRESSDIR"] + "/lib/xprm.jar" + os.pathsep + os.environ["CLASSPATH"]
os.environ["PATH"] = os.environ["XPRESSDIR"] + "/bin" + os.pathsep + os.environ["PATH"]


import django
django.setup()

from scheduler.models import *
import pulp
from pulp import lpSum, value, XPRESS_PY, GUROBI, PULP_CBC_CMD, XPRESS_PY
from django.db.models import Q
from django.template.loader import render_to_string

from qualifiers.models import *
from common.models import GlobalTeam, GlobalCountry
from scheduler.models import Season, Scenario, Team, DayObj, CountryClash, Country, GameRequirement

from qualifiers.draws import groupTeams, optimize_inversions4
from scheduler.solver.tasks.optimize import optimize
from scheduler.solver.tasks.optimize_submodels import ueluecl24_basicmodell_v2
from scheduler.solver.tasks.optimize_specialmodels import uefa24_conflicts

import random
import time
import json
import csv
import networkx as nx
import matplotlib.pyplot as plt
from datetime import timedelta
from collections import defaultdict
from django.contrib.sessions.models import Session

import xpress as xp


scenario = Scenario.objects.get(id=9704)
season = scenario.season

s2 = scenario.id
user_name = 'md'
user_is_staff = True
runMode = 'New'
localsearch_time = 0
# runMode = "Improve"
# localsearch_time = 60
RUN_ENV = 'local'
SOLVER = 'xpress'


partial_solution = []

scenario_id = s2
solver = SOLVER

# partial_solution = optimize(task=None, s2=s2, user_name=user_name, user_is_staff=user_is_staff,
#                 runMode=runMode, localsearch_time=localsearch_time, RUN_ENV=RUN_ENV, solver=SOLVER)

# %%



# ucl_home, ucl_away, uel_team_ids, uecl_team_ids, all_rounds, ucl_rounds, uel_rounds, uecl_rounds, getDateByIso, home_dict, away_dict, viol_dict, team_pairing, team_pairing_ids = uefa24_conflicts(scenario.id)


# class Struct:
#     def __init__(self, **entries):
#         self.__dict__.update(entries)

# games= [
# "A1 Sevilla FC (ESP) ESP  	 A9 FC Internazionale Milano (ITA) ITA",
# "A1 Sevilla FC (ESP) ESP  	 B5 Borussia Dortmund (GER) GER",
# "A1 Sevilla FC (ESP) ESP  	 C8 Atalanta BC (ITA) ITA",
# "A1 Sevilla FC (ESP) ESP  	 D7 Newcastle United FC (ENG) ENG",
# "A2 FC Barcelona (ESP) ESP  	 A3 Manchester United (ENG) ENG",
# "A2 FC Barcelona (ESP) ESP  	 B1 Arsenal FC (ENG) ENG",
# "A2 FC Barcelona (ESP) ESP  	 C1 GNK Dinamo (CRO) CRO",
# "A2 FC Barcelona (ESP) ESP  	 D3 Royal Antwerp FC (BEL) BEL",
# "A3 Manchester United (ENG) ENG  	 A4 FC Bayern München (GER) GER",
# "A3 Manchester United (ENG) ENG  	 B4 RB Leipzig (GER) GER",
# "A3 Manchester United (ENG) ENG  	 C3 Rangers FC (SCO) SCO",
# "A3 Manchester United (ENG) ENG  	 D4 Molde FK (NOR) NOR",
# "A4 FC Bayern München (GER) GER  	 A2 FC Barcelona (ESP) ESP",
# "A4 FC Bayern München (GER) GER  	 B2 FC Porto (POR) POR",
# "A4 FC Bayern München (GER) GER  	 C2 S.S. Lazio (ITA) ITA",
# "A4 FC Bayern München (GER) GER  	 D1 Real Sociedad de Fútbol (ESP) ESP",
# "A5 Real Madrid CF (ESP) ESP  	 A6 Liverpool FC (ENG) ENG",
# "A5 Real Madrid CF (ESP) ESP  	 B8 SL Benfica (POR) POR",
# "A5 Real Madrid CF (ESP) ESP  	 C9 Stade Rennais FC (FRA) FRA",
# "A5 Real Madrid CF (ESP) ESP  	 D2 RC Lens (FRA) FRA",
# "A6 Liverpool FC (ENG) ENG  	 A7 Paris Saint-Germain (FRA) FRA",
# "A6 Liverpool FC (ENG) ENG  	 B6 FC Shakhtar Donetsk (UKR) UKR",
# "A6 Liverpool FC (ENG) ENG  	 C7 Feyenoord (NED) NED",
# "A6 Liverpool FC (ENG) ENG  	 D6 Celtic FC (SCO) SCO",
# "A7 Paris Saint-Germain (FRA) FRA  	 A5 Real Madrid CF (ESP) ESP",
# "A7 Paris Saint-Germain (FRA) FRA  	 B7 Club Atlético de Madrid (ESP) ESP",
# "A7 Paris Saint-Germain (FRA) FRA  	 C4 AC Milan (ITA) ITA",
# "A7 Paris Saint-Germain (FRA) FRA  	 D5 PFC Ludogorets 1945 (BUL) BUL",
# "A8 Manchester City (ENG) ENG  	 A1 Sevilla FC (ESP) ESP",
# "A8 Manchester City (ENG) ENG  	 B3 SSC Napoli (ITA) ITA",
# "A8 Manchester City (ENG) ENG  	 C5 F.C. Copenhagen (DEN) DEN",
# "A8 Manchester City (ENG) ENG  	 D9 1. FC Union Berlin (GER) GER",
# "A9 FC Internazionale Milano (ITA) ITA  	 A8 Manchester City (ENG) ENG",
# "A9 FC Internazionale Milano (ITA) ITA  	 B9 FC Salzburg (AUT) AUT",
# "A9 FC Internazionale Milano (ITA) ITA  	 C6 FK Crvena zvezda (SRB) SRB",
# "A9 FC Internazionale Milano (ITA) ITA  	 D8 Olympique de Marseille (FRA) FRA",
# "B1 Arsenal FC (ENG) ENG  	 A4 FC Bayern München (GER) GER",
# "B1 Arsenal FC (ENG) ENG  	 B3 SSC Napoli (ITA) ITA",
# "B1 Arsenal FC (ENG) ENG  	 C4 AC Milan (ITA) ITA",
# "B1 Arsenal FC (ENG) ENG  	 D4 Molde FK (NOR) NOR",
# "B2 FC Porto (POR) POR  	 A3 Manchester United (ENG) ENG",
# "B2 FC Porto (POR) POR  	 B1 Arsenal FC (ENG) ENG",
# "B2 FC Porto (POR) POR  	 C3 Rangers FC (SCO) SCO",
# "B2 FC Porto (POR) POR  	 D1 Real Sociedad de Fútbol (ESP) ESP",
# "B3 SSC Napoli (ITA) ITA  	 A1 Sevilla FC (ESP) ESP",
# "B3 SSC Napoli (ITA) ITA  	 B4 RB Leipzig (GER) GER",
# "B3 SSC Napoli (ITA) ITA  	 C1 GNK Dinamo (CRO) CRO",
# "B3 SSC Napoli (ITA) ITA  	 D3 Royal Antwerp FC (BEL) BEL",
# "B4 RB Leipzig (GER) GER  	 A2 FC Barcelona (ESP) ESP",
# "B4 RB Leipzig (GER) GER  	 B2 FC Porto (POR) POR",
# "B4 RB Leipzig (GER) GER  	 C2 S.S. Lazio (ITA) ITA",
# "B4 RB Leipzig (GER) GER  	 D2 RC Lens (FRA) FRA",
# "B5 Borussia Dortmund (GER) GER  	 A6 Liverpool FC (ENG) ENG",
# "B5 Borussia Dortmund (GER) GER  	 B8 SL Benfica (POR) POR",
# "B5 Borussia Dortmund (GER) GER  	 C7 Feyenoord (NED) NED",
# "B5 Borussia Dortmund (GER) GER  	 D6 Celtic FC (SCO) SCO",
# "B6 FC Shakhtar Donetsk (UKR) UKR  	 A5 Real Madrid CF (ESP) ESP",
# "B6 FC Shakhtar Donetsk (UKR) UKR  	 B5 Borussia Dortmund (GER) GER",
# "B6 FC Shakhtar Donetsk (UKR) UKR  	 C9 Stade Rennais FC (FRA) FRA",
# "B6 FC Shakhtar Donetsk (UKR) UKR  	 D8 Olympique de Marseille (FRA) FRA",
# "B7 Club Atlético de Madrid (ESP) ESP  	 A8 Manchester City (ENG) ENG",
# "B7 Club Atlético de Madrid (ESP) ESP  	 B9 FC Salzburg (AUT) AUT",
# "B7 Club Atlético de Madrid (ESP) ESP  	 C8 Atalanta BC (ITA) ITA",
# "B7 Club Atlético de Madrid (ESP) ESP  	 D9 1. FC Union Berlin (GER) GER",
# "B8 SL Benfica (POR) POR  	 A9 FC Internazionale Milano (ITA) ITA",
# "B8 SL Benfica (POR) POR  	 B7 Club Atlético de Madrid (ESP) ESP",
# "B8 SL Benfica (POR) POR  	 C6 FK Crvena zvezda (SRB) SRB",
# "B8 SL Benfica (POR) POR  	 D7 Newcastle United FC (ENG) ENG",
# "B9 FC Salzburg (AUT) AUT  	 A7 Paris Saint-Germain (FRA) FRA",
# "B9 FC Salzburg (AUT) AUT  	 B6 FC Shakhtar Donetsk (UKR) UKR",
# "B9 FC Salzburg (AUT) AUT  	 C5 F.C. Copenhagen (DEN) DEN",
# "B9 FC Salzburg (AUT) AUT  	 D5 PFC Ludogorets 1945 (BUL) BUL",
# "C1 GNK Dinamo (CRO) CRO  	 A1 Sevilla FC (ESP) ESP",
# "C1 GNK Dinamo (CRO) CRO  	 B2 FC Porto (POR) POR",
# "C1 GNK Dinamo (CRO) CRO  	 C2 S.S. Lazio (ITA) ITA",
# "C1 GNK Dinamo (CRO) CRO  	 D4 Molde FK (NOR) NOR",
# "C2 S.S. Lazio (ITA) ITA  	 A3 Manchester United (ENG) ENG",
# "C2 S.S. Lazio (ITA) ITA  	 B1 Arsenal FC (ENG) ENG",
# "C2 S.S. Lazio (ITA) ITA  	 C3 Rangers FC (SCO) SCO",
# "C2 S.S. Lazio (ITA) ITA  	 D2 RC Lens (FRA) FRA",
# "C3 Rangers FC (SCO) SCO  	 A2 FC Barcelona (ESP) ESP",
# "C3 Rangers FC (SCO) SCO  	 B3 SSC Napoli (ITA) ITA",
# "C3 Rangers FC (SCO) SCO  	 C4 AC Milan (ITA) ITA",
# "C3 Rangers FC (SCO) SCO  	 D1 Real Sociedad de Fútbol (ESP) ESP",
# "C4 AC Milan (ITA) ITA  	 A4 FC Bayern München (GER) GER",
# "C4 AC Milan (ITA) ITA  	 B4 RB Leipzig (GER) GER",
# "C4 AC Milan (ITA) ITA  	 C1 GNK Dinamo (CRO) CRO",
# "C4 AC Milan (ITA) ITA  	 D3 Royal Antwerp FC (BEL) BEL",
# "C5 F.C. Copenhagen (DEN) DEN  	 A6 Liverpool FC (ENG) ENG",
# "C5 F.C. Copenhagen (DEN) DEN  	 B7 Club Atlético de Madrid (ESP) ESP",
# "C5 F.C. Copenhagen (DEN) DEN  	 C9 Stade Rennais FC (FRA) FRA",
# "C5 F.C. Copenhagen (DEN) DEN  	 D6 Celtic FC (SCO) SCO",
# "C6 FK Crvena zvezda (SRB) SRB  	 A7 Paris Saint-Germain (FRA) FRA",
# "C6 FK Crvena zvezda (SRB) SRB  	 B5 Borussia Dortmund (GER) GER",
# "C6 FK Crvena zvezda (SRB) SRB  	 C5 F.C. Copenhagen (DEN) DEN",
# "C6 FK Crvena zvezda (SRB) SRB  	 D5 PFC Ludogorets 1945 (BUL) BUL",
# "C7 Feyenoord (NED) NED  	 A8 Manchester City (ENG) ENG",
# "C7 Feyenoord (NED) NED  	 B6 FC Shakhtar Donetsk (UKR) UKR",
# "C7 Feyenoord (NED) NED  	 C6 FK Crvena zvezda (SRB) SRB",
# "C7 Feyenoord (NED) NED  	 D8 Olympique de Marseille (FRA) FRA",
# "C8 Atalanta BC (ITA) ITA  	 A5 Real Madrid CF (ESP) ESP",
# "C8 Atalanta BC (ITA) ITA  	 B8 SL Benfica (POR) POR",
# "C8 Atalanta BC (ITA) ITA  	 C7 Feyenoord (NED) NED",
# "C8 Atalanta BC (ITA) ITA  	 D9 1. FC Union Berlin (GER) GER",
# "C9 Stade Rennais FC (FRA) FRA  	 A9 FC Internazionale Milano (ITA) ITA",
# "C9 Stade Rennais FC (FRA) FRA  	 B9 FC Salzburg (AUT) AUT",
# "C9 Stade Rennais FC (FRA) FRA  	 C8 Atalanta BC (ITA) ITA",
# "C9 Stade Rennais FC (FRA) FRA  	 D7 Newcastle United FC (ENG) ENG",
# "D1 Real Sociedad de Fútbol (ESP) ESP  	 A3 Manchester United (ENG) ENG",
# "D1 Real Sociedad de Fútbol (ESP) ESP  	 B4 RB Leipzig (GER) GER",
# "D1 Real Sociedad de Fútbol (ESP) ESP  	 C1 GNK Dinamo (CRO) CRO",
# "D1 Real Sociedad de Fútbol (ESP) ESP  	 D2 RC Lens (FRA) FRA",
# "D2 RC Lens (FRA) FRA  	 A4 FC Bayern München (GER) GER",
# "D2 RC Lens (FRA) FRA  	 B1 Arsenal FC (ENG) ENG",
# "D2 RC Lens (FRA) FRA  	 C3 Rangers FC (SCO) SCO",
# "D2 RC Lens (FRA) FRA  	 D4 Molde FK (NOR) NOR",
# "D3 Royal Antwerp FC (BEL) BEL  	 A1 Sevilla FC (ESP) ESP",
# "D3 Royal Antwerp FC (BEL) BEL  	 B2 FC Porto (POR) POR",
# "D3 Royal Antwerp FC (BEL) BEL  	 C2 S.S. Lazio (ITA) ITA",
# "D3 Royal Antwerp FC (BEL) BEL  	 D1 Real Sociedad de Fútbol (ESP) ESP",
# "D4 Molde FK (NOR) NOR  	 A2 FC Barcelona (ESP) ESP",
# "D4 Molde FK (NOR) NOR  	 B3 SSC Napoli (ITA) ITA",
# "D4 Molde FK (NOR) NOR  	 C4 AC Milan (ITA) ITA",
# "D4 Molde FK (NOR) NOR  	 D3 Royal Antwerp FC (BEL) BEL",
# "D5 PFC Ludogorets 1945 (BUL) BUL  	 A5 Real Madrid CF (ESP) ESP",
# "D5 PFC Ludogorets 1945 (BUL) BUL  	 B6 FC Shakhtar Donetsk (UKR) UKR",
# "D5 PFC Ludogorets 1945 (BUL) BUL  	 C8 Atalanta BC (ITA) ITA",
# "D5 PFC Ludogorets 1945 (BUL) BUL  	 D7 Newcastle United FC (ENG) ENG",
# "D6 Celtic FC (SCO) SCO  	 A8 Manchester City (ENG) ENG",
# "D6 Celtic FC (SCO) SCO  	 B9 FC Salzburg (AUT) AUT",
# "D6 Celtic FC (SCO) SCO  	 C9 Stade Rennais FC (FRA) FRA",
# "D6 Celtic FC (SCO) SCO  	 D5 PFC Ludogorets 1945 (BUL) BUL",
# "D7 Newcastle United FC (ENG) ENG  	 A9 FC Internazionale Milano (ITA) ITA",
# "D7 Newcastle United FC (ENG) ENG  	 B7 Club Atlético de Madrid (ESP) ESP",
# "D7 Newcastle United FC (ENG) ENG  	 C7 Feyenoord (NED) NED",
# "D7 Newcastle United FC (ENG) ENG  	 D9 1. FC Union Berlin (GER) GER",
# "D8 Olympique de Marseille (FRA) FRA  	 A6 Liverpool FC (ENG) ENG",
# "D8 Olympique de Marseille (FRA) FRA  	 B5 Borussia Dortmund (GER) GER",
# "D8 Olympique de Marseille (FRA) FRA  	 C5 F.C. Copenhagen (DEN) DEN",
# "D8 Olympique de Marseille (FRA) FRA  	 D6 Celtic FC (SCO) SCO",
# "D9 1. FC Union Berlin (GER) GER  	 A7 Paris Saint-Germain (FRA) FRA",
# "D9 1. FC Union Berlin (GER) GER  	 B8 SL Benfica (POR) POR",
# "D9 1. FC Union Berlin (GER) GER  	 C6 FK Crvena zvezda (SRB) SRB",
# "D9 1. FC Union Berlin (GER) GER  	 D8 Olympique de Marseille (FRA) FRA",
# ]

# %%
GameRequirement.objects.filter(scenario=scenario).delete()

teams = Team.objects.filter(season=scenario.season,active=True)

gamereqs = []

team_ids = []
teams_from_pot = {p:teams.filter(pot=p).count() for p in range(1,5)}
home_games_agains_pot = {t:{p:0 for p in range(1,5)} for t in teams}
away_games_agains_pot = {t:{p:0 for p in range(1,5)} for t in teams}
opponents_from_same_country = {t:defaultdict(lambda:0) for t in teams}

teams = Team.objects.filter(season=scenario.season,active=True)
team_ids = []



# for game in games:
#     home,away = game.split('\t')
#     new_home = home[3:].split('(')[0].strip()
#     new_away = away[3:].split('(')[0].strip()
#     # print(new_home,new_away)
#     h = teams.filter(name__icontains=new_home).first()
#     a = teams.filter(name__icontains=new_away).first()
#     if not a or not h:
#         print(new_home,new_away)
#     else:
#         team_ids.append(h.id)
#         team_ids.append(a.id)
       
#     gamereqs.append((h,a))
#     if (a,h) in gamereqs:
#         print("DUPLICATE",h,a)
    
    
    
#     home_games_agains_pot[h][a.pot] += 1
#     away_games_agains_pot[a][h.pot] += 1
#     opponents_from_same_country[h][a.country] += 1
#     opponents_from_same_country[a][h.country] += 1
        
    
#     GameRequirement.objects.create(scenario=scenario,team1=h,team2=a,number=1)
    
    


for file in os.listdir('counterexample'):
    filename = os.fsdecode(file)
    if filename.endswith(".txt"): 
        with open('counterexample/'+filename) as f:
            print(filename)
            games = f.readlines()
            for i, game in enumerate(games):
                parsed_game = [x.strip() for x in game.split("\t")]
                new_home = parsed_game[1].split('(')[0].strip()
                new_away = parsed_game[2].split('(')[0].strip()
                h = teams.filter(name__icontains=new_home).first()
                a = teams.filter(name__icontains=new_away).first()
                            
                if not a or not h:
                    print(a,h)
                else:
                    team_ids.append(h.id)
                    team_ids.append(a.id)
                    
                gamereqs.append((h,a))        
                if (a,h) in gamereqs:
                    print("DUPLICATE",h,a)

                home_games_agains_pot[h][a.pot] += 1
                away_games_agains_pot[a][h.pot] += 1
                opponents_from_same_country[h][a.country] += 1
                opponents_from_same_country[a][h.country] += 1


                GameRequirement.objects.create(scenario=scenario,team1=h,team2=a,number=1)
                
            exit()
                
            for t in teams:
                for p in range(1,5):
                    if home_games_agains_pot[t][p] != 1:
                        print("HOME",t,p)
                    if away_games_agains_pot[t][p] != 1:
                        print("AWAY",t,p)
                for c in opponents_from_same_country[t]:
                    if opponents_from_same_country[t][c] >= 4:
                        print(t,c,opponents_from_same_country[t][c])



            #  MODEL WITH HOME
            model = xp.problem(name='HomeAssignments', sense=xp.minimize)

            rounds = range(1,9)

            x = {}
            home = {}
            for r in rounds:
                for (t1,t2) in gamereqs:
                    x[r,t1.id,t2.id] = xp.var(vartype=xp.binary, name='x_{}_{}_{}'.format(r,t1.id,t2.id))

            model.addVariable(x)

            # each game has to be played
            for (t1,t2) in gamereqs:
                model.addConstraint(xp.Sum([x[r,t1.id,t2.id] for r in rounds]) == 1)
                
            # each team has to play once in each round
            for t in teams:
                for r in rounds:
                    model.addConstraint(xp.Sum([x[r,t.id,t2.id] for t2 in teams if (r,t.id,t2.id) in x.keys()])+xp.Sum([x[r,t2.id,t.id] for t2 in teams if (r,t2.id,t.id) in x.keys()]) == 1)
                
            model.solve()


            print ("model.getProbStatus() ",model.getProbStatus() )
            if model.getProbStatus() != 5:
                print("SOLUTION FOUND")
                for r in rounds:
                    for (t1,t2) in gamereqs:
                        if model.getSolution(x[r,t1.id,t2.id]) > 0.9:
                            print(r,t1,t2)
                        if model.getSolution(x[r,t2.id,t1.id]) > 0.9:
                            print(r,t2,t1)
            
            print("\n\n\n")
    
    
# %%
