import asyncio
from dataclasses import dataclass, field
import logging
from typing import Any, Dict, List, Optional, Set, Tuple

from .database import upsert_task_record


@dataclass
class Task:
    id: str
    iocs: list[str]
    status: str = "queued"  # состояния: queued, processing, done, error
    results: Dict[str, Dict[str, Any]] = field(default_factory=dict)
    verdicts: Dict[str, List[Dict[str, Any]]] = field(default_factory=dict)
    processed: Set[str] = field(default_factory=set)
    error: Optional[str] = None
    input_text: Optional[str] = None


# Хранилище в памяти
_tasks: Dict[str, Task] = {}
queue: asyncio.Queue[Tuple[str, str]] = asyncio.Queue()

logger = logging.getLogger(__name__)


async def add_task(
    task_id: str,
    iocs: list[str],
    input_text: str | None = None,
) -> Task:
    if task_id in _tasks:
        raise ValueError(f"Задание {task_id} уже существует")
    task = Task(id=task_id, iocs=iocs, input_text=input_text)
    _tasks[task_id] = task
    for ioc in task.iocs:
        await queue.put((task_id, ioc))
    await upsert_task_record(
        task_id,
        status=task.status,
        iocs=task.iocs,
        results=task.results,
        verdicts=task.verdicts,
        processed=sorted(task.processed),
        error=task.error,
        input_text=task.input_text,
    )
    logger.info(
        "Задание %s поставлено в очередь с %d индикатор(ами)",
        task_id,
        len(iocs),
    )
    logger.debug("Параметры задания %s: %s", task_id, iocs)
    return task


def get_task(task_id: str) -> Optional[Task]:
    logger.debug("Получаем задачу %s из памяти", task_id)
    return _tasks.get(task_id)


async def sync_task(task: Task) -> None:
    await upsert_task_record(
        task.id,
        status=task.status,
        iocs=task.iocs,
        results=task.results,
        verdicts=task.verdicts,
        processed=sorted(task.processed),
        error=task.error,
        input_text=task.input_text,
    )


def get_queue_load() -> Dict[str, int]:
    active_tasks = [task for task in _tasks.values() if len(task.processed) < len(task.iocs)]
    queued_iocs = queue.qsize()
    logger.debug(
        "Состояние очереди: %d активных задач, %d IOC ожидают обработки",
        len(active_tasks),
        queued_iocs,
    )
    return {"queued_tasks": len(active_tasks), "queued_iocs": queued_iocs}
