import flet as ft
from dbActions.chat import Chat
from dbActions.users import Users

class AdminChat:
    def __init__(self, page: ft.Page):
        self.page = page
        self.chat_manager = Chat()
        self.user_namager = Users()

        # Logged in user (ensure this is an admin)
        self.user = self.page.session.get("user")

        # Access flag: if not admin, we won't build the chat UI
        self.access_denied = False
        if not self.user or self.user.get("role") != "admin":
            self.access_denied = True
            return

        # --- Admin chat state ---
        self.active_chat_id: int | None = None
        self.active_chat_session: dict | None = None

        # UI containers
        self.sessions_column = ft.Column(spacing=4, expand=True)
        self.messages_list = ft.ListView(expand=True, spacing=10, auto_scroll=True)
        self.input_field = ft.TextField(
            hint_text="Scrie răspunsul tău aici...",
            expand=True,
            dense=True,
            border_radius=20,
            content_padding=ft.Padding(12, 8, 12, 8),
            on_submit=self.on_send_click
        )
        self.send_button = ft.IconButton(
            icon=ft.Icons.SEND_ROUNDED,
            tooltip="Trimite",
            on_click=self.on_send_click,
        )

        # Notification sound to be played on new client messages
        # Make sure the file path points to a valid audio file in your assets.
        # Example: place `chat_notify.mp3` in `assets/sounds/`.
        self.notification_audio = ft.Audio(
            src="sounds/chat_notify_triple.mp3",
            autoplay=True,
            volume=1.0,
        )

        # Subscribe to PubSub for live updates from clients
        try:
            self.page.pubsub.subscribe(self.on_pubsub_message)
        except Exception as e:
            # If PubSub is not configured, admin can still see messages with manual refresh
            print(e)

        # Cleanup old sessions (keep only chats from today in DB)
        try:
            self.chat_manager.cleanup_old_sessions()
        except Exception as e:
            print(e)

        # Preload sessions data so that when build() is called, lists are already populated
        self.load_sessions()

        self.page.overlay.append(self.notification_audio)

    def build(self) -> ft.Control:
        """Return main layout: left panel (sessions) + right panel (messages).

        This allows the admin chat UI to be embedded inside another container/page.
        """
        # If access is denied, return an informational message
        if getattr(self, "access_denied", False):
            return ft.Column(
                controls=[
                    ft.Text("Acces restricționat", size=22, weight=ft.FontWeight.BOLD),
                    ft.Text("Această pagină este disponibilă doar pentru administratori."),
                ],
                alignment=ft.MainAxisAlignment.CENTER,
                horizontal_alignment=ft.CrossAxisAlignment.CENTER,
            )

        # Left side: list of chat sessions
        left_panel = ft.Container(
            bgcolor=ft.Colors.GREY_100,
            padding=10,
            width=280,
            content=ft.Column(
                expand=True,
                controls=[
                    ft.Text("Conversații", size=18, weight=ft.FontWeight.BOLD),
                    ft.Divider(),
                    ft.Container(
                        expand=True,
                        content=ft.ListView(
                            expand=True,
                            spacing=4,
                            controls=[self.sessions_column],
                        ),
                    ),
                ],
            ),
        )

        # Right side: active conversation
        if not hasattr(self, "header_label"):
            self.header_label = ft.Text("Selectează o conversație", size=18, weight=ft.FontWeight.BOLD)

        right_panel = ft.Container(
            expand=True,
            padding=10,
            content=ft.Column(
                expand=True,
                controls=[
                    ft.Row(
                        alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
                        vertical_alignment=ft.CrossAxisAlignment.CENTER,
                        controls=[
                            self.header_label,
                            ft.Row(
                                [
                                    ft.Icon(ft.Icons.SUPPORT_AGENT),
                                    ft.WebView(
                                        url="/enable-notifications",  # small HTML page with a single 'Activează notificările' button
                                        width=160,
                                        height=40,
                                        expand=False,
                                    ),
                                ],
                                vertical_alignment=ft.CrossAxisAlignment.CENTER,
                                spacing=8,
                            ),
                        ],
                    ),
                    ft.Divider(),
                    ft.Container(
                        expand=True,
                        content=self.messages_list,
                    ),
                    ft.Divider(),
                    ft.Row(
                        vertical_alignment=ft.CrossAxisAlignment.CENTER,
                        controls=[self.input_field, self.send_button],
                    ),
                    self.notification_audio,
                ],
            ),
        )

        main_row = ft.Row(
            expand=True,
            controls=[left_panel, right_panel],
        )

        return main_row

    def load_sessions(self):
        """Load all chat sessions from DB and populate the left panel."""
        self.sessions_column.controls.clear()

        try:
            sessions = self.chat_manager.get_chatsessions_with_messages()
        except Exception:
            sessions = []

        if not sessions:
            self.sessions_column.controls.append(
                ft.Text("Nu există conversații deschise.", size=12, color=ft.Colors.GREY_600)
            )
            return

        # Sort by last_message_at DESC (if available) or created_at
        def sort_key(session):
            return session.get("last_message_at") or session.get("created_at") or ""

        sessions = sorted(sessions, key=sort_key, reverse=True)

        for session in sessions:
            self.sessions_column.controls.append(self._build_session_tile(session))

    def _build_session_tile(self, session: dict) -> ft.Container:
        """Create a clickable row for a chat session."""
        chat_id = session.get("id")
        user_id = session.get("user_id")
        status = session.get("status", "open")
        unread_for_admin = session.get("unread_for_admin", 0)
        
        title = f"Chat #{chat_id}"
        if user_id:
            user = self.user_namager.get(user_id)
            title += f" • User {user['name'].replace('~', ' ')}"

        subtitle_parts = []
        if status == "open":
            subtitle_parts.append("Deschis")
        else:
            subtitle_parts.append("Închis")

        last_from = session.get("last_message_from")
        if last_from:
            subtitle_parts.append(f"Ultimul mesaj: {last_from}")

        subtitle = " • ".join(subtitle_parts)

        badge = None
        if unread_for_admin:
            badge = ft.Container(
                bgcolor=ft.Colors.RED_400,
                border_radius=20,
                padding=ft.padding.symmetric(horizontal=8, vertical=2),
                content=ft.Text("nou", size=10, color=ft.Colors.WHITE),
            )

        bg_color = ft.Colors.BROWN_100 if unread_for_admin else ft.Colors.WHITE

        tile = ft.Container(
            padding=8,
            border_radius=8,
            bgcolor=bg_color,
            ink=True,
            on_click=lambda e, cid=chat_id: self.on_select_session(cid),
            content=ft.Row(
                alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
                controls=[
                    ft.Column(
                        spacing=2,
                        controls=[
                            ft.Text(title, weight=ft.FontWeight.BOLD, size=13),
                            ft.Text(subtitle, size=11, color=ft.Colors.GREY_600),
                        ],
                    ),
                    badge if badge else ft.Container(),
                ],
            ),
        )

        return tile

    def on_select_session(self, chat_id: int):
        """Triggered when admin clicks a chat session on the left."""
        self.active_chat_id = chat_id

        # Load session details
        try:
            session = self.chat_manager.get_chatsession(chat_id)
        except Exception as e:
            print(e)
            session = None

        self.active_chat_session = session

        # Update header
        if session:
            user_id = session.get("user_id")
            label = f"Chat #{chat_id}"
            if user_id:
                user = self.user_namager.get(user_id)
                label += f" • User {user['name'].replace('~', ' ')}"
            self.header_label.value = label
        else:
            self.header_label.value = f"Chat #{chat_id}"

        # Load messages
        self.load_messages_for_active_chat()

        # Mark messages as read for admin and update session's unread flag
        try:
            self.chat_manager.mark_messages_as_read(chat_id, "admin")
            if session:
                session["unread_for_admin"] = 0
                self.chat_manager.update_chatsession(session)
        except Exception as e:
            print(e)

        # Refresh session list to remove unread badge
        self.load_sessions()
        self.page.update()

    def load_messages_for_active_chat(self):
        """Load messages from DB for the currently active chat."""
        self.messages_list.controls.clear()

        if not self.active_chat_id:
            return

        try:
            messages = self.chat_manager.get_chatmessages_for_chat(self.active_chat_id)
        except Exception:
            messages = []

        for msg in messages:
            sender_type = msg.get("sender_type")
            text = msg.get("text", "")

            if sender_type == "admin":
                alignment = ft.MainAxisAlignment.END
                bubble_color = ft.Colors.BROWN_100
            else:
                alignment = ft.MainAxisAlignment.START
                bubble_color = ft.Colors.GREY_200

            self.messages_list.controls.append(
                ft.Row(
                    alignment=alignment,
                    controls=[
                        ft.Container(
                            bgcolor=bubble_color,
                            padding=8,
                            border_radius=12,
                            content=ft.Text(text, size=13),
                        )
                    ],
                )
            )

    def on_send_click(self, e):
        """Admin sends a new message to the active chat."""
        text = self.input_field.value.strip()
        if not text or not self.active_chat_id:
            return

        # Append admin bubble locally
        self.messages_list.controls.append(
            ft.Row(
                alignment=ft.MainAxisAlignment.END,
                controls=[
                    ft.Container(
                        bgcolor=ft.Colors.BROWN_100,
                        padding=8,
                        border_radius=12,
                        content=ft.Text(text, size=13),
                    )
                ],
            )
        )

        # Persist message in DB
        message = {
            "chat_id": self.active_chat_id,
            "session_token": None,
            "sender_type": "admin",
            "sender_id": self.user.get("id") if self.user else None,
            "text": text,
        }
        try:
            self.chat_manager.add_chatmessage(message)
        except Exception as e:
            print(e)

        # Update chat session metadata
        try:
            session = self.chat_manager.get_chatsession(self.active_chat_id)
            if session:
                session["last_message_from"] = "admin"
                session["unread_for_user"] = 1
                self.chat_manager.update_chatsession(session)
        except Exception as e:
            print(e)

        # Notify client side via PubSub
        try:
            self.page.pubsub.send_all(
                {
                    "type": "chat_message",
                    "chat_id": self.active_chat_id,
                    "sender": "admin",
                    "text": text,
                }
            )
        except Exception as e:
            print (e)

        # Refresh the sessions list to reflect new last_message_from and ordering
        self.load_sessions()

        self.input_field.value = ""
        self.page.update()

    def on_pubsub_message(self, data):
        """Handle PubSub messages coming from client pages."""
        if not isinstance(data, dict):
            return

        # New message from a client
        if data.get("type") == "chat_message" and data.get("sender") == "client":
            chat_id = data.get("chat_id")

            # Play notification sound for any incoming client message
            try:
                print('Play sound')
                self.notification_audio.play()
                print('Played sound')
            except Exception as e:
                print(e)

            # If this is the currently open chat, append bubble directly
            if self.active_chat_id == chat_id:
                text = data.get("text", "")
                self.messages_list.controls.append(
                    ft.Row(
                        alignment=ft.MainAxisAlignment.START,
                        controls=[
                            ft.Container(
                                bgcolor=ft.Colors.GREY_200,
                                padding=8,
                                border_radius=12,
                                content=ft.Text(text, size=13),
                            )
                        ],
                    )
                )
                self.page.update()

            # In any case, refresh sessions to update unread badges
            self.load_sessions()
            self.page.update()