from dataclasses import dataclass, field
from enum import Enum
from typing import ClassVar, Generic, TypeVar

T = TypeVar("T")

class ErrorKind(str, Enum):
 NETWORK = "network"
 AUTH = "auth"
 QUOTA = "quota"
 RATE_LIMIT = "rate_limit"
 BALANCE = "balance"
 PERMISSION = "permission"
 NOT_FOUND = "not_found"
 INVALID_INPUT = "invalid_input"
 NOT_READY = "not_ready"
 UNKNOWN = "unknown"
 CONFIG = "config"
 INTERNAL = "internal"

@dataclass(frozen=True)
class ErrorInfo:
 kind: ErrorKind
 message: str
 source: str = ""
 original: BaseException | None = None
 def ui_message(self) -> str:
  src = f"[{self.source}] " if self.source else ""
  return f"{src}{self.kind.value}: {self.message}"

@dataclass(frozen=True)
class Result(Generic[T]):
 data: T
 errors: list[ErrorInfo] = field(default_factory=list)
 @property
 def ok(self) -> bool:
  return not self.errors
 def with_error(self, err: ErrorInfo) -> "Result[T]":
  return Result(data=self.data, errors=[*self.errors, err])
 def with_errors(self, new_errors: list[ErrorInfo]) -> "Result[T]":
  return Result(data=self.data, errors=[*self.errors, *new_errors])
 def with_data(self, new_data: T) -> "Result[T]":
  return Result(data=new_data, errors=list(self.errors))

@dataclass(frozen=True)
class NilPath:
 exists: bool = False
 read_text: str = ""
 errors: ClassVar[list[ErrorInfo]] = []

NIL_PATH = NilPath()

@dataclass(frozen=True)
class NilRAGState:
 enabled: bool = False
 is_empty_result: bool = True
 errors: ClassVar[list[ErrorInfo]] = []

NIL_RAG_STATE = NilRAGState()

OK = Result(data=None)
