import logging
from typing import Optional, Callable

from rio import Component, Text, Spacer, Rectangle, Column, TextStyle, Row, Button, TextInput, ThemeContextSwitcher

from src.ezgg_lan_manager.services.TeamService import TeamService, NotMemberError, TeamLeadRemovalError, AlreadyMemberError, NameNotAllowedError, TeamNameTooLongError, \
    TeamAbbrInvalidError, TeamNameAlreadyTaken
from src.ezgg_lan_manager.types.Team import Team
from src.ezgg_lan_manager.types.User import User

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


class ErrorBox(Component):
    error_message: str
    cancel: Callable

    def build(self) -> Component:
        return Rectangle(
            content=Column(
                Text(self.error_message, style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1.5),
                Row(
                    Button(
                        content="Ok",
                        shape="rectangle",
                        style="major",
                        color="hud",
                        on_press=self.cancel,
                    )
                ),
                margin=1
            ),
            fill=self.session.theme.primary_color
        )


class TeamsDialogJoinHandler(Component):
    is_active: bool
    cancel: Callable
    user: Optional[User] = None
    team: Optional[Team] = None
    error_message: Optional[str] = None
    password: str = ""

    async def join(self) -> None:
        if self.user is None or self.team is None:
            return

        if self.password != self.team.join_password:
            self.error_message = "Falsches Passwort!"
            return

        try:
            await self.session[TeamService].add_member_to_team(self.team, self.user)
        except AlreadyMemberError:
            self.error_message = "Du bist bereits Mitglied dieses Teams"
        else:
            await self.cancel_with_reset()

    async def cancel_with_reset(self) -> None:
        await self.cancel()
        self.error_message = None
        self.password = ""

    def build(self) -> Component:
        if not self.is_active or self.user is None or self.team is None:
            return Spacer()

        if self.error_message is not None:
            return ErrorBox(error_message=self.error_message, cancel=self.cancel_with_reset)

        return Rectangle(
            content=Column(
                Text(f"Team {self.team.name} beitreten", style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1, justify="center"),
                ThemeContextSwitcher(content=TextInput(text=self.bind().password, label="Beitrittspasswort", margin_bottom=1), color="secondary"),
                Row(
                    Button(
                        content="Abbrechen",
                        shape="rectangle",
                        style="major",
                        color=self.session.theme.danger_color,
                        on_press=self.cancel_with_reset,
                    ),
                    Button(
                        content="Beitreten",
                        shape="rectangle",
                        style="major",
                        color=self.session.theme.success_color,
                        on_press=self.join,
                    ),
                    spacing=1
                ),
                margin=1
            ),
            fill=self.session.theme.primary_color
        )


class TeamsDialogLeaveHandler(Component):
    is_active: bool
    cancel: Callable
    user: Optional[User] = None
    team: Optional[Team] = None
    error_message: Optional[str] = None

    async def leave(self) -> None:
        if self.user is not None and self.team is not None:
            try:
                await self.session[TeamService].remove_member_from_team(self.team, self.user)
            except NotMemberError:
                self.error_message = "Du bist kein Mitglied in diesem Team"
            except TeamLeadRemovalError:
                self.error_message = "Als Teamleiter kannst du das Team nicht verlassen"
            else:
                await self.cancel_with_reset()

    async def cancel_with_reset(self) -> None:
        await self.cancel()
        self.error_message = None

    def build(self) -> Component:
        if not self.is_active or self.user is None or self.team is None:
            return Spacer()

        if self.error_message is not None:
            return ErrorBox(error_message=self.error_message, cancel=self.cancel_with_reset)

        return Rectangle(
            content=Column(
                Text(f"Team {self.team.name} wirklich verlassen?", style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1.5, justify="center"),
                Row(
                    Button(
                        content="Nein",
                        shape="rectangle",
                        style="major",
                        color=self.session.theme.danger_color,
                        on_press=self.cancel_with_reset,
                    ),
                    Button(
                        content="Ja",
                        shape="rectangle",
                        style="major",
                        color=self.session.theme.success_color,
                        on_press=self.leave,
                    ),
                    spacing=1
                ),
                margin=1
            ),
            fill=self.session.theme.primary_color
        )


class TeamsDialogCreateHandler(Component):
    is_active: bool
    cancel: Callable
    user: Optional[User] = None
    error_message: Optional[str] = None
    team_name: str = ""
    team_abbr: str = ""
    team_join_password: str = ""

    async def cancel_with_reset(self) -> None:
        await self.cancel()
        self.error_message = None
        self.team_name, self.team_abbr, self.team_join_password = "", "", ""

    async def create(self) -> None:
        if self.user is None:
            return

        if not self.team_name or not self.team_abbr or not self.team_join_password:
            self.error_message = "Angaben unvollständig"
            return

        try:
            await self.session[TeamService].create_team(self.team_name, self.team_abbr, self.team_join_password, self.user)
        except NameNotAllowedError as e:
            self.error_message = f"Angaben ungültig. Darf kein '{e.disallowed_char}' enthalten."
        except TeamNameTooLongError:
            self.error_message = f"Name zu lang. Maximal {TeamService.MAX_TEAM_NAME_LENGTH} Zeichen."
        except TeamAbbrInvalidError:
            self.error_message = f"Name zu lang. Maximal {TeamService.MAX_TEAM_ABBR_LENGTH} Zeichen."
        except TeamNameAlreadyTaken:
            self.error_message = "Ein Team mit diesem Namen existiert bereits."
        else:
            await self.cancel_with_reset()

    def build(self) -> Component:
        if not self.is_active or self.user is None:
            return Spacer()

        if self.error_message is not None:
            return ErrorBox(error_message=self.error_message, cancel=self.cancel_with_reset)

        return Rectangle(
            content=Column(
                Text(f"Team gründen", style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1.5, justify="center"),
                ThemeContextSwitcher(content=TextInput(text=self.bind().team_name, label="Team Name", margin_bottom=1), color="secondary"),
                ThemeContextSwitcher(content=TextInput(text=self.bind().team_abbr, label="Team Abkürzung", margin_bottom=1), color="secondary"),
                ThemeContextSwitcher(content=TextInput(text=self.bind().team_join_password, label="Beitrittspasswort", margin_bottom=1), color="secondary"),
                Row(
                    Button(
                        content="Abbrechen",
                        shape="rectangle",
                        style="major",
                        color=self.session.theme.danger_color,
                        on_press=self.cancel_with_reset,
                    ),
                    Button(
                        content="Gründen",
                        shape="rectangle",
                        style="major",
                        color=self.session.theme.success_color,
                        on_press=self.create,
                    ),
                    spacing=1
                ),
                margin=1
            ),
            fill=self.session.theme.primary_color
        )
