from __future__ import annotations

import json
import time
from pathlib import Path

from armorer.config import resolve_armorer_config_dir
from armorer.core.memory_schema import DurableMemoryRecord


def memory_store_path() -> Path:
    root = resolve_armorer_config_dir()
    path = root / "memory" / "durable_memory.json"
    path.parent.mkdir(parents=True, exist_ok=True)
    return path


def load_memory_records() -> list[DurableMemoryRecord]:
    path = memory_store_path()
    if not path.exists():
        return []
    try:
        raw = json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return []
    if not isinstance(raw, list):
        return []
    records: list[DurableMemoryRecord] = []
    for item in raw:
        if not isinstance(item, dict):
            continue
        try:
            records.append(DurableMemoryRecord(**item))
        except Exception:
            continue
    return records


def save_memory_records(records: list[DurableMemoryRecord]) -> None:
    path = memory_store_path()
    serializable = [record.model_dump(mode="json") for record in records]
    path.write_text(json.dumps(serializable, indent=2, sort_keys=True), encoding="utf-8")


def upsert_memory_record(record: DurableMemoryRecord) -> DurableMemoryRecord:
    records = load_memory_records()
    now = time.time()
    retained: list[DurableMemoryRecord] = []
    replaced = False
    for existing in records:
        if existing.is_expired(now):
            continue
        if (
            existing.kind == record.kind
            and existing.subject == record.subject
            and existing.scope == record.scope
        ):
            retained.append(record)
            replaced = True
        else:
            retained.append(existing)
    if not replaced:
        retained.append(record)
    save_memory_records(retained)
    return record


def list_memory_records(*, include_expired: bool = False) -> list[DurableMemoryRecord]:
    now = time.time()
    records = load_memory_records()
    if include_expired:
        return records
    return [record for record in records if not record.is_expired(now)]

