"""Patcher interface for eval harness.

A patcher receives a prompt (plus a context directory path) and returns a single
unified diff that can be applied with `git apply`.
"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from .payload_types import ContextRequestPayload, PatcherMeta


@dataclass(frozen=True)
class PatchResult:
    diff: str | None
    meta: PatcherMeta | None = None


@dataclass(frozen=True)
class ContextRequestResult:
    request_json: ContextRequestPayload | None
    raw_response: str | None = None
    meta: PatcherMeta | None = None


@dataclass(frozen=True)
class ContextCompactionResult:
    compacted_text: str | None
    raw_response: str | None = None
    meta: PatcherMeta | None = None


class Patcher:
    name: str

    def request_context(
        self,
        *,
        prompt: str,
        context_dir: Path,
        cwd: Path,
        strict_json_first: bool = False,
    ) -> ContextRequestResult | None:
        del strict_json_first
        return None

    async def arequest_context(
        self,
        *,
        prompt: str,
        context_dir: Path,
        cwd: Path,
        strict_json_first: bool = False,
    ) -> ContextRequestResult | None:
        return self.request_context(
            prompt=prompt,
            context_dir=context_dir,
            cwd=cwd,
            strict_json_first=strict_json_first,
        )

    def compact_context(
        self,
        *,
        prompt: str,
        context_text: str,
        context_dir: Path,
        cwd: Path,
        target_chars: int,
    ) -> ContextCompactionResult | None:
        return None

    async def acompact_context(
        self,
        *,
        prompt: str,
        context_text: str,
        context_dir: Path,
        cwd: Path,
        target_chars: int,
    ) -> ContextCompactionResult | None:
        return self.compact_context(
            prompt=prompt,
            context_text=context_text,
            context_dir=context_dir,
            cwd=cwd,
            target_chars=target_chars,
        )

    def propose_patch(self, *, prompt: str, context_dir: Path, cwd: Path) -> PatchResult:
        raise NotImplementedError

    async def apropose_patch(self, *, prompt: str, context_dir: Path, cwd: Path) -> PatchResult:
        return self.propose_patch(prompt=prompt, context_dir=context_dir, cwd=cwd)
