import copy
import re 
import ast 
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, 
                             QScrollArea, QFrame, QTreeWidget, QTreeWidgetItem, 
                             QHeaderView, QTextEdit, QPushButton, QButtonGroup,
                             QListWidget, QListWidgetItem, QSizePolicy)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from gui.assets.theme.styler import current_theme
from gui.widgets.percepts_table import PerceptsTableWidget
from gui.widgets.help_button import HelpButton


class AmbientePage(QWidget):
    def __init__(self, log_store):
        super().__init__()
        self.setProperty("class", "page")
        self.log_store = log_store
        
        self.known_environments = set()
        self.selected_environment = None
        self.env_button_group = QButtonGroup(self)
        self.env_button_group.setExclusive(True)

        self._setup_ui()

        self.log_store.environment_state_updated.connect(self.on_environment_state_updated)
        self.log_store.environment_history_updated.connect(self.on_environment_history_updated)
        self.log_store.store_updated.connect(self.check_timeline_update)

        self.on_environment_state_updated(self.log_store.get_environment_states_at_index(0))

    def _setup_ui(self):
        main_layout = QHBoxLayout(self)
        main_layout.setContentsMargins(20, 20, 20, 20)
        main_layout.setSpacing(15)

        left_column = QFrame()
        left_column.setFrameShape(QFrame.StyledPanel)
        left_column.setProperty("class", "card")
        left_column.setMaximumWidth(250)
        left_layout = QVBoxLayout(left_column)

        left_title_layout = QHBoxLayout()
        left_title = QLabel("Environments")
        left_title.setProperty("class", "h2")
        left_title.setFont(QFont("Segoe UI", 14, QFont.Bold))
        
        self.help_button = HelpButton(
            "<div style='max-width: 450px;'>"
            "<h3 style='margin: 0 0 10px 0; color: #3B82F6;'>Environments</h3>"
            "<p style='margin: 0 0 10px 0;'>Environments are spaces where the agents are situated.</p>"
            "<p style='margin: 0 0 5px 0;'><b>Connected Agents:</b> List of agents currently linked to this environment</p>"
            "<p style='margin: 0 0 5px 0;'><b>Percepts:</b> Information available in the environment that agents can perceive and use to update their beliefs</p>"
            "<p style='margin: 0 0 10px 0;'><b>Changes History:</b> Chronological log of all modifications in the environment</p>"
            "</div>",
            icon_size=28
        )
        
        left_title_layout.addWidget(left_title)
        left_title_layout.addStretch()
        left_title_layout.addWidget(self.help_button)
        left_layout.addLayout(left_title_layout)
        
        self.env_scroll_area = QScrollArea()
        self.env_scroll_area.setWidgetResizable(True)
        self.env_scroll_area.setFrameShape(QFrame.NoFrame)
        
        self.env_list_widget = QWidget()
        self.env_list_layout = QVBoxLayout(self.env_list_widget)
        self.env_list_layout.setAlignment(Qt.AlignTop)
        self.env_list_layout.setSpacing(4)
        self.env_scroll_area.setWidget(self.env_list_widget)
        
        left_layout.addWidget(self.env_scroll_area)
        main_layout.addWidget(left_column)

        self.details_container = QWidget()
        self.details_layout = QVBoxLayout(self.details_container)
        self.details_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.addWidget(self.details_container, stretch=1)

        self._show_placeholder()

    def update_theme(self):
        if self.selected_environment:
            self.rebuild_history_log()
            if hasattr(self, 'percepts_table'):
                self.percepts_table.update_theme()

    def _show_placeholder(self):
        self._clear_layout(self.details_layout)
        placeholder = QLabel("Select an environment to view details")
        placeholder.setAlignment(Qt.AlignCenter)
        placeholder.setProperty("class", "text-secondary")
        placeholder.setFont(QFont("Segoe UI", 12))
        self.details_layout.addWidget(placeholder)

    def _clear_layout(self, layout):
        while layout.count():
            child = layout.takeAt(0)
            if child.widget():
                child.widget().deleteLater()
                
    def _build_details_ui(self, env_name):
        self._clear_layout(self.details_layout)

        title = QLabel(f"Monitoring: {env_name}")
        title.setProperty("class", "h1")
        title.setFont(QFont("Segoe UI", 18, QFont.Bold))
        self.details_layout.addWidget(title)

        top_layout = QHBoxLayout()
        top_layout.setSpacing(15)

        agents_frame = QFrame()
        agents_frame.setProperty("class", "card")
        agents_layout = QVBoxLayout(agents_frame)
        agents_layout.setContentsMargins(16, 16, 16, 16)
        
        agents_title = QLabel("Connected Agents")
        agents_title.setProperty("class", "h2")
        agents_title.setFont(QFont("Segoe UI", 12, QFont.Bold))
        
        self.agents_list = QListWidget()
        self.agents_list.setFrameShape(QFrame.NoFrame)
        self._style_list(self.agents_list)
        
        agents_layout.addWidget(agents_title)
        agents_layout.addWidget(self.agents_list)
        top_layout.addWidget(agents_frame, stretch=1)

        percepts_frame = QFrame()
        percepts_frame.setProperty("class", "card")
        percepts_layout = QVBoxLayout(percepts_frame)
        percepts_layout.setContentsMargins(16, 16, 16, 16)

        percepts_header = QHBoxLayout()
        percepts_title = QLabel("Percepts")
        percepts_title.setProperty("class", "h2")
        percepts_title.setFont(QFont("Segoe UI", 12, QFont.Bold))
        
        self.percepts_counter = QLabel("(0)")
        self.percepts_counter.setProperty("class", "text-secondary")
        self.percepts_counter.setFont(QFont("Segoe UI", 11))
        
        percepts_header.addWidget(percepts_title)
        percepts_header.addWidget(self.percepts_counter)
        percepts_header.addStretch()
        
        percepts_layout.addLayout(percepts_header)
        
        percepts_scroll = QScrollArea()
        percepts_scroll.setWidgetResizable(True)
        percepts_scroll.setFrameShape(QFrame.NoFrame)
        percepts_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        
        self.percepts_table = PerceptsTableWidget()
        percepts_scroll.setWidget(self.percepts_table)
        
        percepts_layout.addWidget(percepts_scroll)
        top_layout.addWidget(percepts_frame, stretch=2)

        self.details_layout.addLayout(top_layout)

        history_frame = QFrame()
        history_frame.setProperty("class", "card")
        history_layout = QVBoxLayout(history_frame)
        history_layout.setContentsMargins(16, 16, 16, 16)
        
        history_title = QLabel("Changes History")
        history_title.setProperty("class", "h2")
        history_title.setFont(QFont("Segoe UI", 12, QFont.Bold))
        
        self.history_log = QTextEdit()
        self.history_log.setReadOnly(True)
        self.history_log.setMinimumHeight(200)
        self.history_log.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.history_log.setFrameShape(QFrame.NoFrame)
        
        history_layout.addWidget(history_title)
        history_layout.addWidget(self.history_log)
        
        self.details_layout.addWidget(history_frame)
        self.details_layout.setStretchFactor(history_frame, 1)

    def _style_list(self, list_widget):
        bg_secondary = current_theme.get('background_secondary', '#1F2937')
        bg_tertiary = current_theme.get('background_tertiary', '#4B5563')
        text_primary = current_theme.get('text_primary', '#F9FAFB')
        interactive = current_theme.get('interactive_primary', '#3B82F6')
        
        list_widget.setStyleSheet(f"""
            QListWidget {{
                background-color: transparent;
                border: none;
                outline: none;
            }}
            QListWidget::item {{
                background-color: {bg_secondary};
                border: 1px solid {bg_tertiary};
                border-radius: 6px;
                padding: 10px 12px;
                margin: 2px 0px;
                color: {text_primary};
            }}
            QListWidget::item:selected {{
                background-color: {interactive};
                border: 1px solid {interactive};
            }}
        """)

    def _add_environment_button(self, env_name):
        button = QPushButton(env_name)
        button.setObjectName("FilterButton")
        button.setCheckable(True)
        button.setCursor(Qt.PointingHandCursor)
        button.clicked.connect(lambda checked, n=env_name: self.on_environment_selected(n))
        self.env_button_group.addButton(button)
        
        for i in range(self.env_list_layout.count()):
            widget = self.env_list_layout.itemAt(i).widget()
            if widget and widget.text() > env_name:
                self.env_list_layout.insertWidget(i, button)
                return
        self.env_list_layout.addWidget(button)

    def on_environment_selected(self, env_name):
        if self.selected_environment == env_name:
            return
            
        self.selected_environment = env_name
        self._build_details_ui(env_name)

        idx = self.log_store.current_timeline_index
        all_states = self.log_store.get_environment_states_at_index(idx)
        
        self.on_environment_state_updated(all_states)
        self.rebuild_history_log()

    def check_timeline_update(self):
        if self.isVisible() and self.selected_environment:
            self.on_timeline_state_changed(self.log_store.current_timeline_index)

    def on_environment_state_updated(self, all_envs_data):
        if not all_envs_data:
            return

        for env_name in all_envs_data.keys():
            if env_name not in self.known_environments:
                self.known_environments.add(env_name)
                self._add_environment_button(env_name)

        if self.selected_environment and self.selected_environment in all_envs_data:
            data = all_envs_data[self.selected_environment]
            self.agents_list.clear()
            agents = data.get('connected_agents', [])
            if not agents:
                item = QListWidgetItem("No agents connected")
                item.setForeground(Qt.gray)
                self.agents_list.addItem(item)
            else:
                for agent in sorted(agents):
                    self.agents_list.addItem(QListWidgetItem(agent))

            percepts = data.get('percepts', {})
            self.percepts_table.set_percepts(percepts)

            total_percepts = len(self.percepts_table._all_percepts)
            self.percepts_counter.setText(f"({total_percepts})")

    def on_environment_history_updated(self, env_name, history_entry):
        if env_name == self.selected_environment and self.log_store.is_live:
            self._format_and_add_history_entry(history_entry)
            sb = self.history_log.verticalScrollBar()
            sb.setValue(sb.maximum())

    def rebuild_history_log(self):
        if not self.selected_environment:
            return
            
        self.history_log.clear()
        history_list = self.log_store.get_environment_change_history(self.selected_environment)

        for entry in history_list:
            self._format_and_add_history_entry(entry)

    def _format_and_add_history_entry(self, entry):
        raw_type = getattr(entry, 'type', 'unknown') or 'unknown'
        content = str(getattr(entry, 'content', 'N/A')).replace('<', '&lt;').replace('>', '&gt;')
        action = str(getattr(entry, 'agent_action', 'N/A'))
        time = getattr(entry, 'system_time', 'N/A')

        log_type_key = raw_type.lower()

        color_map = {
            'create': current_theme.get('success', '#10B981'),
            'delete': current_theme.get('danger', '#EF4444'),
            'change': current_theme.get('warning', '#F59E0B'),
            'update': current_theme.get('info', '#3B82F6')
        }
        
        type_map = {
            'create': '[CREATE]',
            'delete': '[DELETE]',
            'change': '[CHANGE]',
            'update': '[UPDATE]'
        }

        color = color_map.get(log_type_key, current_theme.get('text_primary', '#FFFFFF'))
        type_str = type_map.get(log_type_key, f'[{raw_type.upper()}]')

        text_sec_color = current_theme.get('text_secondary', '#9CA3AF')
        text_pri_color = current_theme.get('text_primary', '#FFFFFF')

        html = (
            f'<span style="color:{text_sec_color};">[{time}]</span> '
            f'<span style="color:{color}; font-weight:bold;">{type_str}</span> '
            f'<span style="color:{text_pri_color};">{content}</span> '
            f'<span style="color:{text_sec_color}; font-style:italic;"> (Action: {action})</span>'
        )
        self.history_log.append(html)

    def on_timeline_state_changed(self, index):
        states_at_index = self.log_store.get_environment_states_at_index(index)
        self.on_environment_state_updated(states_at_index)
        
        if self.selected_environment:
            self.rebuild_history_log()