"""Clipboard monitoring sensor."""

from __future__ import annotations

import hashlib
import platform
import re
import subprocess
from collections import deque
from typing import Optional

from neurovault.sensors.base import BaseSensor


class ClipboardSensor(BaseSensor):
    """Watch OS clipboard for new content."""

    MIN_LENGTH = 10
    MAX_LENGTH = 50000

    name = "clipboard"
    source_tag = "clipboard"
    poll_interval = 2.0

    def __init__(self):
        self._last_hash: Optional[str] = None
        self._recent_hashes: deque[str] = deque(maxlen=20)
        self._system = platform.system()

    def poll(self) -> list[tuple[str, dict]]:
        content = self._read_clipboard()
        if not content:
            return []

        content = content.strip()
        if len(content) < self.MIN_LENGTH:
            return []

        content_hash = hashlib.sha256(content.encode()).hexdigest()
        if content_hash == self._last_hash or content_hash in self._recent_hashes:
            return []

        self._last_hash = content_hash
        self._recent_hashes.append(content_hash)

        if len(content) > self.MAX_LENGTH:
            content = content[: self.MAX_LENGTH] + "\n... [truncated]"

        content_type = self._classify(content)
        return [
            (
                content,
                {
                    "content_type": content_type,
                    "char_count": len(content),
                },
            )
        ]

    def _read_clipboard(self) -> Optional[str]:
        try:
            if self._system == "Darwin":
                result = subprocess.run(
                    ["pbpaste"],
                    capture_output=True,
                    text=True,
                    timeout=2,
                )
                return result.stdout if result.returncode == 0 else None
            if self._system == "Linux":
                result = subprocess.run(
                    ["xclip", "-selection", "clipboard", "-o"],
                    capture_output=True,
                    text=True,
                    timeout=2,
                )
                return result.stdout if result.returncode == 0 else None
            if self._system == "Windows":
                import ctypes

                cf_unicode_text = 13
                ctypes.windll.user32.OpenClipboard(0)
                try:
                    handle = ctypes.windll.user32.GetClipboardData(cf_unicode_text)
                    if handle:
                        return ctypes.c_wchar_p(handle).value
                finally:
                    ctypes.windll.user32.CloseClipboard()
            return None
        except Exception:
            return None

    def _classify(self, content: str) -> str:
        if content.startswith(("http://", "https://")):
            return "url"
        if re.match(r"^\s*[\[{]", content):
            return "json"
        code_keywords = ["def ", "function ", "class ", "import ", "const ", "var ", "let "]
        if any(keyword in content for keyword in code_keywords):
            return "code"
        if re.match(r"^[/~]|^[A-Z]:\\", content):
            return "path"
        return "text"
