import re
import shutil
import subprocess
from datetime import datetime
from pathlib import Path


class WorktreeManager:
    def __init__(self, base_repo: str, worktrees_dir: str = "workspaces"):
        self.base_repo = Path(base_repo).resolve()
        self.worktrees_dir = self.base_repo / worktrees_dir
        self.worktrees_dir.mkdir(parents=True, exist_ok=True)

    def _sanitize(self, name: str) -> str:
        """Vytvoří bezpečný název větve/adresáře."""
        name = re.sub(r'[^a-zA-Z0-9\-]', '-', name)
        name = re.sub(r'-+', '-', name)
        name = name.strip('-')
        if len(name) > 50:
            name = name[:50]
        return name

    def create_worktree(self, task_id: str, branch_name: str | None = None) -> dict:
        if not branch_name:
            safe_name = self._sanitize(task_id)
            timestamp = datetime.utcnow().strftime("%Y%m%d%H%M%S")
            branch_name = f"task/{safe_name}-{timestamp}"
        # Použijeme task_id jako název složky (bez diakritiky)
        folder_name = self._sanitize(task_id)
        target_path = self.worktrees_dir / folder_name
        if target_path.exists():
            raise FileExistsError(f"Worktree pro {task_id} již existuje.")
        cmd = [
            "git", "-C", str(self.base_repo),
            "worktree", "add", "-b", branch_name,
            str(target_path), "HEAD"
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
        if result.returncode != 0:
            raise RuntimeError(f"Git worktree add selhal: {result.stderr}")
        return {
            "task_id": task_id,
            "branch": branch_name,
            "path": str(target_path),
            "created_at": datetime.utcnow().isoformat()
        }

    def get_worktree_path(self, task_id: str) -> Path | None:
        # Pokusíme se najít podle task_id
        folder_name = self._sanitize(task_id)
        path = self.worktrees_dir / folder_name
        if path.exists():
            return path
        # Zpětná kompatibilita: hledáme podle task_id jako celého jména
        path2 = self.worktrees_dir / task_id
        if path2.exists():
            return path2
        return None

    # Ostatní metody beze změny...
    def list_worktrees(self) -> list[dict]:
        cmd = ["git", "-C", str(self.base_repo), "worktree", "list", "--porcelain"]
        result = subprocess.run(cmd, capture_output=True, text=True)
        if result.returncode != 0:
            return []
        worktrees = []
        current: dict = {}
        for line in result.stdout.splitlines():
            if line.startswith("worktree "):
                if current:
                    worktrees.append(current)
                current = {"path": line.split(" ", 1)[1].strip()}
            elif line.startswith("HEAD "):
                current["head"] = line.split(" ", 1)[1].strip()
            elif line.startswith("branch "):
                current["branch"] = line.split(" ", 1)[1].strip()
            elif line.startswith("detached"):
                current["detached"] = True
        if current:
            worktrees.append(current)
        return worktrees

    def get_diff(self, task_id: str, base_branch: str = "lab/phase-3a") -> str:
        worktree_path = self.get_worktree_path(task_id)
        if not worktree_path:
            raise FileNotFoundError(f"Worktree pro {task_id} neexistuje.")
        cmd = [
            "git", "-C", str(worktree_path),
            "diff", base_branch, "--no-color"
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
        return result.stdout

    def apply_patch(self, task_id: str, patch_content: str) -> dict:
        worktree_path = self.get_worktree_path(task_id)
        if not worktree_path:
            raise FileNotFoundError(f"Worktree pro {task_id} neexistuje.")
        patch_file = worktree_path / "temp.patch"
        patch_file.write_text(patch_content)
        cmd = ["git", "-C", str(worktree_path), "apply", str(patch_file)]
        result = subprocess.run(cmd, capture_output=True, text=True)
        patch_file.unlink(missing_ok=True)
        if result.returncode != 0:
            raise RuntimeError(f"Patch selhal: {result.stderr}")
        return {"applied": True, "message": "Patch aplikován."}

    def merge_worktree(self, task_id: str, target_branch: str = "lab/phase-3a") -> dict:
        worktree_path = self.get_worktree_path(task_id)
        if not worktree_path:
            raise FileNotFoundError(f"Worktree pro {task_id} neexistuje.")
        subprocess.run(["git", "-C", str(worktree_path), "add", "."], check=True, capture_output=True)
        subprocess.run(["git", "-C", str(worktree_path), "commit", "-m", f"Merge task {task_id}"], check=True, capture_output=True)
        subprocess.run(["git", "-C", str(worktree_path), "checkout", target_branch], check=True, capture_output=True)
        subprocess.run(["git", "-C", str(worktree_path), "merge", f"task/{task_id}", "--no-ff", "-m", f"Merge task {task_id}"], check=True, capture_output=True)
        return {"merged": True, "target_branch": target_branch}

    def remove_worktree(self, task_id: str, force: bool = False):
        worktree_path = self.get_worktree_path(task_id)
        if not worktree_path:
            return
        cmd = ["git", "-C", str(self.base_repo), "worktree", "remove", str(worktree_path)]
        if force:
            cmd.append("--force")
        subprocess.run(cmd, check=True, capture_output=True)
        shutil.rmtree(worktree_path, ignore_errors=True)
