"""Core symlink management logic."""

from __future__ import annotations

import os
from pathlib import Path

from sympath.utils import is_executable


class SymlinkManager:
    """Manages symlink folders and the links they contain."""

    def __init__(self, config: dict) -> None:
        self.config = config

    # ---- folder operations ------------------------------------------------

    def add_folder(self, name: str, path: str) -> None:
        """Register a new link directory."""
        resolved = Path(path).resolve()
        self.config["folders"][name] = str(resolved)

        if self.config["default"] is None:
            self.config["default"] = name

        print(f"Registered folder '{name}' → {resolved}")

    def set_default(self, name: str) -> None:
        """Set *name* as the default link directory."""
        if name not in self.config["folders"]:
            raise ValueError(f"Folder '{name}' is not registered")

        self.config["default"] = name
        print(f"Default folder set → {name}")

    def get_folder(self, name: str | None = None) -> Path:
        """Return the Path for a named (or default) folder."""
        if name is None:
            name = self.config.get("default")

        if name is None or name not in self.config["folders"]:
            raise ValueError(
                "No folder specified and no default is set. "
                "Run 'sympath add-folder <name> <path>' first."
            )

        return Path(self.config["folders"][name])

    # ---- link operations --------------------------------------------------

    def create_link(
        self,
        target: str,
        folder: str | None = None,
        name: str | None = None,
        force: bool = False,
    ) -> None:
        """Create a symlink pointing to *target* inside a link directory."""
        target_path = Path(target).resolve()

        if not target_path.exists():
            print(f"Error: target does not exist — {target_path}")
            return

        link_dir = self.get_folder(folder)
        link_dir.mkdir(parents=True, exist_ok=True)

        link_name = name if name else target_path.name
        link_path = link_dir / link_name

        if link_path.exists() or link_path.is_symlink():
            if force:
                link_path.unlink()
            else:
                print(f"Link already exists: {link_path}  (use --force to overwrite)")
                return

        os.symlink(target_path, link_path)
        print(f"  {link_path.name} → {target_path}")

    def remove_link(self, name: str, folder: str | None = None) -> None:
        """Remove a managed symlink."""
        link_dir = self.get_folder(folder)
        link_path = link_dir / name

        if link_path.exists() or link_path.is_symlink():
            link_path.unlink()
            print(f"Removed: {link_path}")
        else:
            print(f"Link not found: {name}")

    def list_links(self, folder: str | None = None) -> None:
        """Print all symlinks in a link directory."""
        link_dir = self.get_folder(folder)

        if not link_dir.exists():
            print(f"Folder does not exist yet: {link_dir}")
            return

        found = False
        for p in sorted(link_dir.iterdir()):
            if p.is_symlink():
                found = True
                target = p.resolve()
                status = "" if target.exists() else "  [BROKEN]"
                print(f"  {p.name} → {target}{status}")

        if not found:
            print("  (no managed links)")

    def repair(self, folder: str | None = None) -> None:
        """Report (and optionally clean) broken symlinks."""
        link_dir = self.get_folder(folder)

        if not link_dir.exists():
            print(f"Folder does not exist: {link_dir}")
            return

        broken = []
        for p in sorted(link_dir.iterdir()):
            if p.is_symlink() and not p.resolve().exists():
                broken.append(p)
                print(f"  Broken: {p}")

        if not broken:
            print("  All links are healthy.")

    def link_folder(
        self,
        folder_path: str,
        folder: str | None = None,
        force: bool = False,
    ) -> None:
        """Link every executable found inside *folder_path*."""
        src = Path(folder_path)

        if not src.exists():
            print(f"Error: folder not found — {src}")
            return

        for item in sorted(src.iterdir()):
            if item.is_file() and is_executable(item):
                self.create_link(str(item), folder=folder, force=force)
