import pandas as pd
from pathlib import Path

class SDF_9_2:

  def __init__(
    self,
    campaign_id     : int,
    advertiser_id   : int,
    io_sdf_csv: str | Path,
    li_sdf_csv: str | Path,
  ):
    self.campaign_id = campaign_id
    self.advertiser_id = advertiser_id

    self.io_df = self._load_csv(io_sdf_csv)
    self.li_df = self._load_csv(li_sdf_csv)

    self._validate_required_columns() # we can remove this if we want

  def _load_csv(self, path: str | Path) -> pd.DataFrame:
    df = pd.read_csv(path)
    df.columns = df.columns.str.strip()
    df = df.dropna(how="all")
    return df

  def _validate_required_columns(self):
    required_io_cols = {"Io Id", "Campaign Id", "Status"}
    required_li_cols = {"Line Item Id", "Io Id", "Status"}

    if not required_io_cols.issubset(self.io_df.columns):
      raise ValueError("IO CSV missing required columns")

    if not required_li_cols.issubset(self.li_df.columns):
      raise ValueError("Line Item CSV missing required columns")

  def get_total_line_items_count_by_io(self, io_id: int) -> int:
    filtered = self.li_df[(self.li_df["Io Id"] == io_id)]
    return len(filtered)

  def get_total_active_line_items_count_by_io(self, io_id: int) -> int:
    filtered = self.li_df[
      (self.li_df["Io Id"] == io_id)
      & (self.li_df["Status"].str.lower() == "active")
    ]
    return len(filtered)

  def get_all_line_items_by_io(self, io_id: int) -> pd.DataFrame:
    return self.li_df[self.li_df["Io Id"] == io_id]

  def get_all_insertion_orders_by_io(self, io_id: int) -> pd.DataFrame:
    return self.io_df[self.io_df["Io Id"] == io_id]

  def get_single_io_by_io(self, io_id: int) -> pd.Series:
    return self.io_df[self.io_df["Io Id"] == io_id].squeeze()

  def get_column_from_li_by_io(self, column: str, default: any, io_id: int) -> float:
    df = self.get_all_line_items_by_io(io_id)
    if column not in df.columns:
      return default
    return self.io_df[column]

  def get_column_from_io_by_io(self, column: str, default: any, io_id: int) -> float:
    df = self.get_all_insertion_orders_by_io(io_id)
    if column not in df.columns:
      return default
    return self.io_df[self.io_df["Io Id"] == io_id][column].item()

  def set_li_by_io(self, key: str, value: any, io_id: int) -> None:
    pass
  
  def set_io_by_io(self, key: str, value: any, io_id: int) -> None:
    pass

  def summary(self):
    return {
      "campaign_id": self.campaign_id,
      "advertiser_id": self.advertiser_id,
      "total_ios": len(self.io_df),
      "total_line_items": len(self.li_df),
    }