from __future__ import annotations

import asyncio
import socket
import shutil
import uuid
from pathlib import Path

from cliproom.cli import _request_server_stop, _run_server_start
from cliproom.cli_state import LocalCLIState


def _free_port() -> int:
    sock = socket.socket()
    sock.bind(("127.0.0.1", 0))
    port = int(sock.getsockname()[1])
    sock.close()
    return port


def test_server_stop_signal_flow(monkeypatch) -> None:
    state_dir = Path(".test_state") / str(uuid.uuid4())
    state_dir.mkdir(parents=True, exist_ok=True)
    monkeypatch.setenv("CLIPROOM_STATE_DIR", str(state_dir))

    async def scenario() -> None:
        port = _free_port()
        discovery_port = _free_port()
        task = asyncio.create_task(
            _run_server_start(
                host="127.0.0.1",
                port=port,
                fixed_session="devteam",
                fixed_auth_hash="h1",
                discovery_port=discovery_port,
                enable_discovery=False,
            )
        )
        state = LocalCLIState()
        for _ in range(20):
            payload = state.read_server_state() or {}
            if payload.get("status") == "running":
                break
            await asyncio.sleep(0.1)
        payload = state.read_server_state() or {}
        assert payload.get("status") == "running"

        _request_server_stop(wait_seconds=0)
        await asyncio.wait_for(task, timeout=5)

        payload = state.read_server_state() or {}
        assert payload.get("status") == "stopped"
        assert payload.get("active") is False

    try:
        asyncio.run(scenario())
    finally:
        shutil.rmtree(state_dir, ignore_errors=True)
