from numpy import place

from db import get_connection
from repositories.team_repository import get_team_id_by_external_id
from repositories.stadium_repository import get_or_create_stadium



def upsert_match(
    external_id: str,
    home_team_id: int,
    away_team_id: int,
    match_date=None,
    status: str = "scheduled",
    home_score: int | None = None,
    away_score: int | None = None,
    tour: str | None = None,
    season: str | None = None,
    place: str | None = None,
    stadium_id: int | None = None,
    date_raw: str | None = None,
    score_add: str | None = None,
) -> None:
    query = """
INSERT INTO matches (
    external_id,
    home_team_id,
    away_team_id,
    match_date,
    status,
    home_score,
    away_score,
    tour,
    season,
    place,
    stadium_id,
    date_raw,
    score_add,
    created_at,
    updated_at
)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())
ON CONFLICT (external_id)
DO UPDATE SET
    home_team_id = EXCLUDED.home_team_id,
    away_team_id = EXCLUDED.away_team_id,
    match_date = EXCLUDED.match_date,
    status = EXCLUDED.status,
    home_score = EXCLUDED.home_score,
    away_score = EXCLUDED.away_score,
    tour = EXCLUDED.tour,
    season = EXCLUDED.season,
    place = EXCLUDED.place,
    stadium_id = EXCLUDED.stadium_id,
    date_raw = EXCLUDED.date_raw,
    score_add = EXCLUDED.score_add,
    updated_at = NOW();
    """

    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                query,
                (
                    external_id,
                    home_team_id,
                    away_team_id,
                    match_date,
                    status,
                    home_score,
                    away_score,
                    tour,
                    season,
                    place,
                    stadium_id,
                    date_raw,
                    score_add,
                ),
            )
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()


def upsert_match_by_team_external_ids(
    external_id: str,
    home_team_external_id: str,
    away_team_external_id: str,
    match_date=None,
    status: str = "scheduled",
    home_score: int | None = None,
    away_score: int | None = None,
    tour: str | None = None,
    season: str | None = None,
    place: str | None = None,
    stadium_id: int | None = None,
    date_raw: str | None = None,
    score_add: str | None = None,
) -> None:
    home_team_id = get_team_id_by_external_id(home_team_external_id)
    away_team_id = get_team_id_by_external_id(away_team_external_id)
    stadium_id = get_or_create_stadium(place)

    if home_team_id is None:
        raise ValueError(f"Home team not found by external_id: {home_team_external_id}")

    if away_team_id is None:
        raise ValueError(f"Away team not found by external_id: {away_team_external_id}")

    upsert_match(
        external_id=external_id,
        home_team_id=home_team_id,
        away_team_id=away_team_id,
        match_date=match_date,
        status=status,
        home_score=home_score,
        away_score=away_score,
        tour=tour,
        season=season,
        place=place,
        stadium_id=stadium_id,
        date_raw=date_raw,
        score_add=score_add,
    )


def clear_match_squad_data(match_id: int) -> None:
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute("DELETE FROM match_lineup_players WHERE match_id = %s", (match_id,))
            cur.execute("DELETE FROM match_coaches WHERE match_id = %s", (match_id,))
            cur.execute("DELETE FROM match_lineups WHERE match_id = %s", (match_id,))

            # если есть таблица судей матча
            cur.execute("DELETE FROM match_referees WHERE match_id = %s", (match_id,))

            # если есть матчевые расстановки
            cur.execute("DELETE FROM match_formations WHERE match_id = %s", (match_id,))

        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()
        
        
def get_match_by_external_id(external_id: str):
    query = """
    SELECT id, external_id, home_team_id, away_team_id
    FROM matches
    WHERE external_id = %s
    LIMIT 1;
    """

    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(query, (str(external_id).strip(),))
            return cur.fetchone()
    finally:
        conn.close()


def mark_match_parsed(external_id: str) -> None:
    query = """
    UPDATE matches
    SET parsed = TRUE,
        parse_error = NULL,
        updated_at = NOW()
    WHERE external_id = %s;
    """

    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(query, (str(external_id).strip(),))
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()


def mark_match_parse_error(external_id: str, error_text: str) -> None:
    query = """
    UPDATE matches
    SET parsed = FALSE,
        parse_error = %s,
        updated_at = NOW()
    WHERE external_id = %s;
    """

    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(query, (str(error_text)[:2000], str(external_id).strip()))
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()


def get_tour_schedule_by_match_id(match_id: int) -> list[dict]:
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT m.tour
                FROM matches m
                WHERE m.id = %s
                """,
                (match_id,),
            )
            row = cur.fetchone()
            if not row or not row[0]:
                return []

            tour = row[0]

            cur.execute(
                """
                SELECT
                    m.id,
                    m.external_id,
                    m.match_date,
                    m.place,
                    m.status,
                    m.home_score,
                    m.away_score,
                    ht.name AS home_team_name,
                    at.name AS away_team_name
                FROM matches m
                LEFT JOIN teams ht ON ht.id = m.home_team_id
                LEFT JOIN teams at ON at.id = m.away_team_id
                WHERE m.tour = %s
                ORDER BY
                    m.match_date NULLS LAST,
                    m.id
                """,
                (tour,),
            )
            rows = cur.fetchall()

        return [
            {
                "match_id": r[0],
                "match_external_id": r[1],
                "match_date": r[2],
                "stadium_name": r[3] or "",
                "status": r[4] or "",
                "home_score": r[5],
                "away_score": r[6],
                "home_team_name": r[7] or "",
                "away_team_name": r[8] or "",
            }
            for r in rows
        ]
    finally:
        conn.close()
