"""FBIT Singer tap — extracts financial data from the FBIT REST API."""

from __future__ import annotations

import time
from datetime import date

import requests
from singer_sdk import Stream, Tap
from singer_sdk import typing as th

API_BASE = "https://schools-financial-benchmarking.service.gov.uk/api"
RATE_LIMIT_DELAY = 0.1  # seconds between requests


class FBITFinanceStream(Stream):
    """Stream: School financial benchmarking data."""

    name = "fbit_finance"
    primary_keys = ["urn", "year"]
    replication_key = None

    schema = th.PropertiesList(
        th.Property("urn", th.IntegerType, required=True),
        th.Property("year", th.IntegerType, required=True),
        th.Property("per_pupil_spend", th.NumberType),
        th.Property("staff_cost_pct", th.NumberType),
        th.Property("teacher_cost_pct", th.NumberType),
        th.Property("support_staff_cost_pct", th.NumberType),
        th.Property("premises_cost_pct", th.NumberType),
    ).to_dict()

    def _get_school_urns(self) -> list[int]:
        """Fetch all open school URNs from GIAS to know what to query."""
        import io
        from datetime import timedelta

        import pandas as pd

        base = (
            "https://ea-edubase-api-prod.azurewebsites.net"
            "/edubase/downloads/public/edubasealldata{date}.csv"
        )
        today = date.today()
        url = base.format(date=today.strftime("%Y%m%d"))

        self.logger.info("Fetching URN list from GIAS for FBIT extraction...")
        try:
            resp = requests.get(url, timeout=300)
            # Fall back to yesterday if today's file isn't available
            if resp.status_code == 404:
                yesterday = (today - timedelta(days=1)).strftime("%Y%m%d")
                url = base.format(date=yesterday)
                self.logger.info("Today's GIAS file not available, trying yesterday")
                resp = requests.get(url, timeout=300)
            resp.raise_for_status()
            df = pd.read_csv(
                io.StringIO(resp.text),
                encoding="latin-1",
                usecols=["URN", "EstablishmentStatus (name)"],
                dtype=str,
            )
            df = df[df["EstablishmentStatus (name)"] == "Open"]
            return [int(u) for u in df["URN"].dropna().unique()]
        except Exception as e:
            self.logger.error("Failed to fetch URN list: %s", e)
            return []

    def get_records(self, context):
        urns = self._get_school_urns()
        year = date.today().year - 1

        self.logger.info("Fetching FBIT data for %d schools (year %d)...", len(urns), year)

        for i, urn in enumerate(urns):
            if i % 1000 == 0:
                self.logger.info("  Progress: %d/%d", i, len(urns))

            try:
                resp = requests.get(
                    f"{API_BASE}/schoolFinancialDataObject/{urn}",
                    timeout=10,
                )
                if resp.status_code == 200:
                    data = resp.json()
                    if data:
                        per_pupil = None
                        total_exp = data.get("totalExpenditure")
                        num_pupils = data.get("numberOfPupils")
                        if total_exp and num_pupils:
                            per_pupil = round(total_exp / num_pupils, 2)

                        yield {
                            "urn": urn,
                            "year": year,
                            "per_pupil_spend": per_pupil,
                            "staff_cost_pct": data.get("staffCostPercent"),
                            "teacher_cost_pct": data.get("teachingStaffCostPercent"),
                            "support_staff_cost_pct": data.get("educationSupportStaffCostPercent"),
                            "premises_cost_pct": data.get("premisesStaffCostPercent"),
                        }
            except requests.RequestException:
                pass

            time.sleep(RATE_LIMIT_DELAY)


class TapUKFBIT(Tap):
    """Singer tap for UK FBIT financial data."""

    name = "tap-uk-fbit"

    config_jsonschema = th.PropertiesList(
        th.Property(
            "base_url",
            th.StringType,
            default=API_BASE,
            description="FBIT API base URL",
        ),
    ).to_dict()

    def discover_streams(self):
        return [FBITFinanceStream(self)]


if __name__ == "__main__":
    TapUKFBIT.cli()
