import logging
from asyncio import sleep, create_task

from email_validator import validate_email, EmailNotValidError
from rio import Column, Component, event, Text, TextStyle, TextInput, TextInputChangeEvent, Button

from src.ezgg_lan_manager import ConfigurationService, UserService, MailingService
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox

MINIMUM_PASSWORD_LENGTH = 6

logger = logging.getLogger(__name__.split(".")[-1])


class RegisterPage(Component):
    pw_1: str = ""
    pw_2: str = ""
    email: str = ""
    user_name: str = ""
    pw_1_valid: bool = True
    pw_2_valid: bool = True
    email_valid: bool = True
    submit_button_loading: bool = False
    display_text: str = ""
    display_text_style: TextStyle = TextStyle()

    def on_pw_focus_loss(self, _: TextInputChangeEvent) -> None:
        if not (self.pw_1 == self.pw_2) or len(self.pw_1) < MINIMUM_PASSWORD_LENGTH:
            self.pw_1_valid = False
            self.pw_2_valid = False
            return
        self.pw_1_valid = True
        self.pw_2_valid = True

    def on_email_focus_loss(self, change_event: TextInputChangeEvent) -> None:
        try:
            validate_email(change_event.text, check_deliverability=False)
            self.email_valid = True
        except EmailNotValidError:
            self.email_valid = False

    def on_user_name_focus_loss(self, _: TextInputChangeEvent) -> None:
        current_text = self.user_name
        if len(current_text) > UserService.MAX_USERNAME_LENGTH:
            self.user_name = current_text[:UserService.MAX_USERNAME_LENGTH]

    async def on_submit_button_pressed(self) -> None:
        self.submit_button_loading = True

        if len(self.user_name) < 1:
            await self.display_animated_text(False, "Nutzername darf nicht leer sein!")
            self.submit_button_loading = False
            return

        if not (self.pw_1 == self.pw_2):
            await self.display_animated_text(False, "Passwörter stimmen nicht überein!")
            self.submit_button_loading = False
            return

        if len(self.pw_1) < MINIMUM_PASSWORD_LENGTH:
            await self.display_animated_text(False, f"Passwort muss mindestens {MINIMUM_PASSWORD_LENGTH} Zeichen lang sein!")
            self.submit_button_loading = False
            return

        if not self.email_valid or len(self.email) < 3:
            await self.display_animated_text(False, "E-Mail Adresse ungültig!")
            self.submit_button_loading = False
            return

        user_service = self.session[UserService]
        mailing_service = self.session[MailingService]
        lan_info = self.session[ConfigurationService].get_lan_info()

        if await user_service.get_user(self.email) is not None or await user_service.get_user(self.user_name) is not None:
            await self.display_animated_text(False, "Benutzername oder E-Mail bereits registriert!")
            self.submit_button_loading = False
            return

        try:
            new_user = await user_service.create_user(self.user_name, self.email, self.pw_1)
            if not new_user:
                logger.error(f"create_user returned: {new_user}")
                raise Exception(f"create_user returned: {new_user}")
        except Exception as e:
            logger.error(f"Unknown error during new user registration: {e}")
            await self.display_animated_text(False, "Es ist ein unbekannter Fehler aufgetreten :(")
            self.submit_button_loading = False
            return

        await mailing_service.send_email(
            subject="Erfolgreiche Registrierung",
            body=f"Hallo {self.user_name},\n\n"
                 f"Du hast dich erfolgreich beim EZGG-LAN Manager für {lan_info.name} {lan_info.iteration} registriert.\n\n"
                 f"Wenn du dich nicht registriert hast, kontaktiere bitte unser Team über unsere Homepage.\n\n"
                 f"Liebe Grüße\nDein {lan_info.name} - Team",
            receiver=self.email
        )

        self.submit_button_loading = False
        await self.display_animated_text(True, "Erfolgreich registriert!")

    @event.on_populate
    async def on_populate(self) -> None:
        await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Registrieren")

    async def display_animated_text(self, success: bool, text: str) -> None:
        self.display_text = ""
        style = TextStyle(
            fill=self.session.theme.success_color if success else self.session.theme.danger_color,
            font_size=0.9
        )

        self.display_text_style = style
        _ = create_task(self._animate_text(text))

    async def _animate_text(self, text: str) -> None:
        for c in text:
            self.display_text += c
            await sleep(0.06)

    def build(self) -> Component:
        user_name_input = TextInput(
            label="Benutzername",
            text=self.bind().user_name,
            margin_left=1,
            margin_right=1,
            margin_bottom=1,
            grow_x=True,
            on_lose_focus=self.on_user_name_focus_loss
        )
        email_input = TextInput(
            label="E-Mail Adresse",
            text=self.bind().email,
            margin_left=1,
            margin_right=1,
            margin_bottom=1,
            grow_x=True,
            on_lose_focus=self.on_email_focus_loss,
            is_valid=self.email_valid
        )
        pw_1_input = TextInput(
            label="Passwort",
            text=self.bind().pw_1,
            margin_left=1,
            margin_right=1,
            margin_bottom=1,
            grow_x=True,
            is_secret=True,
            on_lose_focus=self.on_pw_focus_loss,
            is_valid=self.pw_1_valid
        )
        pw_2_input = TextInput(
            label="Passwort wiederholen",
            text=self.bind().pw_2,
            margin_left=1,
            margin_right=1,
            margin_bottom=1,
            grow_x=True,
            is_secret=True,
            on_lose_focus=self.on_pw_focus_loss,
            is_valid=self.pw_2_valid
        )
        submit_button = Button(
            content=Text(
                "Registrieren",
                style=TextStyle(fill=self.session.theme.background_color, font_size=0.9),
                align_x=0.5
            ),
            grow_x=True,
            margin_top=2,
            margin_left=1,
            margin_right=1,
            margin_bottom=1,
            shape="rectangle",
            style="minor",
            color=self.session.theme.secondary_color,
            on_press=self.on_submit_button_pressed,
            is_loading=self.submit_button_loading
        )
        return Column(
            MainViewContentBox(
                content=Column(
                    Text(
                        "Neues Konto anlegen",
                        style=TextStyle(
                            fill=self.session.theme.background_color,
                            font_size=1.2
                        ),
                        margin_top=2,
                        margin_bottom=2,
                        align_x=0.5
                    ),
                    user_name_input,
                    email_input,
                    pw_1_input,
                    pw_2_input,
                    submit_button,
                    Text(self.display_text, margin_top=2, margin_left=1, margin_right=1, margin_bottom=2, style=self.display_text_style)
                )
            ),
            align_y=0,
        )
