from django.core.mail import EmailMessage
from django.utils import timezone
from django.urls import reverse
from enum import Enum

class TeamEmailType(Enum):
    REGISTERED = "registered"
    WAITING_LIST = "waiting_list"
    UNREGISTERED = "unregistered"
    OUT_OF_WAITING_LIST = "out_of_waiting_list"
    TOURNAMENT_CANCELED = "tournament_canceled"
    IN_TOURNAMENT_STRUCTURE = "in_tournament_structure"
    OUT_OF_TOURNAMENT_STRUCTURE = "out_of_tournament_structure"
    OUT_OF_WALKOUT_IS_IN = "out_of_walkout_is_in"
    OUT_OF_WALKOUT_WAITING_LIST = "out_of_walkout_waiting_list"
    WALKOUT = "walkout"
    UNEXPECTED_OUT_OF_TOURNAMENT = 'unexpected_out_of_tournament'

    def email_subject(self) -> str:
            subjects = {
                self.REGISTERED: "Participation confirmée",
                self.WAITING_LIST: "Liste d'attente",
                self.UNREGISTERED: "Désistement",
                self.OUT_OF_WAITING_LIST: "Participation confirmée",
                self.TOURNAMENT_CANCELED: "Tournoi annulé",
                self.IN_TOURNAMENT_STRUCTURE: "Participation confirmée",
                self.OUT_OF_TOURNAMENT_STRUCTURE: "Participation annulée",
                self.OUT_OF_WALKOUT_IS_IN: "Participation confirmée",
                self.OUT_OF_WALKOUT_WAITING_LIST: "Liste d'attente",
                self.WALKOUT: "Participation annulée",
                self.UNEXPECTED_OUT_OF_TOURNAMENT: "Participation annulée",
            }
            return subjects.get(self, "Tournament Notification")

class TournamentEmailService:
    @staticmethod
    def _convert_newlines_to_html(text):
        html_content = text.replace('\n', '<br>')
        return f"""
    <html>
        <body>
            {html_content}
        </body>
    </html>
    """

    @staticmethod
    def email_subject(tournament, topic):
        base_subject = f"[{tournament.build_tournament_type_str()}] [{tournament.formatted_start_date()}] " + topic
        return base_subject

    @staticmethod
    def send_registration_confirmation(request, tournament, team_registration, waiting_list_position):
        if waiting_list_position >= 0:
            TournamentEmailService.notify_team(team_registration, tournament, TeamEmailType.WAITING_LIST)
        else:
            TournamentEmailService.notify_team(team_registration, tournament, TeamEmailType.REGISTERED)

    @staticmethod
    def _build_registration_confirmation_email_body(tournament, captain, tournament_details_str, other_player):
       return TournamentEmailService._build_registration_email_body(tournament, captain, tournament_details_str, other_player, False)

    @staticmethod
    def _build_waiting_list_confirmation_email_body(tournament, captain, tournament_details_str, other_player):
        return TournamentEmailService._build_registration_email_body(tournament, captain, tournament_details_str, other_player, True)

    @staticmethod
    def _build_registration_email_body(tournament, captain, tournament_details_str, other_player, waiting_list):
        inscription_date = captain.team_registration.local_registration_date().strftime("%d/%m/%Y à %H:%M")
        body_parts = []
        body_parts.append("Bonjour,\n")

        if waiting_list:
            body_parts.append(f"Votre inscription en liste d'attente du tournoi {tournament_details_str} est confirmée.")
        else:
            body_parts.append(f"Votre inscription au tournoi {tournament_details_str} est confirmée.")

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "informations sur le tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        body_parts.extend([
            f"\nDate d'inscription: {inscription_date}",
            f"\nÉquipe inscrite: {captain.name()} et {other_player.name()}",
            f"\nLe tournoi commencera le {tournament.formatted_start_date()} au club {tournament.event.club.name}",
            f"\nVoir les {absolute_url}",
            "\nPour toute question, veuillez contacter votre juge-arbitre. Si vous n'êtes pas à l'origine de cette inscription, merci de le contacter rapidement.",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\nCeci est un e-mail automatique, veuillez ne pas y répondre.",
            "\nCordialement,\n\nPadel Club"
        ])

        return "\n".join(body_parts)

    @staticmethod
    def _build_unregistration_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Votre inscription au tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} a été annulée"
        ]

        if other_player is not None:
            body_parts.append(
                f"\n\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
            )

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "informations sur le tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        body_parts.append(
            f"\n\nVoir les {absolute_url}",
        )

        body_parts.extend([
            "\n\nPour toute question, veuillez contacter votre juge-arbitre. "
            "Si vous n'êtes pas à l'origine de cette désinscription, merci de le contacter rapidement.",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_out_of_waiting_list_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Suite au désistement d'une paire, vous êtes maintenant inscrit au tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}"
        ]

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "accéder au tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        if other_player is not None:
            body_parts.append(
                f"\nVoici le partenaire indiqué dans l'inscription : {other_player.name()}, n'oubliez pas de le prévenir."
            )

        body_parts.append(
            "\n\nSi vous n'êtes plus disponible pour participer à ce tournoi, cliquez sur ce lien ou contactez rapidement le juge-arbitre."
            f"\n{absolute_url}"
            "\nPour vous désinscrire en ligne vous devez avoir un compte Padel Club."
        )

        body_parts.extend([
            f"\n\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_tournament_cancellation_email_body(tournament, player, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Le tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} a été annulé par le juge-arbitre."
        ]

        if other_player is not None:
            body_parts.append(
                f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
            )

        body_parts.extend([
            "\n\nPour toute question, veuillez contacter votre juge-arbitre:",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_in_tournament_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Suite à une modification de la taille du tournoi, vous pouvez participer au tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}"
        ]

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "accéder au tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        if other_player is not None:
            body_parts.append(
                f"\nVoici le partenaire indiqué dans l'inscription : {other_player.name()}, n'oubliez pas de le prévenir."
            )

        body_parts.append(
            "\n\nSi vous n'êtes plus disponible pour participer à ce tournoi, cliquez sur ce lien ou contactez rapidement le juge-arbitre."
            f"\n{absolute_url}"
            "\nPour vous désinscrire en ligne vous devez avoir un compte Padel Club."
        )

        body_parts.extend([
            f"\n\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Suite à une modification de la taille du tournoi, vous ne faites plus partie des équipes participant au tournoi  {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}"
        ]

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "informations sur le tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        body_parts.append(f"\n\nVoir les {absolute_url}")

        if other_player is not None:
            body_parts.append(
                f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
            )

        body_parts.extend([
            "\n\nPour toute question, veuillez contacter votre juge-arbitre : ",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_walk_out_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Le juge-arbitre a annulé votre participation au tournoi  {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}"
        ]

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "accéder au tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        body_parts.append(f"\n\nVoir les {absolute_url}")


        if other_player is not None:
            body_parts.append(
                f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
            )

        body_parts.extend([
            "\n\nPour toute question, veuillez contacter votre juge-arbitre : ",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_out_of_walkout_is_in_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Le juge-arbitre vous a ré-intégré au tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}"
        ]

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "informations sur le tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        body_parts.append(f"\n\nVoir les {absolute_url}")

        if other_player is not None:
            body_parts.append(
                f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
            )

        body_parts.extend([
            "\n\nPour toute question, veuillez contacter votre juge-arbitre : ",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_unexpected_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"En raison d'une décision du juge-arbitre, vous ne faites plus partie des équipes participant au tournoi  {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}"
        ]

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "informations sur le tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        body_parts.append(f"\n\nVoir les {absolute_url}")

        if other_player is not None:
            body_parts.append(
                f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
            )

        body_parts.extend([
            "\n\nPour toute question, veuillez contacter votre juge-arbitre : ",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _build_out_of_walkout_waiting_list_email_body(tournament, captain, tournament_details_str, other_player):
        body_parts = [
            "Bonjour,\n\n",
            f"Le juge-arbitre vous a ré-intégré au tournoi en liste d'attente {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}"
        ]

        absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
        link_text = "informations sur le tournoi"
        absolute_url = f'<a href="{absolute_url}">{link_text}</a>'

        body_parts.append(f"\n\nVoir les {absolute_url}")

        if other_player is not None:
            body_parts.append(
                f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
            )

        body_parts.extend([
            "\n\nPour toute question, veuillez contacter votre juge-arbitre : ",
            f"\n{TournamentEmailService._format_umpire_contact(tournament)}",
            "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
        ])

        return "".join(body_parts)

    @staticmethod
    def _format_umpire_contact(tournament):
        contact_parts = []
        creator_full_name = tournament.umpire_contact()
        contact_parts.append(creator_full_name)

        if not tournament.hide_umpire_mail:
            creator_email = tournament.umpire_mail()
            if creator_email:
                contact_parts.append(creator_email)

        if not tournament.hide_umpire_phone:
            creator_phone = tournament.umpire_phone()
            if creator_phone:
                contact_parts.append(creator_phone)

        return "\n".join(contact_parts)

    @staticmethod
    def notify(captain, other_player, tournament, message_type: TeamEmailType):
        print("TournamentEmailService.notify", captain.email, captain.registered_online, tournament, message_type)
        if not captain or not captain.registered_online or not captain.email:
            return

        tournament_details_str = tournament.build_tournament_details_str()

        email_body = TournamentEmailService._build_email_content(
            message_type, captain, tournament, tournament_details_str, other_player
        )

        if email_body is None:
            return

        topic = message_type.email_subject()
        email_subject = TournamentEmailService.email_subject(tournament, topic)
        TournamentEmailService._send_email(captain.email, email_subject, email_body)

    @staticmethod
    def _build_email_content(message_type, recipient, tournament, tournament_details_str, other_player, request=None, waiting_list_position=None):
        if message_type == TeamEmailType.REGISTERED:
            body = TournamentEmailService._build_registration_confirmation_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.WAITING_LIST:
            body = TournamentEmailService._build_waiting_list_confirmation_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.OUT_OF_WAITING_LIST:
            body = TournamentEmailService._build_out_of_waiting_list_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.UNREGISTERED:
            body = TournamentEmailService._build_unregistration_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.TOURNAMENT_CANCELED:
            body = TournamentEmailService._build_tournament_cancellation_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.WALKOUT:
            body = TournamentEmailService._build_walk_out_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.OUT_OF_WALKOUT_IS_IN:
            body = TournamentEmailService._build_out_of_walkout_is_in_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST:
            body = TournamentEmailService._build_out_of_walkout_waiting_list_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.UNEXPECTED_OUT_OF_TOURNAMENT:
            body = TournamentEmailService._build_unexpected_out_of_tournament_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE:
            body = TournamentEmailService._build_out_of_tournament_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        elif message_type == TeamEmailType.IN_TOURNAMENT_STRUCTURE:
            body = TournamentEmailService._build_in_tournament_email_body(
                tournament, recipient, tournament_details_str, other_player
            )
        else:
            return None

        return body

    @staticmethod
    def _send_email(to, subject, body):
        email = EmailMessage(
            subject=subject,
            body=TournamentEmailService._convert_newlines_to_html(body),
            to=[to]
        )
        email.content_subtype = "html"
        email.send()
        print("TournamentEmailService._send_email", to, subject)

    @staticmethod
    def notify_team(team, tournament, message_type: TeamEmailType):
        # Notify both players separately if there is no captain or the captain is unavailable
        players = list(team.player_registrations.all())
        if len(players) == 2:
            print("TournamentEmailService.notify_team 2p", team)
            first_player, second_player = players
            TournamentEmailService.notify(first_player, second_player, tournament, message_type)
            TournamentEmailService.notify(second_player, first_player, tournament, message_type)
        elif len(players) == 1:
            print("TournamentEmailService.notify_team 1p", team)
            # If there's only one player, just send them the notification
            TournamentEmailService.notify(players[0], None, tournament, message_type)
