from pandera.pandas import Column, DataFrameSchema

from chickenstats.chicken_nhl._validation_utils import pydantic_to_pandera
from chickenstats.chicken_nhl.validation_pydantic import PBPEvent

# Auto-generated from PBPEvent — all integers use pandas nullable Int64 dtype
pbp_pandera_pandas = pydantic_to_pandera(PBPEvent, engine="pandas")

# Hand-written schemas below cannot be derived from a single Pydantic model — keep as-is

# Pandera schema for xG data (has extra columns beyond XGFields and required=False semantics)
xg_pandera_pandas = DataFrameSchema(
    columns={
        "season": Column(int),
        "goal": Column(int),
        "period": Column(int),
        "period_seconds": Column(int),
        "score_diff": Column(int),
        "danger": Column(int, default=0),
        "high_danger": Column(int, default=0),
        "position_f": Column(int, default=0),
        "position_d": Column(int, default=0),
        "position_g": Column(int, default=0),
        "event_distance": Column(float),
        "event_angle": Column(float, nullable=True),
        # "forwards_percent": Column(float, nullable=True),
        # "forwards_count": Column(int),
        # "opp_forwards_percent": Column(float, nullable=True),
        # "opp_forwards_count": Column(int),
        "is_rebound": Column(int, default=0),
        "rush_attempt": Column(int, default=0),
        "is_home": Column(int, default=0),
        "seconds_since_last": Column(float, nullable=True),
        "distance_from_last": Column(float, nullable=True),
        "prior_shot_same": Column(int, default=0),
        "prior_miss_same": Column(int, default=0),
        "prior_block_same": Column(int, default=0),
        "prior_give_same": Column(int, default=0),
        "prior_take_same": Column(int, default=0),
        "prior_hit_same": Column(int, default=0),
        "prior_shot_opp": Column(int, default=0),
        "prior_miss_opp": Column(int, default=0),
        "prior_block_opp": Column(int, default=0),
        "prior_give_opp": Column(int, default=0),
        "prior_take_opp": Column(int, default=0),
        "prior_hit_opp": Column(int, default=0),
        "prior_face": Column(int, default=0),
        "backhand": Column(int, default=0),
        "bat": Column(int, default=0),
        "between_legs": Column(int, default=0),
        "cradle": Column(int, default=0),
        "deflected": Column(int, default=0),
        "poke": Column(int, default=0),
        "slap": Column(int, default=0),
        "snap": Column(int, default=0),
        "tip_in": Column(int, default=0),
        "wrap_around": Column(int, default=0),
        "wrist": Column(int, default=0),
        "strength_state_3v3": Column(int, required=False),
        "strength_state_4v4": Column(int, required=False),
        "strength_state_5v5": Column(int, required=False),
        "strength_state_3v4": Column(int, required=False),
        "strength_state_3v5": Column(int, required=False),
        "strength_state_4v5": Column(int, required=False),
        "strength_state_4v3": Column(int, required=False),
        "strength_state_5v3": Column(int, required=False),
        "strength_state_5v4": Column(int, required=False),
        "strength_state_Ev3": Column(int, required=False),
        "strength_state_Ev4": Column(int, required=False),
        "strength_state_Ev5": Column(int, required=False),
        "strength_state_3vE": Column(int, required=False),
        "strength_state_4vE": Column(int, required=False),
        "strength_state_5vE": Column(int, required=False),
    },
    strict="filter",
    add_missing_columns=True,
    coerce=True,
    ordered=True,
)

# Column order
column_order = [
    "season",
    "session",
    "game_id",
    "game_date",
    "player",
    "eh_id",
    "api_id",
    "position",
    "team",
    "opp_team",
    "strength_state",
    "period",
    "score_state",
    "forwards",
    "forwards_eh_id",
    "forwards_api_id",
    "defense",
    "defense_eh_id",
    "defense_api_id",
    "own_goalie",
    "own_goalie_eh_id",
    "own_goalie_api_id",
    "opp_forwards",
    "opp_forwards_eh_id",
    "opp_forwards_api_id",
    "opp_defense",
    "opp_defense_eh_id",
    "opp_defense_api_id",
    "opp_goalie",
    "opp_goalie_eh_id",
    "opp_goalie_api_id",
    "toi",
    "g",
    "g_adj",
    "ihdg",
    "a1",
    "a2",
    "ixg",
    "ixg_adj",
    "isf",
    "isf_adj",
    "ihdsf",
    "imsf",
    "imsf_adj",
    "ihdm",
    "iff",
    "iff_adj",
    "ihdf",
    "isb",
    "isb_adj",
    "icf",
    "icf_adj",
    "ibs",
    "ibs_adj",
    "igive",
    "itake",
    "ihf",
    "iht",
    "ifow",
    "ifol",
    "iozfw",
    "iozfl",
    "inzfw",
    "inzfl",
    "idzfw",
    "idzfl",
    "a1_xg",
    "a2_xg",
    "ipent0",
    "ipent2",
    "ipent4",
    "ipent5",
    "ipent10",
    "ipend0",
    "ipend2",
    "ipend4",
    "ipend5",
    "ipend10",
    "gf",
    "ga",
    "gf_adj",
    "ga_adj",
    "hdgf",
    "hdga",
    "xgf",
    "xga",
    "xgf_adj",
    "xga_adj",
    "sf",
    "sa",
    "sf_adj",
    "sa_adj",
    "hdsf",
    "hdsa",
    "ff",
    "fa",
    "ff_adj",
    "fa_adj",
    "hdff",
    "hdfa",
    "cf",
    "ca",
    "cf_adj",
    "ca_adj",
    "bsf",
    "bsa",
    "bsf_adj",
    "bsa_adj",
    "msf",
    "msa",
    "msf_adj",
    "msa_adj",
    "hdmsf",
    "hdmsa",
    "teammate_block",
    "teammate_block_adj",
    "hf",
    "ht",
    "give",
    "take",
    "ozf",
    "nzf",
    "dzf",
    "fow",
    "fol",
    "ozfw",
    "ozfl",
    "nzfw",
    "nzfl",
    "dzfw",
    "dzfl",
    "pent0",
    "pent2",
    "pent4",
    "pent5",
    "pent10",
    "pend0",
    "pend2",
    "pend4",
    "pend5",
    "pend10",
    "ozs",
    "nzs",
    "dzs",
    "otf",
    "g_p60",
    "g_adj_p60",
    "ihdg_p60",
    "a1_p60",
    "a2_p60",
    "ixg_p60",
    "ixg_adj_p60",
    "isf_p60",
    "isf_adj_p60",
    "ihdsf_p60",
    "imsf_p60",
    "imsf_adj_p60",
    "ihdm_p60",
    "iff_p60",
    "iff_adj_p60",
    "ihdf_p60",
    "isb_p60",
    "isb_adj_p60",
    "icf_p60",
    "icf_adj_p60",
    "ibs_p60",
    "ibs_adj_p60",
    "igive_p60",
    "itake_p60",
    "ihf_p60",
    "iht_p60",
    "a1_xg_p60",
    "a2_xg_p60",
    "ipent0_p60",
    "ipent2_p60",
    "ipent4_p60",
    "ipent5_p60",
    "ipent10_p60",
    "ipend0_p60",
    "ipend2_p60",
    "ipend4_p60",
    "ipend5_p60",
    "ipend10_p60",
    "gf_p60",
    "ga_p60",
    "gf_adj_p60",
    "ga_adj_p60",
    "hdgf_p60",
    "hdga_p60",
    "xgf_p60",
    "xga_p60",
    "xgf_adj_p60",
    "xga_adj_p60",
    "sf_p60",
    "sa_p60",
    "sf_adj_p60",
    "sa_adj_p60",
    "hdsf_p60",
    "hdsa_p60",
    "ff_p60",
    "fa_p60",
    "ff_adj_p60",
    "fa_adj_p60",
    "hdff_p60",
    "hdfa_p60",
    "cf_p60",
    "ca_p60",
    "cf_adj_p60",
    "ca_adj_p60",
    "bsf_p60",
    "bsa_p60",
    "bsf_adj_p60",
    "bsa_adj_p60",
    "msf_p60",
    "msa_p60",
    "msf_adj_p60",
    "msa_adj_p60",
    "hdmsf_p60",
    "hdmsa_p60",
    "teammate_block_p60",
    "teammate_block_adj_p60",
    "hf_p60",
    "ht_p60",
    "give_p60",
    "take_p60",
    "pent0_p60",
    "pent2_p60",
    "pent4_p60",
    "pent5_p60",
    "pent10_p60",
    "pend0_p60",
    "pend2_p60",
    "pend4_p60",
    "pend5_p60",
    "pend10_p60",
    "gf_percent",
    "gf_adj_percent",
    "hdgf_percent",
    "xgf_percent",
    "xgf_adj_percent",
    "sf_percent",
    "sf_adj_percent",
    "hdsf_percent",
    "ff_percent",
    "ff_adj_percent",
    "hdff_percent",
    "cf_percent",
    "cf_adj_percent",
    "bsf_percent",
    "bsf_adj_percent",
    "msf_percent",
    "msf_adj_percent",
    "hdmsf_percent",
    "hf_percent",
    "take_percent",
]


# Function to reorder columns
def reorder_columns(pandera_columns: dict, ordered_columns: list = None) -> dict:
    """Function to reorder pandera columns."""
    if not ordered_columns:
        ordered_columns = column_order

    reordered_columns = {key: pandera_columns[key] for key in ordered_columns if key in pandera_columns}

    return reordered_columns


# Basic info used in all pandera schemas
basic_info = {
    "season": Column(str),
    "session": Column(str),
    "game_id": Column(str, required=False),
    "game_date": Column(str, required=False),
}

# Individual stats columns
ind_stats_info = {
    "player": Column(str),
    "eh_id": Column(str),
    "api_id": Column(int),
    "position": Column(str),
    "team": Column(str),
    "opp_team": Column(str, required=False),
    "strength_state": Column(str, required=False),
    "period": Column(int, required=False),
    "score_state": Column(str, required=False),
    "forwards": Column(str, required=False),
    "forwards_eh_id": Column(str, required=False),
    "forwards_api_id": Column(str, required=False),
    "defense": Column(str, required=False),
    "defense_eh_id": Column(str, required=False),
    "defense_api_id": Column(str, required=False),
    "own_goalie": Column(str, required=False),
    "own_goalie_eh_id": Column(str, required=False),
    "own_goalie_api_id": Column("Int64", required=False, nullable=True),
    "opp_forwards": Column(str, required=False),
    "opp_forwards_eh_id": Column(str, required=False),
    "opp_forwards_api_id": Column(str, required=False),
    "opp_defense": Column(str, required=False),
    "opp_defense_eh_id": Column(str, required=False),
    "opp_defense_api_id": Column(str, required=False),
    "opp_goalie": Column(str, required=False),
    "opp_goalie_eh_id": Column(str, required=False),
    "opp_goalie_api_id": Column("Int64", required=False, nullable=True),
}

ind_stats_columns = {
    "g": Column(int, default=0),
    "g_adj": Column(float, default=0),
    "ihdg": Column(int, default=0),
    "a1": Column(int, default=0),
    "a2": Column(int, default=0),
    "ixg": Column(float, default=0),
    "ixg_adj": Column(float, default=0),
    "isf": Column(int, default=0),
    "isf_adj": Column(float, default=0),
    "ihdsf": Column(int, default=0),
    "imsf": Column(int, default=0),
    "imsf_adj": Column(float, default=0),
    "ihdm": Column(int, default=0),
    "iff": Column(int, default=0),
    "iff_adj": Column(float, default=0),
    "ihdf": Column(int, default=0),
    "isb": Column(int, default=0),
    "isb_adj": Column(float, default=0),
    "icf": Column(int, default=0),
    "icf_adj": Column(float, default=0),
    "ibs": Column(int, default=0),
    "ibs_adj": Column(float, default=0),
    "igive": Column(int, default=0),
    "itake": Column(int, default=0),
    "ihf": Column(int, default=0),
    "iht": Column(int, default=0),
    "ifow": Column(int, default=0),
    "ifol": Column(int, default=0),
    "iozfw": Column(int, default=0),
    "iozfl": Column(int, default=0),
    "inzfw": Column(int, default=0),
    "inzfl": Column(int, default=0),
    "idzfw": Column(int, default=0),
    "idzfl": Column(int, default=0),
    "a1_xg": Column(float, default=0),
    "a2_xg": Column(float, default=0),
    "ipent0": Column(int, default=0),
    "ipent2": Column(int, default=0),
    "ipent4": Column(int, default=0),
    "ipent5": Column(int, default=0),
    "ipent10": Column(int, default=0),
    "ipend0": Column(int, default=0),
    "ipend2": Column(int, default=0),
    "ipend4": Column(int, default=0),
    "ipend5": Column(int, default=0),
    "ipend10": Column(int, default=0),
}

oi_stats_columns = {
    "toi": Column(float, default=0),
    "gf": Column(int, default=0),
    "ga": Column(int, default=0),
    "gf_adj": Column(float, default=0),
    "ga_adj": Column(float, default=0),
    "hdgf": Column(int, default=0),
    "hdga": Column(int, default=0),
    "xgf": Column(float, default=0),
    "xga": Column(float, default=0),
    "xgf_adj": Column(float, default=0),
    "xga_adj": Column(float, default=0),
    "sf": Column(int, default=0),
    "sa": Column(int, default=0),
    "sf_adj": Column(float, default=0),
    "sa_adj": Column(float, default=0),
    "hdsf": Column(int, default=0),
    "hdsa": Column(int, default=0),
    "ff": Column(int, default=0),
    "fa": Column(int, default=0),
    "ff_adj": Column(float, default=0),
    "fa_adj": Column(float, default=0),
    "hdff": Column(int, default=0),
    "hdfa": Column(int, default=0),
    "cf": Column(int, default=0),
    "ca": Column(int, default=0),
    "cf_adj": Column(float, default=0),
    "ca_adj": Column(float, default=0),
    "bsf": Column(int, default=0),
    "bsa": Column(int, default=0),
    "bsf_adj": Column(float, default=0),
    "bsa_adj": Column(float, default=0),
    "msf": Column(int, default=0),
    "msa": Column(int, default=0),
    "msf_adj": Column(float, default=0),
    "msa_adj": Column(float, default=0),
    "hdmsf": Column(int, default=0),
    "hdmsa": Column(int, default=0),
    "teammate_block": Column(int, default=0),
    "teammate_block_adj": Column(float, default=0),
    "hf": Column(int, default=0),
    "ht": Column(int, default=0),
    "give": Column(int, default=0),
    "take": Column(int, default=0),
    "ozf": Column(int, default=0),
    "nzf": Column(int, default=0),
    "dzf": Column(int, default=0),
    "fow": Column(int, default=0),
    "fol": Column(int, default=0),
    "ozfw": Column(int, default=0),
    "ozfl": Column(int, default=0),
    "nzfw": Column(int, default=0),
    "nzfl": Column(int, default=0),
    "dzfw": Column(int, default=0),
    "dzfl": Column(int, default=0),
    "pent0": Column(int, default=0),
    "pent2": Column(int, default=0),
    "pent4": Column(int, default=0),
    "pent5": Column(int, default=0),
    "pent10": Column(int, default=0),
    "pend0": Column(int, default=0),
    "pend2": Column(int, default=0),
    "pend4": Column(int, default=0),
    "pend5": Column(int, default=0),
    "pend10": Column(int, default=0),
    "ozs": Column(int, default=0),
    "nzs": Column(int, default=0),
    "dzs": Column(int, default=0),
    "otf": Column(int, default=0),
}

# Stats per 60 minute columns
p60_columns = {
    "g_p60": Column(float, default=0),
    "g_adj_p60": Column(float, default=0),
    "ihdg_p60": Column(float, default=0),
    "a1_p60": Column(float, default=0),
    "a2_p60": Column(float, default=0),
    "ixg_p60": Column(float, default=0),
    "ixg_adj_p60": Column(float, default=0),
    "isf_p60": Column(float, default=0),
    "isf_adj_p60": Column(float, default=0),
    "ihdsf_p60": Column(float, default=0),
    "imsf_p60": Column(float, default=0),
    "imsf_adj_p60": Column(float, default=0),
    "ihdm_p60": Column(float, default=0),
    "iff_p60": Column(float, default=0),
    "iff_adj_p60": Column(float, default=0),
    "ihdf_p60": Column(float, default=0),
    "isb_p60": Column(float, default=0),
    "isb_adj_p60": Column(float, default=0),
    "icf_p60": Column(float, default=0),
    "icf_adj_p60": Column(float, default=0),
    "ibs_p60": Column(float, default=0),
    "ibs_adj_p60": Column(float, default=0),
    "igive_p60": Column(float, default=0),
    "itake_p60": Column(float, default=0),
    "ihf_p60": Column(float, default=0),
    "iht_p60": Column(float, default=0),
    "a1_xg_p60": Column(float, default=0),
    "a2_xg_p60": Column(float, default=0),
    "ipent0_p60": Column(float, default=0),
    "ipent2_p60": Column(float, default=0),
    "ipent4_p60": Column(float, default=0),
    "ipent5_p60": Column(float, default=0),
    "ipent10_p60": Column(float, default=0),
    "ipend0_p60": Column(float, default=0),
    "ipend2_p60": Column(float, default=0),
    "ipend4_p60": Column(float, default=0),
    "ipend5_p60": Column(float, default=0),
    "ipend10_p60": Column(float, default=0),
    "gf_p60": Column(float, default=0),
    "ga_p60": Column(float, default=0),
    "gf_adj_p60": Column(float, default=0),
    "ga_adj_p60": Column(float, default=0),
    "hdgf_p60": Column(float, default=0),
    "hdga_p60": Column(float, default=0),
    "xgf_p60": Column(float, default=0),
    "xga_p60": Column(float, default=0),
    "xgf_adj_p60": Column(float, default=0),
    "xga_adj_p60": Column(float, default=0),
    "sf_p60": Column(float, default=0),
    "sa_p60": Column(float, default=0),
    "sf_adj_p60": Column(float, default=0),
    "sa_adj_p60": Column(float, default=0),
    "hdsf_p60": Column(float, default=0),
    "hdsa_p60": Column(float, default=0),
    "ff_p60": Column(float, default=0),
    "fa_p60": Column(float, default=0),
    "ff_adj_p60": Column(float, default=0),
    "fa_adj_p60": Column(float, default=0),
    "hdff_p60": Column(float, default=0),
    "hdfa_p60": Column(float, default=0),
    "cf_p60": Column(float, default=0),
    "ca_p60": Column(float, default=0),
    "cf_adj_p60": Column(float, default=0),
    "ca_adj_p60": Column(float, default=0),
    "bsf_p60": Column(float, default=0),
    "bsa_p60": Column(float, default=0),
    "bsf_adj_p60": Column(float, default=0),
    "bsa_adj_p60": Column(float, default=0),
    "msf_p60": Column(float, default=0),
    "msa_p60": Column(float, default=0),
    "msf_adj_p60": Column(float, default=0),
    "msa_adj_p60": Column(float, default=0),
    "hdmsf_p60": Column(float, default=0),
    "hdmsa_p60": Column(float, default=0),
    "teammate_block_p60": Column(float, default=0),
    "teammate_block_adj_p60": Column(float, default=0),
    "hf_p60": Column(float, default=0),
    "ht_p60": Column(float, default=0),
    "give_p60": Column(float, default=0),
    "take_p60": Column(float, default=0),
    "pent0_p60": Column(float, default=0),
    "pent2_p60": Column(float, default=0),
    "pent4_p60": Column(float, default=0),
    "pent5_p60": Column(float, default=0),
    "pent10_p60": Column(float, default=0),
    "pend0_p60": Column(float, default=0),
    "pend2_p60": Column(float, default=0),
    "pend4_p60": Column(float, default=0),
    "pend5_p60": Column(float, default=0),
    "pend10_p60": Column(float, default=0),
}

# For / against percentage columns
percent_columns = {
    "gf_percent": Column(float, default=0),
    "gf_adj_percent": Column(float, default=0),
    "hdgf_percent": Column(float, default=0),
    "xgf_percent": Column(float, default=0),
    "xgf_adj_percent": Column(float, default=0),
    "sf_percent": Column(float, default=0),
    "sf_adj_percent": Column(float, default=0),
    "hdsf_percent": Column(float, default=0),
    "ff_percent": Column(float, default=0),
    "ff_adj_percent": Column(float, default=0),
    "hdff_percent": Column(float, default=0),
    "cf_percent": Column(float, default=0),
    "cf_adj_percent": Column(float, default=0),
    "bsf_percent": Column(float, default=0),
    "bsf_adj_percent": Column(float, default=0),
    "msf_percent": Column(float, default=0),
    "msf_adj_percent": Column(float, default=0),
    "hdmsf_percent": Column(float, default=0),
    "hf_percent": Column(float, default=0),
    "take_percent": Column(float, default=0),
}

# Pandera schema for individual stats
ind_stats_pandera_pandas = DataFrameSchema(
    columns=reorder_columns({**basic_info, **ind_stats_info, **ind_stats_columns}),
    strict="filter",
    add_missing_columns=True,
    coerce=True,
    ordered=True,
)

# Pandera schema for on-ice stats
oi_stats_pandera_pandas = DataFrameSchema(
    columns=reorder_columns({**basic_info, **ind_stats_info, **oi_stats_columns}),
    strict="filter",
    add_missing_columns=True,
    coerce=True,
    ordered=True,
)

# Pandera schema for individual stats, combining individual, on-ice, per 60, and percent for / against stats
stats_pandera_pandas = DataFrameSchema(
    columns=reorder_columns(
        {**basic_info, **ind_stats_info, **ind_stats_columns, **oi_stats_columns, **p60_columns, **percent_columns}
    ),
    strict="filter",
    add_missing_columns=True,
    coerce=True,
    ordered=True,
)

# Info columns specifically for the line stats schema
line_stats_info = [
    "team",
    "opp_team",
    "strength_state",
    "period",
    "score_state",
    "forwards",
    "forwards_eh_id",
    "forwards_api_id",
    "defense",
    "defense_eh_id",
    "defense_api_id",
    "own_goalie",
    "own_goalie_eh_id",
    "own_goalie_api_id",
    "opp_forwards",
    "opp_forwards_eh_id",
    "opp_forwards_api_id",
    "opp_defense",
    "opp_defense_eh_id",
    "opp_defense_api_id",
    "opp_goalie",
    "opp_goalie_eh_id",
    "opp_goalie_api_id",
]

# Collecting line stats info columns from the individual stats info columns
line_stats_info = {key: value for key, value in ind_stats_info.items() if key in line_stats_info}

# Pandera schema for line stats
line_stats_pandera_pandas = DataFrameSchema(
    columns=reorder_columns({**basic_info, **line_stats_info, **oi_stats_columns, **p60_columns, **percent_columns}),
    strict="filter",
    add_missing_columns=True,
    coerce=True,
    ordered=True,
)

# Info columns specifically for the team stats schema
team_stats_info = ["team", "opp_team", "strength_state", "period", "score_state"]

# Collecting team stats info columns from the individual stats info columns
team_stats_info = {key: value for key, value in ind_stats_info.items() if key in team_stats_info}

# Pandera schema for team stats
team_stats_pandera_pandas = DataFrameSchema(
    columns=reorder_columns({**basic_info, **team_stats_info, **oi_stats_columns, **p60_columns, **percent_columns}),
    strict="filter",
    add_missing_columns=True,
    coerce=True,
    ordered=True,
)
