import random
from datetime import datetime
from typing import List, Optional

from sqlmodel import or_, select

from config.notif_config import NotifConfig
from src.api.fixtures_client import FixturesClient
from src.db.db_manager import NotifierDBManager
from src.db.notif_sql_models import Fixture as DBFixture
from src.db.notif_sql_models import League as DBLeague
from src.db.notif_sql_models import Team as DBTeam
from src.emojis import Emojis
from src.entities import Fixture, TeamStanding
from src.senders.email_sender import send_email_html
from src.senders.telegram_sender import send_telegram_message
from src.utils.date_utils import get_date_spanish_text_format
from src.utils.fixtures_utils import (
    get_image_search,
    get_last_fixture,
    get_last_fixture_db,
    get_next_fixture,
    get_next_fixture_db,
    get_youtube_highlights_videos,
)
from src.utils.message_utils import (
    get_first_phrase_msg,
    get_team_intro_message,
    is_subscripted_for_team,
)


class TeamFixturesManager:
    def __init__(self, season: str, team_id: str) -> None:
        self._season = season
        self._team_id = team_id
        self._fixtures_client = FixturesClient()
        self._notifier_db_manager = NotifierDBManager()

    def get_next_team_fixture_text(self, user: str = "") -> tuple:
        next_team_fixture = self.get_next_team_fixture()
        return (
            self._telegram_next_fixture_notification(next_team_fixture, True, user)
            if next_team_fixture
            else ("Fixture para el equipo no encontrado", "")
        )

    def get_last_team_fixture_text(self, user: str = "") -> tuple:
        last_team_fixture = self.get_last_team_fixture()
        return (
            self._telegram_last_fixture_notification(last_team_fixture, user)
            if last_team_fixture
            else ("Fixture para el equipo no encontrado", "")
        )

    def get_next_team_fixture(self) -> Optional[Fixture]:
        fixtures_statement = select(DBFixture).where(
            or_(
                DBFixture.home_team == self._team_id,
                DBFixture.away_team == self._team_id,
            )
        )
        team_fixtures = self._notifier_db_manager.select_records(fixtures_statement)

        next_team_fixture = None

        if len(team_fixtures):
            next_team_fixture = get_next_fixture_db(team_fixtures)

        return next_team_fixture

    def notify_next_fixture_db(self) -> None:
        next_team_fixture = self.get_next_team_fixture()

        if next_team_fixture:
            if next_team_fixture.remaining_time().days < NotifConfig.NEXT_MATCH_THRESHOLD:
                self._perform_fixture_notification(next_team_fixture)

    def notify_next_fixture(self) -> None:
        team_fixtures = self._fixtures_client.get_fixtures_by(
            self._season, self._team_id
        )

        next_team_fixture = None

        if "response" in team_fixtures.as_dict:
            next_team_fixture = get_next_fixture(
                team_fixtures.as_dict["response"], self._team_id
            )

        if next_team_fixture:
            if next_team_fixture.remaining_time().days < 500:
                self._perform_fixture_notification(next_team_fixture)

    def notify_fixture_line_up_update(self) -> None:
        team_fixtures = self._fixtures_client.get_fixtures_by(
            self._season, self._team_id
        )

        next_team_fixture = None

        if "response" in team_fixtures.as_dict:
            next_team_fixture = get_next_fixture(
                team_fixtures.as_dict["response"], self._team_id
            )

        if next_team_fixture:
            if (
                next_team_fixture.remaining_time().days < 1
                and next_team_fixture.remaining_time().hours < 6
                and next_team_fixture.line_up
            ):
                self._perform_line_up_confirmed_notification(next_team_fixture)
            else:
                print(
                    f"There is still no line up for the match of {next_team_fixture.home_team} vs {next_team_fixture.away_team}"
                )
                print(str(next_team_fixture.remaining_time()))

    def get_last_team_fixture(self) -> Optional[Fixture]:
        fixtures_statement = 