"""
Hamilton module to ingest fight data into FalkorDB.
"""
import falkordb
import pandas as pd
import utils
from hamilton.htypes import Collect, Parallelizable


def raw_total_fight_data() -> pd.DataFrame:
    """Loads the raw fight data"""
    _df = pd.read_csv("../data/raw_total_fight_data.csv", delimiter=";")
    return _df


def transformed_data(raw_total_fight_data: pd.DataFrame) -> pd.DataFrame:
    """Does some light transformation on the data and adds some columns"""
    _df = raw_total_fight_data
    _df.last_round = _df.last_round.astype(int)
    _df.last_round_time = _df.last_round_time.apply(lambda x: utils.time_to_seconds(x))
    _df.date = _df.date.apply(lambda x: utils.date_to_timestamp(x))
    _df["Loser"] = _df.apply(
        lambda x: x["B_fighter"] if x["Winner"] == x["R_fighter"] else x["R_fighter"], axis=1
    )
    return _df


def columns_of_interest() -> list[str]:
    """Returns the columns that we're interested in processing"""
    return [
        "R_fighter",
        "B_fighter",
        #    R_KD, B_KD, R_SIG_STR.,B_SIG_STR.,
        # R_SIG_STR_pct, B_SIG_STR_pct, R_TOTAL_STR., B_TOTAL_STR.,
        # R_TD, B_TD, R_TD_pct, B_TD_pct, R_SUB_ATT, B_SUB_ATT,
        # R_REV, B_REV, R_CTRL, B_CTRL, R_HEAD, B_HEAD, R_BODY,
        # B_BODY, R_LEG, B_LEG, R_DISTANCE, B_DISTANCE, R_CLINCH,
        # B_CLINCH, R_GROUND, B_GROUND, win_by,
        "last_round",
        "last_round_time",
        "Format",
        "Referee",
        "date",
        "location",
        "Fight_type",
        "Winner",
        "Loser",
    ]


def fight(
    transformed_data: pd.DataFrame,
    columns_of_interest: list[str],
) -> Parallelizable[pd.Series]:
    """Enables us to process each fight. We pass in a client along with each row"""
    for _idx, _row in transformed_data[columns_of_interest].iterrows():
        yield _row


def write_to_graph(fight: pd.Series, graph: falkordb.Graph) -> str:
    _row, _graph = fight, graph
    # create referee
    q = "MERGE (:Referee {Name: $name})"
    _graph.query(q, {"name": _row.Referee if isinstance(_row.Referee, str) else ""})

    # create card
    q = "MERGE (c:Card {Date: $date, Location: $location})"
    _graph.query(q, {"date": _row.date, "location": _row.location})

    # create fight
    q = """MATCH (c:Card {Date: $date, Location: $location})
           MATCH (ref:Referee {Name: $referee})
           MATCH (r:Fighter {Name:$R_fighter})
           MATCH (b:Fighter {Name:$B_fighter})
           CREATE (f:Fight)-[:PART_OF]->(c)
           SET f = $fight
           CREATE (f)-[:RED]->(r)
           CREATE (f)-[:BLUE]->(b)
           CREATE (ref)-[:REFEREED]->(f)
           RETURN ID(f)
        """
    f_id = _graph.query(
        q,
        {
            "date": _row.date,
            "location": _row.location,
            "referee": _row.Referee if isinstance(_row.Referee, str) else "",
            "R_fighter": _row.R_fighter,
            "B_fighter": _row.B_fighter,
            "fight": {
                "Last_round": _row.last_round,
                "Last_round_time": _row.last_round_time,
                "Format": _row.Format,
                "Fight_type": _row.Fight_type,
            },
        },
    ).result_set[0][0]

    # mark winner & loser
    q = """MATCH (f:Fight) WHERE ID(f) = $fight_id
           MATCH (l:Fighter {Name:$loser})
           MATCH (w:Fighter {Name:$winner})
           CREATE (w)-[:WON]->(f), (l)-[:LOST]->(f)
        """
    _graph.query(
        q,
        {
            "fight_id": f_id,
            "loser": _row.Loser,
            "winner": _row.Winner if isinstance(_row.Winner, str) else "",
        },
    )
    return "success"


def collect_writes(write_to_graph: Collect[str]) -> int:
    return len(list(write_to_graph))
