"""
Stress tests for the Flex-O ID lifecycle.
Focus: collision avoidance, version ceiling, reproducibility.
"""

import copy
import logging
import random

import pytest
from uuid import uuid4
from flexoentity import FlexOID, EntityType, EntityState, FlexoSignature

logger = logging.getLogger(__name__)

def test_bulk_generation_uniqueness(sample_domain):
    """
    Generate 100,000 IDs and ensure uniqueness using safe_generate().
    If a collision occurs, safe_generate() must resolve it automatically
    via salt + date adjustment.
    """
    entity_type = EntityType.ITEM
    estate = EntityState.DRAFT
    seeds = [f"question {i}" for i in range(100000)]

    # Simulate a simple in-memory repository for collision detection
    repo = {}

    def repo_get(oid_str):
        return repo.get(str(oid_str))

    # Generate IDs using safe_generate
    ids = []
    for seed in seeds:
        oid = FlexOID.safe_generate(sample_domain.domain_id, entity_type.value,
                                    estate.value, seed, repo=repo)
        assert isinstance(oid, FlexOID)
        ids.append(str(oid))
        repo[str(oid)] = oid  # register for future collision detection

    unique_count = len(set(ids))
    total_count = len(ids)
    collisions = total_count - unique_count

    logger.info(f"Generated {total_count} IDs ({collisions} collisions handled).")

    # Assert that safe_generate avoided duplicates
    assert total_count == unique_count, f"Unexpected duplicate IDs ({collisions} found)"

    # Sanity check: IDs should look canonical
    # assert all(id_str.startswith("GENERIC") for id_str in ids)
    assert all("@" in id_str for id_str in ids)

def test_id_generation_is_deterministic(sample_domain):
    """
    Generating the same entity twice with same inputs yields identical ID.
    (No runtime disambiguation; IDs are deterministic by design.)
    """
    entity_type = EntityType.ITEM
    estate = EntityState.DRAFT
    text = "identical question text"

    id1 = FlexOID.generate(sample_domain.domain_id, entity_type.value, estate.value, text)
    id2 = FlexOID.generate(sample_domain.domain_id, entity_type.value, estate.value, text)
    # IDs must be identical because generation is deterministic
    assert id1 == id2

def test_massive_lifecycle_simulation(cert_ref_linux, sample_domain):
    """
    Generate 100 random FlexoSignatures, mutate content, run through lifecycle,
    and ensure all FlexOIDs are unique and valid.
    """
    entities = []

    for i in range(100):
        sig = FlexoSignature.with_domain_id(
            domain_id="SIGTEST",
            signed_entity=sample_domain.flexo_id,
            signer_id=uuid4(),
            certificate_reference=cert_ref_linux,
            comment=f"Initial signature #{i}"
        )
        entities.append(sig)

    # Mutate + lifecycle transitions
    for i, e in enumerate(entities):
        # CONTENT CHANGE → fingerprint changes → hash → FlexOID.prefix changes
        e.comment += f" updated-{i}"
        e._update_fingerprint()

        # lifecycle transitions
        e.approve()
        if random.random() > 0.3:
            e.sign()
        if random.random() > 0.6:
            e.publish()

    # Check ID uniqueness
    flexoids = [str(e.flexo_id) for e in entities]
    assert len(flexoids) == len(set(flexoids)), "Duplicate FlexOIDs detected"
