from datetime import date
from hashlib import sha256
from typing import Optional

from email_validator import validate_email, EmailNotValidError
from from_root import from_root
from rio import Component, Column, Button, Color, TextStyle, Text, TextInput, Row, Image, event, Spacer, DateInput, \
    TextInputChangeEvent, NoFileSelectedError

from src.ezgg_lan_manager.services.UserService import UserService, NameNotAllowedError
from src.ezgg_lan_manager.services.ConfigurationService import ConfigurationService
from src.ezgg_lan_manager.types.User import User
from src.ezgg_lan_manager.types.UserSession import UserSession


class UserEditForm(Component):
    is_own_profile: bool = True
    profile_picture: Optional[bytes] = None
    user: Optional[User] = None

    input_user_name: str = ""
    input_user_mail: str = ""
    input_user_first_name: str = ""
    input_user_last_name: str = ""
    input_password_1: str = ""
    input_password_2: str = ""
    input_birthday: date = date.today()

    is_email_valid: bool = True

    result_text: str = ""
    result_success: bool = True

    @event.on_populate
    async def on_populate(self) -> None:
        await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Profil bearbeiten")
        if self.is_own_profile:
            try:
                user_id = self.session[UserSession].user_id
            except KeyError:
                self.session.navigate_to("/")
            else:
                self.user = await self.session[UserService].get_user(user_id)
                self.profile_picture = await self.session[UserService].get_profile_picture(self.user.user_id)
        else:
            self.profile_picture = await self.session[UserService].get_profile_picture(self.user.user_id)

        self.input_user_name = self.user.user_name
        self.input_user_mail = self.user.user_mail
        self.input_user_first_name = self.optional_str_to_str(self.user.user_first_name)
        self.input_user_last_name = self.optional_str_to_str(self.user.user_last_name)
        self.input_birthday = self.user.user_birth_day if self.user.user_birth_day else date.today()


    @staticmethod
    def optional_str_to_str(s: Optional[str]) -> str:
        if s:
            return s
        return ""

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

    async def upload_new_pfp(self) -> None:
        try:
            new_pfp = await self.session.pick_file(file_types=("png", "jpg", "jpeg"), multiple=False)
        except NoFileSelectedError:
            self.result_text = "Keine Datei ausgewählt!"
            self.result_success = False
            return

        if new_pfp.size_in_bytes > 2 * 1_000_000:
            self.result_text = "Bild zu groß! (> 2MB)"
            self.result_success = False
            return

        image_data = await new_pfp.read_bytes()
        await self.session[UserService].set_profile_picture(self.user.user_id, image_data)
        self.profile_picture = image_data
        self.result_text = "Gespeichert!"
        self.result_success = True

    async def remove_profile_picture(self) -> None:
        await self.session[UserService].remove_profile_picture(self.user.user_id)
        self.profile_picture = None
        self.result_text = "Profilbild entfernt!"
        self.result_success = True

    async def on_save_pressed(self) -> None:
        if not all((self.is_email_valid, self.input_user_name, self.input_user_mail)):
            self.result_text = "Ungültige Werte!"
            self.result_success = False
            return

        if len(self.input_password_1.strip()) > 0:
            if self.input_password_1.strip() != self.input_password_2.strip():
                self.result_text = "Passwörter nicht gleich!"
                self.result_success = False
                return

        self.user.user_mail = self.input_user_mail

        if self.input_birthday == date.today():
            self.user.user_birth_day = None
        else:
            self.user.user_birth_day = self.input_birthday

        self.user.user_first_name = self.input_user_first_name
        self.user.user_last_name = self.input_user_last_name
        self.user.user_name = self.input_user_name
        if len(self.input_password_1.strip()) > 0:
            self.user.user_password = sha256(self.input_password_1.strip().encode(encoding="utf-8")).hexdigest()

        try:
            await self.session[UserService].update_user(self.user)
        except NameNotAllowedError:
            self.result_text = "Ungültige Zeichen in Nutzername"
            self.result_success = False
            return

        self.result_text = "Gespeichert!"
        self.result_success = True

    def build(self) -> Component:
        pfp_image_container = Image(
            from_root("src/ezgg_lan_manager/assets/img/anon_pfp.png") if self.profile_picture is None else self.profile_picture,
            align_x=0.5,
            min_width=10,
            min_height=10,
            margin_top=1,
            margin_bottom=1
        )

        return Column(
            pfp_image_container,
            Button(
                content=Text(
                    "Neues Bild hochladen",
                    style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
                ),
                align_x=0.5,
                margin_bottom=1,
                shape="rectangle",
                style="major",
                color="primary",
                on_press=self.upload_new_pfp
            ) if self.is_own_profile else Button(
                content=Text(
                    "Bild löschen",
                    style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
                ),
                align_x=0.5,
                margin_bottom=1,
                shape="rectangle",
                style="major",
                color="primary",
                on_press=self.remove_profile_picture
            ),
            Row(
                TextInput(
                    label=f"{'Deine ' if self.is_own_profile else ''}User-ID",
                    text=str(self.user.user_id),
                    is_sensitive=False,
                    margin_left=1,
                    grow_x=False
                ),
                TextInput(
                    label=f"{'Dein ' if self.is_own_profile else ''}Nickname",
                    text=self.bind().input_user_name,
                    is_sensitive=not self.is_own_profile,
                    margin_left=1,
                    margin_right=1,
                    grow_x=True
                ),
                margin_bottom=1
            ),
            TextInput(
                label="E-Mail Adresse",
                text=self.bind().input_user_mail,
                margin_left=1,
                margin_right=1,
                margin_bottom=1,
                grow_x=True,
                is_valid=self.is_email_valid,
                on_change=self.on_email_changed
            ),
            Row(
                TextInput(
                    label="Vorname",
                    text=self.bind().input_user_first_name,
                    margin_left=1,
                    margin_right=1,
                    grow_x=True
                ),
                TextInput(
                    label="Nachname",
                    text=self.bind().input_user_last_name,
                    margin_right=1,
                    grow_x=True
                ),
                margin_bottom=1
            ),
            DateInput(
                value=self.bind().input_birthday,
                label="Geburtstag",
                margin_left=1,
                margin_right=1,
                margin_bottom=1,
                grow_x=True
            ),
            TextInput(
                label="Neues Passwort setzen",
                text=self.bind().input_password_1,
                margin_left=1,
                margin_right=1,
                margin_bottom=1,
                grow_x=True,
                is_secret=True
            ),
            TextInput(
                label="Neues Passwort wiederholen",
                text=self.bind().input_password_2,
                margin_left=1,
                margin_right=1,
                margin_bottom=1,
                grow_x=True,
                is_secret=True
            ),

            Row(
                Text(
                    text=self.bind().result_text,
                    style=TextStyle(fill=self.session.theme.success_color if self.result_success else self.session.theme.danger_color),
                    margin_left=1
                ),
                Button(
                    content=Text(
                        "Speichern",
                        style=TextStyle(fill=self.session.theme.success_color, font_size=0.9),
                        align_x=0.2
                    ),
                    align_x=0.9,
                    margin_top=2,
                    margin_bottom=1,
                    shape="rectangle",
                    style="major",
                    color="primary",
                    on_press=self.on_save_pressed
                ),
            )
        ) if self.user else Spacer()