"""Tests for cumulative ingest — append mode preserves existing chunks."""

from __future__ import annotations

import pytest

from hcp.protocol import HCPProtocol
from hcp.types import ContextChunk, ContentType


SAMPLE_A = "Bismillahirrahmanirrahim.  İlk metin."
SAMPLE_B = "İkinci metin.  Kudret-i İlahiye."
SAMPLE_C = "Üçüncü metin.  Hakîm ismi."


@pytest.fixture()
def proto() -> HCPProtocol:
    return HCPProtocol()


class TestAppendMode:
    """append=True (default) extends chunks without destroying old ones."""

    def test_default_is_append(self, proto):
        proto.ingest(SAMPLE_A)
        n = len(proto._chunks)
        proto.ingest(SAMPLE_B)
        assert len(proto._chunks) > n

    def test_positions_are_offset(self, proto):
        proto.ingest(SAMPLE_A)
        first_positions = {c.position for c in proto._chunks}
        max_first = max(first_positions)

        proto.ingest(SAMPLE_B, append=True)
        second_positions = {c.position for c in proto._chunks} - first_positions
        assert all(p > max_first for p in second_positions)

    def test_three_sequential_ingests(self, proto):
        proto.ingest(SAMPLE_A)
        n1 = len(proto._chunks)
        proto.ingest(SAMPLE_B)
        n2 = len(proto._chunks)
        proto.ingest(SAMPLE_C)
        n3 = len(proto._chunks)
        assert n3 > n2 > n1

    def test_all_positions_unique(self, proto):
        proto.ingest(SAMPLE_A)
        proto.ingest(SAMPLE_B)
        proto.ingest(SAMPLE_C)
        positions = [c.position for c in proto._chunks]
        assert len(positions) == len(set(positions))


class TestReplaceMode:
    """append=False replaces all existing chunks."""

    def test_replace_clears_old(self, proto):
        proto.ingest(SAMPLE_A)
        proto.ingest(SAMPLE_B, append=False)
        # Only SAMPLE_B chunks remain
        texts = " ".join(c.content for c in proto._chunks)
        assert SAMPLE_A not in texts

    def test_replace_keeps_new(self, proto):
        proto.ingest(SAMPLE_A)
        proto.ingest(SAMPLE_B, append=False)
        assert len(proto._chunks) > 0
        texts = " ".join(c.content for c in proto._chunks)
        # B content should be present in at least one chunk
        assert any(
            word in texts for word in SAMPLE_B.split()[:2]
        )


class TestAppendWithChunks:
    """ingest_chunks also supports append."""

    def test_ingest_chunks_append(self, proto):
        chunk_a = ContextChunk(
            content="Alpha", position=0,
            content_type=ContentType.FACT,
            keywords=("alpha",),
        )
        chunk_b = ContextChunk(
            content="Beta", position=0,
            content_type=ContentType.FACT,
            keywords=("beta",),
        )
        proto.ingest_chunks([chunk_a])
        proto.ingest_chunks([chunk_b], append=True)
        assert len(proto._chunks) == 2
        contents = {c.content for c in proto._chunks}
        assert contents == {"Alpha", "Beta"}

    def test_ingest_chunks_replace(self, proto):
        chunk_a = ContextChunk(
            content="Alpha", position=0,
            content_type=ContentType.FACT,
            keywords=("alpha",),
        )
        chunk_b = ContextChunk(
            content="Beta", position=0,
            content_type=ContentType.FACT,
            keywords=("beta",),
        )
        proto.ingest_chunks([chunk_a])
        proto.ingest_chunks([chunk_b], append=False)
        assert len(proto._chunks) == 1
        assert proto._chunks[0].content == "Beta"

    def test_offset_positions_in_append(self, proto):
        chunk_a = ContextChunk(
            content="Alpha", position=0,
            content_type=ContentType.FACT,
            keywords=("alpha",),
        )
        chunk_b = ContextChunk(
            content="Beta", position=0,
            content_type=ContentType.FACT,
            keywords=("beta",),
        )
        proto.ingest_chunks([chunk_a])
        proto.ingest_chunks([chunk_b], append=True)
        positions = sorted(c.position for c in proto._chunks)
        # chunk_b should get position = 0 + 1 = 1
        assert positions == [0, 1]
