"""Per-meeting context selector — repo/knowledge chips with search and load."""

from __future__ import annotations

import json
import threading
import urllib.request
from pathlib import Path
from typing import TYPE_CHECKING

import flet as ft

if TYPE_CHECKING:
    from meeting_helper.config import Config

TEAL = "#4ec9b0"


def _sanitize(name: str) -> str:
    return name.replace("_", " ").replace("-", " ").title()


class ContextSelector(ft.Column):
    """Chip-based repo + knowledge folder selector for the dashboard."""

    def __init__(self, page: ft.Page, config: "Config"):
        super().__init__(spacing=10)
        self._page = page
        self._config = config
        self._port = config.port
        self._session_active = False
        self._repos: list[dict] = []
        self._repo_chips: list[ft.Chip] = []
        self._kb_chips: list[ft.Chip] = []

        self._loaded_label = ft.Text("", size=11, color=TEAL)
        self._search = ft.TextField(
            hint_text="Search repos and knowledge...",
            dense=True,
            border_radius=8,
            content_padding=ft.padding.symmetric(horizontal=12, vertical=8),
            text_size=12,
            on_change=self._on_search,
        )

        self._repos_wrap = ft.Row(wrap=True, spacing=6, run_spacing=6)
        self._kb_wrap = ft.Row(wrap=True, spacing=6, run_spacing=6)

        self._load_btn = ft.ElevatedButton(
            "Load Context",
            icon=ft.Icons.UPLOAD,
            bgcolor="#238636",
            color="white",
            on_click=self._load_context,
            disabled=True,
        )

        self._disabled_label = ft.Text(
            "Start a meeting to select context",
            size=12,
            color=ft.Colors.OUTLINE,
            italic=True,
            text_align=ft.TextAlign.CENTER,
        )

        self._content_col = ft.Column(
            [
                self._search,
                ft.Text("Repositories", size=12, color=ft.Colors.ON_SURFACE_VARIANT),
                self._repos_wrap,
                ft.Text("Knowledge Base", size=12, color=ft.Colors.ON_SURFACE_VARIANT),
                self._kb_wrap,
                ft.Row([self._load_btn, self._loaded_label], spacing=12),
            ],
            spacing=8,
            visible=False,
        )

        self.controls = [
            ft.Row(
                [
                    ft.Text("Context Selector", size=14, weight=ft.FontWeight.W_600, color=ft.Colors.ON_SURFACE_VARIANT),
                    self._loaded_label,
                ],
                alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
            ),
            self._disabled_label,
            self._content_col,
        ]

        self._populate()

    def _populate(self):
        """Scan repos and knowledge folders to create chips."""
        self._repo_chips.clear()
        self._kb_chips.clear()
        self._repos_wrap.controls.clear()
        self._kb_wrap.controls.clear()

        # Repos
        if self._config.repos_workspaces:
            try:
                from meeting_helper.context_loader import get_repos_from_workspaces
                self._repos = get_repos_from_workspaces(
                    self._config.repos_workspaces,
                    ignored=list(self._config.ignored_repos),
                )
            except Exception:
                self._repos = []

        for repo in self._repos:
            chip = ft.Chip(
                label=ft.Text(repo["sanitized_name"], size=12),
                selected=False,
                on_select=lambda e: None,
                show_checkmark=False,
                selected_color="#238636",
                data=repo["path"],
            )
            self._repo_chips.append(chip)
            self._repos_wrap.controls.append(chip)

        # Knowledge
        if self._config.knowledge_paths:
            try:
                from meeting_helper.context_loader import get_knowledge_trees
                tree = get_knowledge_trees(
                    list(self._config.knowledge_paths),
                    ignored=list(self._config.ignored_knowledge),
                )
                if tree:
                    self._flatten_tree(tree)
            except Exception:
                pass

    def _flatten_tree(self, nodes):
        for node in nodes:
            chip = ft.Chip(
                label=ft.Text(_sanitize(node["name"]), size=12),
                selected=False,
                on_select=lambda e: None,
                show_checkmark=False,
                selected_color="#238636",
                data=node["path"],
            )
            self._kb_chips.append(chip)
            self._kb_wrap.controls.append(chip)
            if node.get("children"):
                self._flatten_tree(node["children"])

    def set_session_active(self, active: bool):
        self._session_active = active
        self._load_btn.disabled = not active
        self._disabled_label.visible = not active
        self._content_col.visible = active
        if not active:
            self._loaded_label.value = ""
            self._search.value = ""

    def sync_selection(self, repos: list[str], knowledge: list[str]):
        """Check chips matching given names (additive only)."""
        for chip in self._repo_chips:
            if Path(chip.data).name in repos:
                chip.selected = True
        for chip in self._kb_chips:
            if chip.data in knowledge:
                chip.selected = True
        if repos or knowledge:
            parts = list(repos) + [k.split("/")[-1] for k in knowledge]
            self._loaded_label.value = "Auto: " + ", ".join(parts)
            self._loaded_label.color = TEAL

    def _on_search(self, e):
        terms = [t.strip().lower() for t in (e.control.value or "").split(",") if t.strip()]
        for chip in self._repo_chips + self._kb_chips:
            name = chip.label.value.lower()
            chip.visible = not terms or any(t in name for t in terms)
        self._page.update()

    def _load_context(self, e):
        repos = [c.data for c in self._repo_chips if c.selected]
        folders = [c.data for c in self._kb_chips if c.selected]

        if not repos and not folders:
            self._loaded_label.value = "Select at least one item"
            self._loaded_label.color = "#f14c4c"
            self._page.update()
            return

        self._load_btn.disabled = True
        self._loaded_label.value = "Loading..."
        self._loaded_label.color = ft.Colors.ON_SURFACE_VARIANT
        self._page.update()

        def _do():
            try:
                data = json.dumps({
                    "repos": repos,
                    "knowledge_paths": list(self._config.knowledge_paths),
                    "knowledge_folders": folders,
                }).encode()
                req = urllib.request.Request(
                    f"http://127.0.0.1:{self._port}/config",
                    data=data,
                    headers={"Content-Type": "application/json"},
                    method="POST",
                )
                urllib.request.urlopen(req, timeout=15)
                self._loaded_label.value = f"Loaded {len(repos)} repo(s), {len(folders)} folder(s)"
                self._loaded_label.color = TEAL
            except Exception as exc:
                self._loaded_label.value = f"Error: {exc}"
                self._loaded_label.color = "#f14c4c"
            finally:
                self._load_btn.disabled = not self._session_active
                try:
                    self._page.update()
                except Exception:
                    pass

        self._page.run_thread(_do)
