import hashlib
import struct

import pytest

from pydstl import Dstl
from pydstl.store import EMBEDDING_DIM
from pydstl.types import SkillDocument


def _deterministic_embed(text: str) -> list[float]:
    h = hashlib.sha256(text.encode()).digest()
    raw = (h * ((EMBEDDING_DIM * 4 // len(h)) + 1))[: EMBEDDING_DIM * 4]
    vec = list(struct.unpack(f"{EMBEDDING_DIM}f", raw))
    # Normalize to avoid NaN/Inf issues
    mag = sum(v * v for v in vec) ** 0.5
    if mag > 0:
        vec = [v / mag for v in vec]
    return vec


def _mock_distill(evidence_list, topic=None):
    title = topic or "General Knowledge"
    body = "\n\n".join(f"- {e.content}" for e in evidence_list)
    return SkillDocument(title=title, content=body)


def _mock_edit(current_content, instruction):
    return f"{current_content}\n\n## Edit: {instruction}"


def _mock_consolidate(documents, topic=None):
    title = topic or "Consolidated"
    body = "\n\n".join(f"## {label}\n\n{content[:200]}" for label, content in documents)
    return SkillDocument(title=title, content=body)


@pytest.fixture
def dstl_instance(tmp_path):
    db_path = str(tmp_path / "test.db")
    d = Dstl(
        db_path=db_path,
        model="test",
        embed_fn=_deterministic_embed,
        distill_fn=_mock_distill,
        edit_fn=_mock_edit,
        consolidate_fn=_mock_consolidate,
    )
    yield d
    d.close()


@pytest.fixture
def skills_dir(tmp_path):
    d = tmp_path / "skills"
    d.mkdir()
    return str(d)
