"""Workspace screen — repos workspace folders, knowledge folders, ignore management."""

from __future__ import annotations

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

import flet as ft

if TYPE_CHECKING:
    from meeting_helper.config import Config

TEAL = "#4ec9b0"
ERROR_RED = "#f14c4c"


class WorkspaceScreen(ft.Column):
    """Configure repos workspace and knowledge folder for Claude context."""

    def __init__(self, page: ft.Page, config: "Config"):
        super().__init__(
            expand=True,
            scroll=ft.ScrollMode.AUTO,
            spacing=20,
            horizontal_alignment=ft.CrossAxisAlignment.STRETCH,
        )
        self._page = page
        self._config = config

        # File pickers
        self._repos_picker = ft.FilePicker()
        self._knowledge_picker = ft.FilePicker()
        page.services.append(self._repos_picker)
        page.services.append(self._knowledge_picker)

        # --- Repos Workspaces (folder paths) ---
        self._repos_paths_col = ft.Column(spacing=4)
        self._repos_search = ft.TextField(
            hint_text="Filter repos...",
            dense=True,
            border_radius=8,
            text_size=12,
            prefix_icon=ft.Icons.SEARCH,
            on_change=self._on_repos_search,
            content_padding=ft.padding.symmetric(horizontal=12, vertical=6),
        )
        self._repos_chips_wrap = ft.Row(wrap=True, spacing=8, run_spacing=8)
        self._repos_chips: list[ft.Chip] = []

        repos_card = ft.Card(
            content=ft.Container(
                content=ft.Column([
                    ft.Text("Repos Workspaces", size=14, weight=ft.FontWeight.W_600),
                    ft.Text(
                        "Add workspace folders. Click a repo chip to toggle ignore.",
                        size=12, color=ft.Colors.ON_SURFACE_VARIANT,
                    ),
                    self._repos_paths_col,
                    ft.Row([
                        ft.ElevatedButton(
                            "+ Add Folder", bgcolor="#238636", color="white",
                            on_click=self._add_repos_workspace,
                        ),
                    ], spacing=10),
                    ft.Divider(height=1),
                    self._repos_search,
                    self._repos_chips_wrap,
                ], spacing=10),
                padding=20,
            ),
        )

        # --- Knowledge Folders ---
        self._knowledge_paths_col = ft.Column(spacing=4)
        self._knowledge_search = ft.TextField(
            hint_text="Filter knowledge...",
            dense=True,
            border_radius=8,
            text_size=12,
            prefix_icon=ft.Icons.SEARCH,
            on_change=self._on_knowledge_search,
            content_padding=ft.padding.symmetric(horizontal=12, vertical=6),
        )
        self._knowledge_chips_wrap = ft.Row(wrap=True, spacing=8, run_spacing=8)
        self._knowledge_chips: list[ft.Chip] = []

        knowledge_card = ft.Card(
            content=ft.Container(
                content=ft.Column([
                    ft.Text("Knowledge Folders", size=14, weight=ft.FontWeight.W_600),
                    ft.Text(
                        "Add knowledge folders. Click a topic chip to toggle ignore.",
                        size=12, color=ft.Colors.ON_SURFACE_VARIANT,
                    ),
                    self._knowledge_paths_col,
                    ft.Row([
                        ft.ElevatedButton(
                            "+ Add Folder", bgcolor="#238636", color="white",
                            on_click=self._add_knowledge_path,
                        ),
                    ], spacing=10),
                    ft.Divider(height=1),
                    self._knowledge_search,
                    self._knowledge_chips_wrap,
                ], spacing=10),
                padding=20,
            ),
        )

        # --- Save ---
        self._status_label = ft.Text("", size=12, color=ft.Colors.ON_SURFACE_VARIANT)
        save_btn = ft.ElevatedButton(
            "Save",
            icon=ft.Icons.SAVE,
            bgcolor=TEAL,
            color="white",
            on_click=self._save,
        )

        for card in (repos_card, knowledge_card):
            card.expand = True

        self.controls = [
            ft.Container(
                content=ft.Column([
                    ft.Text("Workspace", size=22, weight=ft.FontWeight.W_600),
                    repos_card,
                    knowledge_card,
                    ft.Row([save_btn, self._status_label], spacing=12),
                ], spacing=16, horizontal_alignment=ft.CrossAxisAlignment.STRETCH),
                padding=30,
            ),
        ]

        self._populate_paths()
        self._refresh_chips()

    def on_activate(self):
        self._refresh_chips()

    # --- Path management ---

    def _populate_paths(self):
        """Build path rows from config."""
        self._repos_paths_col.controls.clear()
        for ws in self._config.repos_workspaces:
            self._repos_paths_col.controls.append(self._path_row(ws, "repos"))
        self._knowledge_paths_col.controls.clear()
        for kp in self._config.knowledge_paths:
            self._knowledge_paths_col.controls.append(self._path_row(kp, "knowledge"))

    def _path_row(self, path: str, category: str) -> ft.Row:
        return ft.Row([
            ft.Icon(ft.Icons.FOLDER, size=16, color=ft.Colors.ON_SURFACE_VARIANT),
            ft.Text(path, size=12, expand=True, no_wrap=True, overflow=ft.TextOverflow.ELLIPSIS),
            ft.IconButton(
                icon=ft.Icons.CLOSE,
                icon_size=16,
                tooltip="Remove",
                on_click=lambda e, p=path, c=category: self._remove_path(p, c),
            ),
        ], spacing=6, vertical_alignment=ft.CrossAxisAlignment.CENTER)

    def _remove_path(self, path: str, category: str):
        if category == "repos":
            self._repos_paths_col.controls = [
                r for r in self._repos_paths_col.controls
                if not any(
                    isinstance(c, ft.Text) and c.value == path
                    for c in (r.controls if hasattr(r, "controls") else [])
                )
            ]
        else:
            self._knowledge_paths_col.controls = [
                r for r in self._knowledge_paths_col.controls
                if not any(
                    isinstance(c, ft.Text) and c.value == path
                    for c in (r.controls if hasattr(r, "controls") else [])
                )
            ]
        self._refresh_chips()
        self._page.update()

    async def _add_repos_workspace(self, e):
        path = await self._repos_picker.get_directory_path(
            dialog_title="Select Repos Workspace Folder"
        )
        if path:
            existing = self._get_repos_workspaces()
            if path not in existing:
                self._repos_paths_col.controls.append(self._path_row(path, "repos"))
                self._refresh_chips()
                self._page.update()

    async def _add_knowledge_path(self, e):
        path = await self._knowledge_picker.get_directory_path(
            dialog_title="Select Knowledge Folder"
        )
        if path:
            existing = self._get_knowledge_paths()
            if path not in existing:
                self._knowledge_paths_col.controls.append(self._path_row(path, "knowledge"))
                self._refresh_chips()
                self._page.update()

    def _get_repos_workspaces(self) -> list[str]:
        paths = []
        for row in self._repos_paths_col.controls:
            if hasattr(row, "controls"):
                for c in row.controls:
                    if isinstance(c, ft.Text) and c.value and "/" in c.value:
                        paths.append(c.value)
        return paths

    def _get_knowledge_paths(self) -> list[str]:
        paths = []
        for row in self._knowledge_paths_col.controls:
            if hasattr(row, "controls"):
                for c in row.controls:
                    if isinstance(c, ft.Text) and c.value and "/" in c.value:
                        paths.append(c.value)
        return paths

    # --- Chip management ---

    def _refresh_chips(self):
        self._refresh_repos_chips()
        self._refresh_knowledge_chips()

    def _refresh_repos_chips(self):
        self._repos_chips.clear()
        self._repos_chips_wrap.controls.clear()
        workspaces = self._get_repos_workspaces()
        if not workspaces:
            self._repos_chips_wrap.controls.append(
                ft.Text("Add a workspace folder to see repos", size=12, color=ft.Colors.OUTLINE, italic=True)
            )
            return
        try:
            from meeting_helper.context_loader import get_repos_from_workspaces
            repos = get_repos_from_workspaces(workspaces)
            if not repos:
                self._repos_chips_wrap.controls.append(
                    ft.Text("No subdirectories found", size=12, color=ft.Colors.OUTLINE, italic=True)
                )
                return
            for r in repos:
                ignored = r["name"] in self._config.ignored_repos
                chip = self._make_chip(
                    name=r["name"],
                    display=r["sanitized_name"],
                    ignored=ignored,
                    on_toggle=lambda e, n=r["name"]: self._toggle_repo_ignore(n),
                )
                self._repos_chips.append(chip)
                self._repos_chips_wrap.controls.append(chip)
        except Exception:
            self._repos_chips_wrap.controls.append(
                ft.Text("Could not scan folder", size=12, color=ft.Colors.OUTLINE, italic=True)
            )

    def _refresh_knowledge_chips(self):
        self._knowledge_chips.clear()
        self._knowledge_chips_wrap.controls.clear()
        paths = self._get_knowledge_paths()
        if not paths:
            self._knowledge_chips_wrap.controls.append(
                ft.Text("Add a knowledge folder to see topics", size=12, color=ft.Colors.OUTLINE, italic=True)
            )
            return
        try:
            from meeting_helper.context_loader import get_knowledge_trees
            tree = get_knowledge_trees(paths)
            if not tree:
                self._knowledge_chips_wrap.controls.append(
                    ft.Text("No topic folders found", size=12, color=ft.Colors.OUTLINE, italic=True)
                )
                return
            for node in tree:
                ignored = node["name"] in self._config.ignored_knowledge
                display = node["name"].replace("_", " ").replace("-", " ").title()
                chip = self._make_chip(
                    name=node["name"],
                    display=display,
                    ignored=ignored,
                    on_toggle=lambda e, n=node["name"]: self._toggle_knowledge_ignore(n),
                )
                self._knowledge_chips.append(chip)
                self._knowledge_chips_wrap.controls.append(chip)
        except Exception:
            self._knowledge_chips_wrap.controls.append(
                ft.Text("Could not scan folder", size=12, color=ft.Colors.OUTLINE, italic=True)
            )

    def _make_chip(self, name: str, display: str, ignored: bool, on_toggle) -> ft.Chip:
        """Create a chip with visual ignored/active state."""
        if ignored:
            label = ft.Text(
                display,
                size=12,
                style=ft.TextStyle(decoration=ft.TextDecoration.LINE_THROUGH),
                color=ft.Colors.OUTLINE,
            )
        else:
            label = ft.Text(display, size=12)

        return ft.Chip(
            label=label,
            leading=ft.Icon(
                ft.Icons.BLOCK if ignored else ft.Icons.CHECK_CIRCLE,
                size=14,
                color=ERROR_RED if ignored else TEAL,
            ),
            on_click=on_toggle,
            data={"name": name, "ignored": ignored},
            bgcolor=ft.Colors.ERROR_CONTAINER if ignored else None,
        )

    # --- Toggle ignore ---

    def _toggle_repo_ignore(self, name: str):
        lst = list(self._config.ignored_repos)
        if name in lst:
            lst.remove(name)
            action = "Unignored"
        else:
            lst.append(name)
            action = "Ignored"
        self._config.ignored_repos = lst
        self._config.save()
        self._sync_ignored_to_daemon()
        self._refresh_repos_chips()
        self._status_label.value = f"{action}: {name}"
        self._status_label.color = TEAL
        self._page.update()

    def _toggle_knowledge_ignore(self, name: str):
        lst = list(self._config.ignored_knowledge)
        if name in lst:
            lst.remove(name)
            action = "Unignored"
        else:
            lst.append(name)
            action = "Ignored"
        self._config.ignored_knowledge = lst
        self._config.save()
        self._sync_ignored_to_daemon()
        self._refresh_knowledge_chips()
        self._status_label.value = f"{action}: {name}"
        self._status_label.color = TEAL
        self._page.update()

    # --- Search ---

    def _on_repos_search(self, e):
        query = (e.control.value or "").lower().strip()
        for chip in self._repos_chips:
            name = chip.data["name"].lower()
            chip.visible = not query or query in name
        self._page.update()

    def _on_knowledge_search(self, e):
        query = (e.control.value or "").lower().strip()
        for chip in self._knowledge_chips:
            name = chip.data["name"].lower()
            chip.visible = not query or query in name
        self._page.update()

    # --- Sync & Save ---

    def _sync_ignored_to_daemon(self):
        port = self._config.port
        payload = json.dumps({
            "ignored_repos": list(self._config.ignored_repos),
            "ignored_knowledge": list(self._config.ignored_knowledge),
        }).encode()

        def _do():
            try:
                req = urllib.request.Request(
                    f"http://127.0.0.1:{port}/config",
                    data=payload,
                    headers={"Content-Type": "application/json"},
                    method="POST",
                )
                urllib.request.urlopen(req, timeout=3)
            except Exception:
                pass

        threading.Thread(target=_do, daemon=True).start()

    def _save(self, e):
        self._config.repos_workspaces = self._get_repos_workspaces()
        self._config.knowledge_paths = self._get_knowledge_paths()
        self._config.save()
        self._status_label.value = "Saved!"
        self._status_label.color = TEAL
        self._page.update()
