"""Dashboard: die Seite, die man beim Botten wirklich braucht.

Status + Steuerung auf einen Blick: Bot an/aus, Cavebot, Healing, Kombos,
aktuelle Aufgabe, Position, Session-Zeit und die letzten Ereignisse.
Aktualisiert sich sekundenweise aus den Live-Statusdateien.
"""
import customtkinter

from src.ui import livestate, theme


class StatusCard(customtkinter.CTkFrame):
    def __init__(self, master, title):
        super().__init__(
            master, corner_radius=14, fg_color=theme.SURFACE,
            border_width=1, border_color=theme.BORDER,
        )
        self.grid_columnconfigure(0, weight=1)
        customtkinter.CTkLabel(
            self, text=title, font=theme.font(12, 'bold'),
            text_color=theme.MUTED,
        ).grid(row=0, column=0, padx=16, pady=(12, 2), sticky='w')
        self.body = customtkinter.CTkFrame(self, fg_color='transparent')
        self.body.grid(row=1, column=0, padx=16, pady=(0, 14), sticky='nsew')
        self.body.grid_columnconfigure(0, weight=1)


class DashboardPage(customtkinter.CTkFrame):
    def __init__(self, master, context):
        super().__init__(master, fg_color='transparent')
        self.context = context
        self.grid_columnconfigure((0, 1), weight=1, uniform='cards')
        self.grid_rowconfigure(3, weight=1)

        self._buildStatusCard()
        self._buildCavebotCard()
        self._buildVitalsCard()
        self._buildSessionCard()
        self._buildEventsCard()
        self._buildMapCard()
        self._refresh()

    # ------------------------------------------------------------------ Karten
    def _buildStatusCard(self):
        card = StatusCard(self, 'STATUS')
        card.grid(row=0, column=0, padx=(0, 8), pady=(0, 12), sticky='nsew')
        self.stateLabel = customtkinter.CTkLabel(
            card.body, text='—', font=theme.font(26, 'bold'),
        )
        self.stateLabel.grid(row=0, column=0, sticky='w')
        self.taskLabel = customtkinter.CTkLabel(
            card.body, text='', font=theme.font(12),
            text_color=theme.MUTED, wraplength=300, justify='left',
        )
        self.taskLabel.grid(row=1, column=0, sticky='w', pady=(2, 10))
        self.playButton = customtkinter.CTkButton(
            card.body, text='Bot starten', height=40, corner_radius=10,
            font=theme.font(13, 'bold'), fg_color=theme.ACCENT,
            hover_color=theme.ACCENT_HOVER, command=self._togglePlay,
        )
        self.playButton.grid(row=2, column=0, sticky='ew')

    def _buildCavebotCard(self):
        card = StatusCard(self, 'STEUERUNG')
        card.grid(row=0, column=1, padx=(8, 0), pady=(0, 12), sticky='nsew')
        self.toggles = {}
        for row, (key, label, command) in enumerate([
            ('cavebot', 'Cavebot', self._toggleCavebot),
            ('creatures', 'Run to Creatures', self._toggleRunToCreatures),
            ('healing', 'Healing', self._toggleHealing),
            ('combo', 'Kombos', self._toggleCombo),
        ]):
            switch = customtkinter.CTkSwitch(
                card.body, text=label, command=command,
                progress_color=theme.ACCENT, font=theme.font(13),
            )
            switch.grid(row=row, column=0, sticky='w', pady=4)
            self.toggles[key] = switch

    def _buildVitalsCard(self):
        card = StatusCard(self, 'ZUSTAND')
        card.grid(row=1, column=0, padx=(0, 8), pady=(0, 12), sticky='nsew')
        self.hpBar = self._bar(card.body, 0, 'HP', theme.DANGER)
        self.manaBar = self._bar(card.body, 1, 'Mana', '#3B82D6')
        self.coordLabel = customtkinter.CTkLabel(
            card.body, text='', font=theme.font(12), text_color=theme.MUTED,
        )
        self.coordLabel.grid(row=2, column=0, sticky='w', pady=(8, 0))

    def _bar(self, parent, row, label, color):
        customtkinter.CTkLabel(
            parent, text=label, font=theme.font(12), text_color=theme.MUTED,
            width=44, anchor='w',
        ).grid(row=row, column=0, sticky='w', pady=4)
        bar = customtkinter.CTkProgressBar(parent, progress_color=color)
        bar.grid(row=row, column=1, sticky='ew', padx=(8, 0), pady=4)
        parent.grid_columnconfigure(1, weight=1)
        bar.set(0)
        return bar

    def _buildSessionCard(self):
        card = StatusCard(self, 'SESSION')
        card.grid(row=1, column=1, padx=(8, 0), pady=(0, 12), sticky='nsew')
        self.sessionLabel = customtkinter.CTkLabel(
            card.body, text='—', font=theme.font(18, 'bold'),
        )
        self.sessionLabel.grid(row=0, column=0, sticky='w')
        self.sessionDetail = customtkinter.CTkLabel(
            card.body, text='', font=theme.font(12), text_color=theme.MUTED,
        )
        self.sessionDetail.grid(row=1, column=0, sticky='w')
        self.sessionStats = customtkinter.CTkLabel(
            card.body, text='', font=theme.font(12),
            text_color=theme.ACCENT,
        )
        self.sessionStats.grid(row=2, column=0, sticky='w', pady=(4, 0))

    def _buildEventsCard(self):
        card = StatusCard(self, 'EREIGNISSE')
        card.grid(row=2, column=0, padx=(0, 8), sticky='nsew')
        self.eventsLabel = customtkinter.CTkLabel(
            card.body, text='Keine Ereignisse.', font=theme.font(12),
            text_color=theme.MUTED, justify='left', anchor='nw',
        )
        self.eventsLabel.grid(row=0, column=0, sticky='nw')

    def _buildMapCard(self):
        card = StatusCard(self, 'KARTE', )
        card.grid(row=2, column=1, padx=(8, 0), sticky='nsew')
        self.mapCanvas = customtkinter.CTkCanvas(
            card.body, width=340, height=190, bg=theme.ELEVATED,
            highlightthickness=0,
        )
        self.mapCanvas.grid(row=0, column=0, sticky='nsew')

    def _drawMap(self):
        canvas = self.mapCanvas
        canvas.delete('all')
        data = livestate.readHeatmap()
        points = data.get('points', [])
        if not points:
            canvas.create_text(
                170, 95, text='Noch keine Route aufgezeichnet.',
                fill='#8B95A7', font=('Segoe UI', 11),
            )
            return
        xs = [p[0] for p in points]
        ys = [p[1] for p in points]
        pad = 4
        minX, maxX = min(xs) - pad, max(xs) + pad
        minY, maxY = min(ys) - pad, max(ys) + pad
        spanX = max(maxX - minX, 1)
        spanY = max(maxY - minY, 1)
        width, height = 340, 190

        def project(point):
            px = 8 + (point[0] - minX) / spanX * (width - 16)
            py = 8 + (point[1] - minY) / spanY * (height - 16)
            return px, py

        recent = points[-40:]
        for point in points[:-40] if len(points) > 40 else []:
            px, py = project(point)
            canvas.create_oval(px - 1, py - 1, px + 1, py + 1,
                               fill='#3B4454', outline='')
        for point in recent:
            px, py = project(point)
            canvas.create_oval(px - 1.5, py - 1.5, px + 1.5, py + 1.5,
                               fill='#E33A63', outline='')
        for stuck in data.get('stucks', []):
            px, py = project(stuck['coordinate'])
            canvas.create_oval(px - 4, py - 4, px + 4, py + 4,
                               outline='#E0A23B', width=2)
        for jump in data.get('jumps', []):
            px, py = project(jump['to'])
            canvas.create_line(px - 4, py - 4, px + 4, py + 4,
                               fill='#E5484D', width=2)
            canvas.create_line(px - 4, py + 4, px + 4, py - 4,
                               fill='#E5484D', width=2)
        px, py = project(points[-1])
        canvas.create_oval(px - 3, py - 3, px + 3, py + 3,
                           outline='#3FB68B', width=2)

    # ------------------------------------------------------------------ Aktionen
    def _togglePlay(self):
        ctx = self.context.context
        if ctx['ng_pause']:
            self.context.play()
        else:
            self.context.pause()
        self._refresh()

    def _toggleCavebot(self):
        self.context.toggleCavebot(self.toggles['cavebot'].get() == 1)

    def _toggleRunToCreatures(self):
        self.context.toggleRunToCreatures(
            self.toggles['creatures'].get() == 1)

    def _toggleHealing(self):
        self.context.toggleHealingMaster(self.toggles['healing'].get() == 1)

    def _toggleCombo(self):
        self.context.toggleComboSpells(self.toggles['combo'].get() == 1)

    # ------------------------------------------------------------------ Refresh
    def _refresh(self):
        ctx = self.context.context
        state = livestate.readState()
        paused = ctx['ng_pause']
        onBreak = ctx.get('ng_sessionBreak', False)
        failsafe = 'ng_failsafe' in ctx

        if failsafe:
            status, color = 'FAILSAFE', theme.DANGER
        elif paused and onBreak:
            status, color = 'SESSION-PAUSE', theme.WARNING
        elif paused:
            status, color = 'PAUSIERT', theme.MUTED
        else:
            status, color = 'AKTIV', theme.SUCCESS
        self.stateLabel.configure(text=status, text_color=color)
        self.playButton.configure(
            text='Bot pausieren' if not paused else 'Bot starten')

        task = state.get('task')
        waypoint = state.get('waypointIndex')
        detail = f'Aufgabe: {task}' if task else 'Keine aktive Aufgabe.'
        if waypoint is not None:
            detail += f'  ·  Wegpunkt {waypoint}'
        self.taskLabel.configure(text=detail)

        self.toggles['cavebot'].select() if ctx['ng_cave']['enabled'] \
            else self.toggles['cavebot'].deselect()
        self.toggles['creatures'].select() if ctx['ng_cave']['runToCreatures'] \
            else self.toggles['creatures'].deselect()
        self.toggles['healing'].select() if self.context.healingMasterEnabled() \
            else self.toggles['healing'].deselect()
        self.toggles['combo'].select() if ctx['ng_comboSpells']['enabled'] \
            else self.toggles['combo'].deselect()

        vitals = ctx.get('ng_statusBar', {})
        hp = vitals.get('hpPercentage')
        mana = vitals.get('manaPercentage')
        self.hpBar.set((hp or 0) / 100)
        self.manaBar.set((mana or 0) / 100)
        coord = state.get('coordinate')
        self.coordLabel.configure(
            text=f'Position: {coord}' if coord else 'Position unbekannt')

        session = livestate.sessionSummary()
        self.sessionLabel.configure(
            text=livestate.formatDuration(session['playedSeconds']))
        remaining = session['breakRemainingSeconds']
        self.sessionDetail.configure(
            text=f'Pause noch {livestate.formatDuration(remaining)}'
            if remaining else 'gespielt heute')

        events = livestate.readEvents()
        if events:
            lines = [
                f"{event.get('at', '?')[11:16]}  {event.get('type', '?')}"
                for event in events
            ]
            self.eventsLabel.configure(text='\n'.join(lines))

        bot = livestate.readStats()
        if bot:
            self.sessionStats.configure(
                text=(f"Loot/h: {bot.get('lootPerHour', 0)}  ·  "
                      f"Stuck: {bot.get('stucks', 0)}  ·  "
                      f"Sprünge: {bot.get('jumps', 0)}"))
        self._drawMap()

        self.after(1000, self._refresh)
