# System utilities for path management
import sys
import os
sys.path.append(os.path.abspath(".."))

# Logging configuration
import logging

# Suppress TensorFlow logging and warnings
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
logging.getLogger("tensorflow").setLevel(logging.ERROR)

# Keras model loading utility
from keras.models import load_model  # type: ignore

# Custom race data utility
from fixedData.raceData import getRaceData

# Custom model and loss function
from models.transformer import Transformer
from models.loss import WeightedSequenceLoss

__all__ = ["getData"]

def getData(driverNumber, city):
    """
    Prepares and returns all necessary components for race prediction models

    This function loads pre-trained models, prepares input features for both pit stop
    and compound predictions, loads TFRecord race data, and collects all metadata
    needed for inference

    Parameters:
        driverNumber (int): Numeric identifier of the driver to predict
        city (str): Name of the city where the race takes place

    Returns:
        tuple:
            - data (list): List containing structured race data
            - predictionData (list): Components required for inference including:
                - pitstopModel (Keras model)
                - compoundModel (Keras model)
                - tfRecordFile (str): Path to TFRecord data file
                - year (int): Race year
                - roundNumber (int): Round number in the season
                - driverNumber (int): Driver identifier
                - lapDependentFeaturesPitstop (list): Features used in pit stop prediction
                - nonLapDependentFeaturesPitstop (list): Static features for pit stop model
                - lapDependentFeaturesCompound (list): Features used in compound prediction
                - nonLapDependentFeaturesCompound (list): Static features for compound model
                - maxLaps (int): Maximum number of laps used for padding
                - raceLaps (int): Actual number of laps in the race
                - city (str): Race city name
            - raceStartTime (str): Start time of the race as an ISO 8601 string
    """

    pitstopModel = load_model(f"../models/pitstop.keras")
    compoundModel = load_model(f"../models/compound.keras")

    # General lap-dependent features used for prediction
    sharedLapDependentFeatures = [
        "RPM", "Speed", "Throttle", "Sector1Time", "Sector2Time", "Sector3Time",
        "AirTemp", "Humidity", "Pressure", "Rainfall", "TrackTemp", "TrackStatus",
        "WindDirection", "WindSpeed", "TyreLife", "FreshTyre", "Stint",
        "GapToNext", "GapToLeader", "Position", "LapNumber", "LapTime"
    ]

    # General lap-dependent features used for prediction
    sharedNonLapDependentFeatures = [
        "Driver", "RoundNumber", "Year", "Q1",
        "Q2", "Q3", "Team", "GridPosition", "City"
    ]

    # Lap-dependent features used in the pitstop prediction
    lapDependentFeaturesPitstop = sharedLapDependentFeatures.copy()

    # Non lap-dependent features used in the pitstop prdiction
    nonLapDependentFeaturesPitstop = sharedNonLapDependentFeatures.copy()

    # Lap-dependent features used in the compound prediction
    lapDependentFeaturesCompound = sharedLapDependentFeatures.copy()

    # Non lap-dependent features used in the compound prdiction
    nonLapDependentFeaturesCompound = sharedNonLapDependentFeatures.copy()

    # Maximum laps in a race
    maxLaps = 78

    # Extract the necessary data for the race
    data, year, roundNumber, raceStartTime, raceLaps, filePath = getRaceData(city)

    # Get the file where the data is stored
    tfRecordFile = f"{filePath}.tfrecord"

    # Build the data dictionary
    predictionData = [
            pitstopModel,
            compoundModel,
            tfRecordFile,
            year,
            roundNumber,
            driverNumber,
            lapDependentFeaturesPitstop, 
            nonLapDependentFeaturesPitstop,
            lapDependentFeaturesCompound, 
            nonLapDependentFeaturesCompound,
            maxLaps,
            raceLaps,
            city
        ]

    # Return the necessary data
    return data, predictionData, raceStartTime