from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any, AsyncIterator

from leshy.core.models import AttackConfig, AttackPayload, EvalConfig
from leshy.core.session import SessionContext


class Attack(ABC):
    """Abstract base class for all attacks."""

    name: str = ""
    category: str = ""
    description: str = ""
    default_evaluators: list[EvalConfig] = []

    def __init__(self, config: AttackConfig | None = None, **kwargs: Any) -> None:
        self.config = config or AttackConfig(name=self.name)

    @abstractmethod
    def generate_payloads(self) -> list[AttackPayload]:
        """Generate single-turn attack payloads."""
        ...

    async def generate_turns(self, session: SessionContext) -> AsyncIterator[AttackPayload]:
        """Generate payloads for multi-turn attacks. Override for stateful attacks."""
        for payload in self.generate_payloads():
            yield payload

    def _make_payload(self, content: str, turn: int = 0, **metadata: Any) -> AttackPayload:
        """Helper to create an AttackPayload with consistent fields."""
        return AttackPayload(
            id=f"{self.name}:{turn}:{hash(content) & 0xFFFFFFFF:08x}",
            content=content,
            attack_name=self.name,
            category=self.category,
            turn=turn,
            metadata=metadata,
        )
