"""
Immune system framework for trading agents.

Users register their own checks. Zero provides the structure:
run all checks, fix failures, log everything.
"""

import asyncio
import time
from dataclasses import dataclass, field
from typing import Callable


@dataclass
class Check:
    name: str
    check: Callable[[], bool]   # returns True if OK
    fix: Callable[[], bool]     # returns True if fixed


@dataclass
class CycleResult:
    checks_run: int
    checks_passed: int
    saves: int


@dataclass
class LogEntry:
    timestamp: float
    check_name: str
    passed: bool
    fixed: bool


class ImmuneProtocol:
    def __init__(self):
        self.checks: list[Check] = []
        self.log: list[LogEntry] = []

    def register_check(self, check: Check):
        self.checks.append(check)

    async def run_cycle(self) -> CycleResult:
        checks_run = 0
        checks_passed = 0
        saves = 0

        for check in self.checks:
            checks_run += 1
            ts = time.time()

            try:
                if asyncio.iscoroutinefunction(check.check):
                    ok = await check.check()
                else:
                    ok = check.check()
            except Exception:
                ok = False

            if ok:
                checks_passed += 1
                self.log.append(LogEntry(
                    timestamp=ts, check_name=check.name,
                    passed=True, fixed=False,
                ))
                continue

            # Check failed — attempt fix
            fixed = False
            try:
                if asyncio.iscoroutinefunction(check.fix):
                    fixed = await check.fix()
                else:
                    fixed = check.fix()
            except Exception:
                fixed = False

            if fixed:
                saves += 1

            self.log.append(LogEntry(
                timestamp=ts, check_name=check.name,
                passed=False, fixed=fixed,
            ))

        return CycleResult(
            checks_run=checks_run,
            checks_passed=checks_passed,
            saves=saves,
        )
