from db import get_connection
from repositories.match_view_repository import get_match_lineups_grouped
from repositories.match_coach_repository import get_match_coaches_grouped


def replace_match_lineups(match_id: int, rows: list[dict]) -> None:
    delete_query = "DELETE FROM match_lineups WHERE match_id = %s;"
    insert_query = """
    INSERT INTO match_lineups (
        match_id,
        team_id,
        player_id,
        player_name,
        number,
        position,
        is_captain,
        lineup_type,
        source,
        created_at,
        updated_at
    )
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW());
    """

    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(delete_query, (match_id,))
            for row in rows:
                cur.execute(
                    insert_query,
                    (
                        row["match_id"],
                        row["team_id"],
                        row.get("player_id"),
                        row["player_name"],
                        row.get("number"),
                        row.get("position"),
                        row.get("is_captain"),
                        row["lineup_type"],
                        row.get("source", "parser"),
                    ),
                )
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()


def _player_to_editor_dict(p: dict) -> dict:
    return {
        "player_id": p.get("player_id"),
        "player_name": p.get("player_name")
        or f"{p.get('last_name', '')} {p.get('first_name', '')}".strip(),
        "last_name": p.get("last_name", "") or p.get("player_name", "") or "",
        "first_name": p.get("first_name", "") or "",
        "number": str(p.get("number", "") or ""),
        "position": p.get("position", "") or "",
        "is_captain": bool(p.get("is_captain")),
    }


def _coach_to_editor_dict(c: dict) -> dict:
    return {
        "coach_id": c.get("coach_id"),
        "coach_name": c.get("coach_name", "") or "",
        "role": c.get("role", "") or "",
    }


def get_match_lineup_for_editor(
    match_id: int,
    home_team_id: int,
    away_team_id: int,
) -> dict:
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT
                    mlp.side,
                    mlp.role,
                    mlp.sort_order,
                    p.id AS player_id,
                    COALESCE(p.full_name, TRIM(COALESCE(p.last_name, '') || ' ' || COALESCE(p.first_name, ''))) AS player_name,
                    COALESCE(p.last_name, '') AS last_name,
                    COALESCE(p.first_name, '') AS first_name,
                    COALESCE(mlp.number::text, '') AS number,
                    COALESCE(p.position, '') AS position,
                    COALESCE(mlp.is_captain, FALSE) AS is_captain
                FROM match_lineup_players mlp
                JOIN players p
                    ON p.id = mlp.player_id
                WHERE mlp.match_id = %s
                ORDER BY mlp.side, mlp.role, mlp.sort_order, mlp.id
                """,
                (match_id,),
            )
            player_rows = cur.fetchall()

            cur.execute(
                """
                SELECT
                    mc.side,
                    mc.sort_order,
                    c.id AS coach_id,
                    COALESCE(c.player, '') AS coach_name,
                    COALESCE(mc.role, c.amplua, '') AS role
                FROM match_coaches mc
                JOIN coaches c
                    ON c.id = mc.coach_id
                WHERE mc.match_id = %s
                ORDER BY mc.side, mc.sort_order, mc.id
                """,
                (match_id,),
            )
            coach_rows = cur.fetchall()
    finally:
        conn.close()

    result = {
        "home_starting": [],
        "home_bench": [],
        "away_starting": [],
        "away_bench": [],
        "home_coaches": [],
        "away_coaches": [],
    }

    # Если редактор уже сохранял состав — берём игроков из новой таблицы
    if player_rows:
        for row in player_rows:
            player = {
                "player_id": row[3],
                "player_name": row[4] or "",
                "last_name": row[5] or "",
                "first_name": row[6] or "",
                "number": row[7] or "",
                "position": row[8] or "",
                "is_captain": bool(row[9]),
            }

            side = row[0]
            role = row[1]

            if side == "home" and role == "starting":
                result["home_starting"].append(player)
            elif side == "home" and role == "bench":
                result["home_bench"].append(player)
            elif side == "away" and role == "starting":
                result["away_starting"].append(player)
            elif side == "away" and role == "bench":
                result["away_bench"].append(player)
    else:
        # Иначе берём загруженный с сайта состав из старой таблицы
        lineups = get_match_lineups_grouped(
            match_id=match_id,
            home_team_id=home_team_id,
            away_team_id=away_team_id,
        )

        result["home_starting"] = [
            _player_to_editor_dict(p) for p in lineups.get("home_starting", [])
        ]
        result["home_bench"] = [
            _player_to_editor_dict(p) for p in lineups.get("home_bench", [])
        ]
        result["away_starting"] = [
            _player_to_editor_dict(p) for p in lineups.get("away_starting", [])
        ]
        result["away_bench"] = [
            _player_to_editor_dict(p) for p in lineups.get("away_bench", [])
        ]

    # Тренеров берём из match_coaches, если они уже есть
    if coach_rows:
        for row in coach_rows:
            coach = {
                "coach_id": row[2],
                "coach_name": row[3] or "",
                "role": row[4] or "",
            }

            side = row[0]
            if side == "home":
                result["home_coaches"].append(coach)
            elif side == "away":
                result["away_coaches"].append(coach)
    else:
        coaches = get_match_coaches_grouped(
            match_id=match_id,
            home_team_id=home_team_id,
            away_team_id=away_team_id,
        )

        result["home_coaches"] = [
            _coach_to_editor_dict(c) for c in coaches.get("home", [])
        ]
        result["away_coaches"] = [
            _coach_to_editor_dict(c) for c in coaches.get("away", [])
        ]
        
    return result

def get_match_lineup_for_vmix(
    match_id: int,
    home_team_id: int,
    away_team_id: int,
) -> dict:
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            # Сначала пробуем взять ручную версию из редактора
            cur.execute(
                """
                SELECT
                    mlp.side,
                    mlp.role,
                    mlp.sort_order,
                    p.id AS player_id,
                    COALESCE(
                        p.full_name,
                        TRIM(COALESCE(p.last_name, '') || ' ' || COALESCE(p.first_name, ''))
                    ) AS player_name,
                    COALESCE(p.last_name, '') AS last_name,
                    COALESCE(p.first_name, '') AS first_name,
                    COALESCE(mlp.number::text, '') AS number,
                    COALESCE(p.position, '') AS position,
                    COALESCE(mlp.is_captain, FALSE) AS is_captain,
                    COALESCE(p.position, '') AS pos
                FROM match_lineup_players mlp
                JOIN players p
                    ON p.id = mlp.player_id
                WHERE mlp.match_id = %s
                ORDER BY
                    CASE
                        WHEN LOWER(COALESCE(p.position, '')) IN ('вр', 'вр.', 'gk', 'goalkeeper', 'вратарь') THEN 0
                        ELSE 1
                    END,
                    CASE
                        WHEN COALESCE(p.number::text, '') ~ '^[0-9]+$' THEN p.number::integer
                        ELSE 999
                    END,
                    COALESCE(p.last_name, ''),
                    COALESCE(p.first_name, ''),
                    p.id
                """,
                (match_id,),
            )
            player_rows = cur.fetchall()

            cur.execute(
                """
                SELECT
                    mc.side,
                    mc.sort_order,
                    c.id AS coach_id,
                    COALESCE(c.player, '') AS coach_name,
                    COALESCE(mc.role, c.amplua, '') AS role
                FROM match_coaches mc
                JOIN coaches c
                    ON c.id = mc.coach_id
                WHERE mc.match_id = %s
                ORDER BY mc.side, mc.sort_order, mc.id
                """,
                (match_id,),
            )
            coach_rows = cur.fetchall()
    finally:
        conn.close()

    result = {
        "home_starting": [],
        "home_bench": [],
        "away_starting": [],
        "away_bench": [],
        "home_coaches": [],
        "away_coaches": [],
    }

    # 1. Если есть ручной состав — берём его
    if player_rows:
        for row in player_rows:
            player = {
                "player_id": row[3],
                "player_name": row[4] or "",
                "last_name": row[5] or "",
                "first_name": row[6] or "",
                "number": row[7] or "",
                "position": row[8] or "",
                "is_captain": bool(row[9]),
                "pos": row[10] or "",
            }

            side = row[0]
            role = row[1]

            if side == "home" and role == "starting":
                result["home_starting"].append(player)
            elif side == "home" and role == "bench":
                result["home_bench"].append(player)
            elif side == "away" and role == "starting":
                result["away_starting"].append(player)
            elif side == "away" and role == "bench":
                result["away_bench"].append(player)

    else:
        # 2. Иначе — fallback на сайт
        lineups = get_match_lineups_grouped(
            match_id=match_id,
            home_team_id=home_team_id,
            away_team_id=away_team_id,
        )

        result["home_starting"] = lineups.get("home_starting", [])
        result["home_bench"] = lineups.get("home_bench", [])
        result["away_starting"] = lineups.get("away_starting", [])
        result["away_bench"] = lineups.get("away_bench", [])

    if coach_rows:
        for row in coach_rows:
            coach = {
                "coach_id": row[2],
                "coach_name": row[3] or "",
                "role": row[4] or "",
            }

            if row[0] == "home":
                result["home_coaches"].append(coach)
            elif row[0] == "away":
                result["away_coaches"].append(coach)
    else:
        coaches = get_match_coaches_grouped(
            match_id=match_id,
            home_team_id=home_team_id,
            away_team_id=away_team_id,
        )
        result["home_coaches"] = coaches.get("home", [])
        result["away_coaches"] = coaches.get("away", [])

    return result

def save_match_lineup_for_editor(
    match_id: int,
    home_team_id: int,
    away_team_id: int,
    home_starting: list[dict],
    home_bench: list[dict],
    away_starting: list[dict],
    away_bench: list[dict],
    home_coaches: list[dict],
    away_coaches: list[dict],
) -> None:
    def is_goalkeeper(position: str) -> bool:
        if not position:
            return False
        return str(position).strip().lower() in {
            "вр", "вр.", "вратарь", "gk", "goalkeeper"
        }

    def safe_number(value) -> int:
        try:
            return int(str(value).strip())
        except Exception:
            return 9999

    def lineup_sort_key(player: dict):
        return (
            0 if is_goalkeeper(player.get("position", "")) else 1,
            safe_number(player.get("number")),
            (player.get("last_name") or player.get("player_name") or "").lower(),
            (player.get("first_name") or "").lower(),
            player.get("player_id") or 0,
        )

    # Пересортировка перед сохранением
    home_starting = sorted(home_starting, key=lineup_sort_key)
    home_bench = sorted(home_bench, key=lineup_sort_key)
    away_starting = sorted(away_starting, key=lineup_sort_key)
    away_bench = sorted(away_bench, key=lineup_sort_key)

    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,),
            )

            def insert_players(side: str, role: str, players: list[dict]) -> None:
                for sort_order, p in enumerate(players, start=1):
                    cur.execute(
                        """
                        INSERT INTO match_lineup_players (
                            match_id,
                            side,
                            role,
                            sort_order,
                            player_id,
                            number,
                            position,
                            is_captain
                        )
                        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
                        """,
                        (
                            match_id,
                            side,
                            role,
                            sort_order,
                            p.get("player_id"),
                            p.get("number", "") or None,
                            p.get("position", "") or None,
                            bool(p.get("is_captain")),
                        ),
                    )

            def insert_coaches(side: str, coaches: list[dict]) -> None:
                for sort_order, c in enumerate(coaches, start=1):
                    cur.execute(
                        """
                        INSERT INTO match_coaches (
                            match_id,
                            side,
                            sort_order,
                            coach_id,
                            role
                        )
                        VALUES (%s, %s, %s, %s, %s)
                        """,
                        (
                            match_id,
                            side,
                            sort_order,
                            c.get("coach_id"),
                            c.get("role", "") or None,
                        ),
                    )

            insert_players("home", "starting", home_starting)
            insert_players("home", "bench", home_bench)
            insert_players("away", "starting", away_starting)
            insert_players("away", "bench", away_bench)

            insert_coaches("home", home_coaches)
            insert_coaches("away", away_coaches)

        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()
