from hashlib import sha256
from random import choices

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


class ForgotPasswordPage(Component):
    def on_email_changed(self, change_event: TextInputChangeEvent) -> None:
        try:
            validate_email(change_event.text, check_deliverability=False)
            self.email_input.is_valid = True
            self.submit_button.is_sensitive = True
        except EmailNotValidError:
            self.email_input.is_valid = False
            self.submit_button.is_sensitive = False

    async def on_submit_button_pressed(self) -> None:
        self.submit_button.is_loading = True
        self.submit_button.force_refresh()
        lan_info = self.session[ConfigurationService].get_lan_info()
        user_service = self.session[UserService]
        mailing_service = self.session[MailingService]
        user = await user_service.get_user(self.email_input.text.strip())
        if user is not None:
            new_password = "".join(choices(user_service.ALLOWED_USER_NAME_SYMBOLS, k=16))
            user.user_fallback_password = sha256(new_password.encode(encoding="utf-8")).hexdigest()
            await user_service.update_user(user)
            await mailing_service.send_email(
                subject=f"Dein neues Passwort für {lan_info.name}",
                body=f"Du hast für den EZGG-LAN Manager der {lan_info.name} ein neues Passwort angefragt. "
                     f"Und hier ist es schon:\n\n{new_password}\n\nSolltest du kein neues Passwort angefordert haben, "
                     f"ignoriere diese E-Mail.\n\nLiebe Grüße\nDein {lan_info.name} - Team",
                receiver=self.email_input.text.strip()
            )

        self.submit_button.is_loading = False
        self.email_input.text = ""

        self.info_text.text = "Falls für diese E-Mail ein Konto besteht, " \
                              "bekommst du in den nächsten Minuten ein neues Passwort zugeschickt. " \
                              "Bitte prüfe dein Spam-Postfach.",

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

    def build(self) -> Component:
        self.email_input = TextInput(
            label="E-Mail Adresse",
            text="",
            margin_left=1,
            margin_right=1,
            margin_bottom=1,
            grow_x=True,
            on_change=self.on_email_changed
        )
        self.submit_button = Button(
            content=Text(
                "Neues Passwort anfordern",
                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_sensitive=False
        )
        self.info_text = Text(
            text="",
            style=TextStyle(
                fill=self.session.theme.background_color,
                font_size=1
            ),
            margin_top=2,
            margin_left=1,
            margin_right=1,
            margin_bottom=2,
            overflow="wrap"
        )
        return Column(
            MainViewContentBox(
                content=Column(
                    Text(
                        "Passwort vergessen",
                        style=TextStyle(
                            fill=self.session.theme.background_color,
                            font_size=1.2
                        ),
                        margin_top=2,
                        margin_bottom=2,
                        align_x=0.5
                    ),
                    self.email_input,
                    self.submit_button,
                    self.info_text
                )
            ),
            align_y=0,
        )
