from django.utils import timezone
from ..forms import TournamentRegistrationForm, AddPlayerForm
from ..repositories import TournamentRegistrationRepository
from .email_service import TournamentEmailService
from django.contrib import messages
from ..utils.licence_validator import LicenseValidator
from ..utils.player_search import get_player_name_from_csv
from tournaments.models import PlayerRegistration
from ..utils.extensions import is_not_sqlite_backend

class TournamentRegistrationService:
    def __init__(self, request, tournament):
        self.request = request
        self.tournament = tournament
        self.context = {}
        self.repository = TournamentRegistrationRepository()
        self.email_service = TournamentEmailService()

    def initialize_context(self):
        self.context = {
            'tournament': self.tournament,
            'registration_successful': False,
            'team_form': None,
            'add_player_form': None,
            'current_players': self.request.session.get('team_registration', []),
        }
        return self.context

    def handle_post_request(self):
        self.context['team_form'] = TournamentRegistrationForm(self.request.POST)
        self.context['add_player_form'] = AddPlayerForm(self.request.POST)

        if 'add_player' in self.request.POST:
            self.handle_add_player()
        if 'remove_player' in self.request.POST:
            self.handle_remove_player()
        elif 'register_team' in self.request.POST:
            self.handle_team_registration()

    def handle_remove_player(self):
        team_registration = self.request.session.get('team_registration', [])
        if team_registration:  # Check if list is not empty
            team_registration.pop()  # Remove last element
            self.request.session['team_registration'] = team_registration
        self.context['current_players'] = team_registration

    def handle_add_player(self):
        if not self.context['add_player_form'].is_valid():
            return

        player_data = self.context['add_player_form'].cleaned_data
        licence_id = player_data.get('licence_id', '').upper()

        # Validate license
        if not self._validate_license(licence_id):
            return

        # Check for duplicate players
        if self._is_duplicate_player(licence_id):
            return

        # Check if player is already registered in tournament
        if self._is_already_registered(licence_id):
            return

        if self.request.user.licence_id is None and len(self.context['current_players']) == 0:
            # if no licence id for authentificated user and trying to add him as first player of the team, we check his federal data
            self._handle_invalid_names(licence_id, player_data)
        else:
            # Handle player data
            if self.context['add_player_form'].names_is_valid():
                self._handle_valid_names(player_data)
            else:
                self._handle_invalid_names(licence_id, player_data)

        if self.request.user.is_authenticated and self.request.user.licence_id is None:
            self._update_user_license(player_data.get('licence_id'))

    def handle_team_registration(self):
        if not self.context['team_form'].is_valid():
            return

        if self.request.user.is_authenticated:
            cleaned_data = self.context['team_form'].cleaned_data
            mobile_number = cleaned_data.get('mobile_number')
            self.request.user.phone = mobile_number
            self.request.user.save()

        waiting_list_position = self.tournament.get_waiting_list_position()

        team_registration = self.repository.create_team_registration(
            self.tournament,
            timezone.now().replace(microsecond=0)
        )

        self.repository.create_player_registrations(
            self.request,
            team_registration,
            self.request.session['team_registration'],
            self.context['team_form'].cleaned_data
        )

        if is_not_sqlite_backend():
            self.email_service.send_registration_confirmation(
                self.request,
                self.tournament,
                team_registration,
                waiting_list_position
            )

        self.clear_session_data()
        self.context['registration_successful'] = True

    def handle_get_request(self):
        self.context['add_player_form'] = AddPlayerForm()
        self.context['team_form'] = self.initialize_team_form()
        self.initialize_session_data()

    def add_player_to_session(self, player_data):
        print("add_player_to_session", player_data)
        if not self.request.session.get('team_registration'):
            self.request.session['team_registration'] = []

        self.request.session['team_registration'].append(player_data)
        self.context['current_players'] = self.request.session.get('team_registration', [])
        self.context['add_player_form'].first_tournament = False
        self.context['add_player_form'].user_without_licence = False
        self.request.session.modified = True

    def clear_session_data(self):
        self.request.session['team_registration'] = []
        self.request.session.modified = True

    def initialize_team_form(self):
        initial_data = {}
        if self.request.user.is_authenticated:
            initial_data = {
                'email': self.request.user.email,
                'mobile_number': self.request.user.phone,
            }
        return TournamentRegistrationForm(initial=initial_data)

    def initialize_session_data(self):
        print("initialize_session_data")
        self.request.session['team_registration'] = []
        if self.request.user.is_authenticated:
            self._add_authenticated_user_to_session()

    def _add_authenticated_user_to_session(self):
        if not self.request.user.licence_id:
            self._handle_user_without_license()
            return

        player_data = self._get_authenticated_user_data()
        if player_data:
            self.request.session['team_registration'].insert(0, player_data)
            self.context['current_players'] = self.request.session.get('team_registration', [])
            self.request.session.modified = True

    def _handle_user_without_license(self):
        player_data = {
            'first_name': self.request.user.first_name,
            'last_name': self.request.user.last_name.upper(),
        }
        self.context['add_player_form'] = AddPlayerForm(initial=player_data)
        self.context['add_player_form'].user_without_licence = True
        self.request.session.modified = True

    def _get_authenticated_user_data(self):
        from ..utils.player_search import get_player_name_from_csv
        from ..utils.licence_validator import LicenseValidator
        user = self.request.user
        validator = LicenseValidator(user.licence_id)

        player_data = {
            'first_name': user.first_name,
            'last_name': user.last_name.upper(),
            'email': user.email,
            'phone': user.phone,
            'licence_id': validator.computed_licence_id
        }

        data, found = get_player_name_from_csv(self.tournament.federal_category, user.licence_id)
        if found and data:
            player_data.update({
                'rank': data['rank'],
                'points': data.get('points'),
                'assimilation': data.get('assimilation'),
                'tournament_count': data.get('tournament_count'),
                'ligue_name': data.get('ligue_name'),
                'club_name': data.get('club_name'),
                'birth_year': data.get('birth_year'),
                'found_in_french_federation': True,
            })

        return player_data

    def _validate_license(self, licence_id):
        validator = LicenseValidator(licence_id)

        if validator.validate_license() is False and self.tournament.license_is_required:
            if not licence_id:
                message = ("Le numéro de licence est obligatoire."
                          if not self.request.session.get('team_registration', [])
                          else "Le numéro de licence de votre partenaire est obligatoire.")
                messages.error(self.request, message)
            else:
                # computed_license_key = validator.computed_license_key
                # messages.error(self.request, f"Le numéro de licence est invalide, la lettre ne correspond pas. {computed_license_key}")
                messages.error(self.request, "Le numéro de licence est invalide, la lettre ne correspond pas.")
            return False
        return True

    def _is_duplicate_player(self, licence_id):
        existing_players = [player['licence_id'] for player in self.request.session.get('team_registration', [])]
        if licence_id in existing_players:
            messages.error(self.request, "Ce joueur est déjà dans l'équipe.")
            return True
        return False

    def _is_already_registered(self, licence_id):
        validator = LicenseValidator(licence_id)
        if (validator.validate_license() and
            self._license_already_registered(validator.stripped_license) and
            self.tournament.license_is_required):
            messages.error(self.request, "Un joueur avec ce numéro de licence est déjà inscrit dans une équipe.")
            return True
        return False

    def _handle_valid_names(self, player_data):
        print("_handle_valid_names", player_data)
        if player_data.get('rank') is None:
            self._set_default_rank(player_data)

        self.add_player_to_session(player_data)
        self.context['add_player_form'] = AddPlayerForm()
        self.context['add_player_form'].first_tournament = False

    def _handle_invalid_names(self, licence_id, player_data):
        data, found = get_player_name_from_csv(self.tournament.federal_category, licence_id)
        print("_handle_invalid_names get_player_name_from_csv", data, found)
        if found and data:
            self._update_player_data_from_csv(player_data, data)
            player_check = self._player_check(player_data)
            if player_check == True:
                self.add_player_to_session(player_data)
                self.context['add_player_form'] = AddPlayerForm()
            else:
                return
        else:
            print("_handle_first_tournament_case")
            self._handle_first_tournament_case(data)

    def _set_default_rank(self, player_data):
        if self.request.session.get('last_rank') is None:
            data, found = get_player_name_from_csv(self.tournament.federal_category, None)
            if data:
                self.request.session['last_rank'] = data['rank']
                self.request.session['is_woman'] = data['is_woman']
                self.request.session.modified = True

        player_data['rank'] = self.request.session.get('last_rank', None)
        player_data['is_woman'] = self.request.session.get('is_woman', False)

    def _update_user_license(self, licence_id):
        if self.request.user.is_authenticated and licence_id:
            self.context['add_player_form'].user_without_licence = False
            validator = LicenseValidator(licence_id)
            self.request.user.licence_id = validator.computed_licence_id
            self.request.user.save()
            self.request.user.refresh_from_db()
            self.request.session.modified = True
            # Reset the form state
            self.context['add_player_form'] = AddPlayerForm()
            self.context['add_player_form'].first_tournament = False

    def _update_player_data_from_csv(self, player_data, csv_data):
        print("_update_player_data_from_csv", player_data, csv_data)
        player_data.update({
            'first_name': csv_data['first_name'],
            'last_name': csv_data['last_name'],
            'rank': csv_data['rank'],
            'is_woman': csv_data['is_woman'],
            'points': csv_data.get('points'),
            'assimilation': csv_data.get('assimilation'),
            'tournament_count': csv_data.get('tournament_count'),
            'ligue_name': csv_data.get('ligue_name'),
            'club_name': csv_data.get('club_name'),
            'birth_year': csv_data.get('birth_year'),
            'found_in_french_federation': True,
            'email': None,
            'phone': None,
        })

        from django.contrib.auth import get_user_model
        User = get_user_model()

        # Get the license ID from player_data
        licence_id = player_data.get('licence_id')
        validator = LicenseValidator(licence_id)
        if validator and validator.stripped_license:
            try:
                # Try to find a user with matching license
                user_with_same_license = User.objects.get(licence_id__icontains=validator.stripped_license)

                # If found, update the email and phone
                if user_with_same_license:
                    player_data.update({
                        'email': user_with_same_license.email,
                        'phone': user_with_same_license.phone
                    })
                    print(f"Found user with license {licence_id}, updated email and phone")
            except User.DoesNotExist:
                # No user found with this license, continue with None email and phone
                pass

    def _handle_first_tournament_case(self, data):
        print("_handle_first_tournament_case", data)
        if data:
            self.request.session['last_rank'] = data['rank']
            self.request.session['is_woman'] = data['is_woman']
            self.request.session.modified = True

        self.context['add_player_form'].first_tournament = True

        if not self.context['add_player_form'].names_is_valid():
            message = ("Pour confirmer votre inscription votre prénom et votre nom sont obligatoires."
                      if not self.request.session.get('team_registration', [])
                      else "Pour rajouter un partenaire, son prénom et son nom sont obligatoires.")
            messages.error(self.request, message)

    def _player_check(self, player_data):
        licence_id = player_data['licence_id'].upper()
        validator = LicenseValidator(licence_id)
        is_license_valid = validator.validate_license()

        player_register_check = self.tournament.player_register_check(licence_id)
        if  is_license_valid and player_register_check is not None:
            for message in player_register_check:
                messages.error(self.request, message)
            return False

        return True

    def _license_already_registered(self, stripped_license):
        return PlayerRegistration.objects.filter(
            team_registration__tournament=self.tournament,
            licence_id__icontains=stripped_license,
            team_registration__walk_out=False
        ).exists()
