import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent))

from main.services.satbots.satbot_priority import SatbotPriority
from main.services.satbots.satbot_state import SatbotState
from main.services.satbots.satbot_type import SatbotType
from datetime import datetime
from dateutil.relativedelta import relativedelta
from app import app
from main.models.users.satbot import Satbot
from main.models.insar.frame import Frame
from setup import DB_SESSION
from config import CONFIG


def get_current_satbots():
    with app.app_context():
        satbots = Satbot.query.filter(((Satbot.state == SatbotState.INITIAL) | 
                                       (Satbot.state == SatbotState.STARTED) |
                                       (Satbot.state == SatbotState.ERROR)), 
                                      Satbot.type == SatbotType.GENERATE_GRID).all()
        
    return satbots

def get_frame(current_frames):
    for database in ['standard', 'rural', 'hr']:
        with DB_SESSION[database].begin() as db_session:
            frame = db_session.query(Frame).filter((Frame.grids_updated_at.is_(None) | 
                                                    (Frame.grids_updated_at < datetime.now() - relativedelta(months=6))),
                                                   ~Frame.id.in_(current_frames[database])).order_by(Frame.id).first()
            
            if frame is not None:
                current_frames[database].append(frame.id)
                return f"{database}-{frame.id}"
            
    return None

def spawn_satbot(current_frames, created_by_id):
    frame_id = get_frame(current_frames)

    if frame_id is None:
        return False

    with DB_SESSION['users'].begin() as db_session:
        encoded_params = Satbot().encoded_parameters({ "frame-id": frame_id })
        satbot = Satbot(type=SatbotType.GENERATE_GRID, 
                        parameters=encoded_params, 
                        state=SatbotState.INITIAL,
                        priority=SatbotPriority.LOW,
                        created_by_id=created_by_id)

        db_session.add(satbot)
        db_session.commit()
        db_session.close()

    print(f"Created Satbot for frame {frame_id}")

    return True

def main(created_by_id):
    current_satbots = get_current_satbots()
    # have to convert to int values to get the comparison to work in tests, for some reason
    count = len([satbot for satbot in current_satbots if satbot.state.value != SatbotState.ERROR.value])
    to_create = CONFIG['satbots']['update_grids_script']['max_satbots'] - count

    if to_create > 0:
        print(f"Creating {to_create} Satbots")
        current_frames = { 'standard': [], 'rural': [], 'hr': [] }
        for satbot in current_satbots:
            database, frame_id = satbot.decoded_parameters['frame-id'].split('-')
            current_frames[database].append(frame_id)

        for _ in range(to_create):
            spawned = spawn_satbot(current_frames, created_by_id)
            if not spawned:
                print(f"No more frames without recent grids")
                break
    else:
        print(f"No Satbots created as the queue already contains the maximum number")

if __name__ == '__main__':
    main(CONFIG['satbots']['update_grids_script']['created_by_id'])