from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Final


ANSI_ESCAPE_RE: Final[re.Pattern[str]] = re.compile(r"\x1b\[[0-9;]*m")
URL_RE: Final[re.Pattern[str]] = re.compile(r"https://\S+")
CODE_RE: Final[re.Pattern[str]] = re.compile(r"[A-Z0-9]{4}-[A-Z0-9]{4,5}")


@dataclass(frozen=True)
class DeviceAuthPromptParts:
    url: str
    code: str
    raw_text: str


class DeviceAuthProtocol:
    def feed(self, buffered_text: str, chunk: str) -> tuple[str, DeviceAuthPromptParts | None]:
        text = buffered_text + self.strip_ansi(chunk)
        return text, self.extract_prompt(text)

    @staticmethod
    def strip_ansi(text: str) -> str:
        return ANSI_ESCAPE_RE.sub("", text)

    @staticmethod
    def extract_prompt(raw_text: str) -> DeviceAuthPromptParts | None:
        url_match = URL_RE.search(raw_text)
        code_match = CODE_RE.search(raw_text)
        if url_match is None or code_match is None:
            return None
        return DeviceAuthPromptParts(
            url=url_match.group(0),
            code=code_match.group(0),
            raw_text=raw_text,
        )
