"""Upgrade suite — test version upgrade path."""

from __future__ import annotations

import re
from typing import TYPE_CHECKING

from tests.remote.suites.base import BaseSuite, StepStatus, SuiteResult

if TYPE_CHECKING:
    from tests.remote.runner import RemoteTestRunner

VERSION_PATTERN = re.compile(r"(\d+\.\d+\.\d+)")


class UpgradeSuite(BaseSuite):
    name = "upgrade"
    description = "Test pip upgrade path and verify new version"

    async def execute(self, runner: RemoteTestRunner, result: SuiteResult) -> None:
        # Step 1: Record current version
        r = await runner.run_command("llmhosts --version", timeout=15.0)
        old_version = ""
        if r.success:
            match = VERSION_PATTERN.search(r.stdout)
            old_version = match.group(1) if match else r.stdout.strip()

        self._add_step(
            result,
            "record_version",
            f"Current version: {old_version or 'unknown'}",
            status=StepStatus.PASSED if old_version else StepStatus.FAILED,
            stdout=r.stdout,
            duration_s=r.duration_s,
            error_message="" if old_version else "Could not determine current version",
        )

        if not old_version:
            return

        # Step 2: Run upgrade
        r = await runner.run_command("pip install --upgrade llmhosts", timeout=300.0)
        self._add_step(
            result,
            "pip_upgrade",
            "Run pip install --upgrade llmhosts",
            status=StepStatus.PASSED if r.success else StepStatus.FAILED,
            stdout=r.stdout,
            stderr=r.stderr,
            duration_s=r.duration_s,
            error_message="" if r.success else f"Upgrade failed (exit={r.exit_code})",
        )

        if not r.success:
            return

        # Step 3: Verify new version
        r = await runner.run_command("llmhosts --version", timeout=15.0)
        new_version = ""
        if r.success:
            match = VERSION_PATTERN.search(r.stdout)
            new_version = match.group(1) if match else r.stdout.strip()

        version_ok = bool(new_version) and new_version >= old_version
        self._add_step(
            result,
            "verify_upgrade",
            f"Version after upgrade: {new_version} (was {old_version})",
            status=StepStatus.PASSED if version_ok else StepStatus.FAILED,
            stdout=r.stdout,
            duration_s=r.duration_s,
            error_message="" if version_ok else f"Version did not advance: {old_version} -> {new_version}",
        )

        # Step 4: Run doctor to validate
        r = await runner.run_command("llmhosts doctor", timeout=120.0)
        has_traceback = "traceback" in r.stdout.lower() or "exception" in r.stdout.lower()
        self._add_step(
            result,
            "post_upgrade_doctor",
            "Run doctor after upgrade",
            status=StepStatus.PASSED if r.success and not has_traceback else StepStatus.FAILED,
            stdout=r.stdout,
            stderr=r.stderr,
            duration_s=r.duration_s,
            error_message="Doctor failed after upgrade" if not r.success or has_traceback else "",
        )
