import hashlib
import pytest
from pathlib import Path
from transduck.storage import TranslationStore


@pytest.fixture
def store(tmp_path):
    db_path = tmp_path / "test.duckdb"
    s = TranslationStore(db_path)
    s.initialize()
    return s


def _hash(text: str) -> str:
    return hashlib.sha256(text.encode()).hexdigest()


def test_initialize_creates_table(store):
    result = store.query("SELECT count(*) FROM translations")
    assert result[0][0] == 0


def test_insert_and_lookup(store):
    store.insert(
        source_text="Hello",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
        translated_text="Hallo",
        model="gpt-4.1-mini",
        status="translated",
    )
    result = store.lookup(
        source_text="Hello",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
    )
    assert result == "Hallo"


def test_lookup_miss_returns_none(store):
    result = store.lookup(
        source_text="Missing",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
    )
    assert result is None


def test_lookup_skips_failed(store):
    store.insert(
        source_text="Bad",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
        translated_text="bad translation",
        model="gpt-4.1-mini",
        status="failed",
    )
    result = store.lookup(
        source_text="Bad",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
    )
    assert result is None


def test_duplicate_insert_does_not_error(store):
    kwargs = dict(
        source_text="Hello",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
        translated_text="Hallo",
        model="gpt-4.1-mini",
        status="translated",
    )
    store.insert(**kwargs)
    store.insert(**kwargs)  # should not raise
    result = store.lookup(
        source_text="Hello",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
    )
    assert result == "Hallo"


def test_schema_v2_has_plural_category(store):
    """Verify the v2 schema includes plural_category in the table."""
    result = store.query(
        "SELECT column_name FROM information_schema.columns "
        "WHERE table_name = 'translations' AND column_name = 'plural_category'"
    )
    assert len(result) == 1


def test_insert_and_lookup_with_empty_plural_category(store):
    """Regular ait() rows use empty string plural_category."""
    store.insert(
        source_text="Hello", source_lang="EN", target_lang="DE",
        project_context_hash=_hash("ctx"), string_context_hash=_hash(""),
        translated_text="Hallo", model="gpt-4.1-mini",
    )
    result = store.lookup(
        source_text="Hello", source_lang="EN", target_lang="DE",
        project_context_hash=_hash("ctx"), string_context_hash=_hash(""),
    )
    assert result == "Hallo"


def test_insert_plural_and_lookup_plural(store):
    categories = {"one": "1 Nachricht", "other": "{count} Nachrichten"}
    source_key = "{count} message\x00{count} messages"
    for cat, text in categories.items():
        store.insert_plural(
            source_text=source_key, source_lang="EN", target_lang="DE",
            project_context_hash=_hash("ctx"), string_context_hash=_hash(""),
            plural_category=cat, translated_text=text, model="gpt-4.1-mini",
        )
    result = store.lookup_plural(
        source_text=source_key, source_lang="EN", target_lang="DE",
        project_context_hash=_hash("ctx"), string_context_hash=_hash(""),
    )
    assert result == {"one": "1 Nachricht", "other": "{count} Nachrichten"}


def test_lookup_plural_returns_empty_dict_on_miss(store):
    result = store.lookup_plural(
        source_text="missing", source_lang="EN", target_lang="DE",
        project_context_hash=_hash("ctx"), string_context_hash=_hash(""),
    )
    assert result == {}


def test_lookup_plural_skips_failed(store):
    store.insert_plural(
        source_text="key", source_lang="EN", target_lang="DE",
        project_context_hash=_hash("ctx"), string_context_hash=_hash(""),
        plural_category="one", translated_text="bad", model="gpt-4.1-mini",
        status="failed",
    )
    result = store.lookup_plural(
        source_text="key", source_lang="EN", target_lang="DE",
        project_context_hash=_hash("ctx"), string_context_hash=_hash(""),
    )
    assert result == {}


def test_migration_from_v1(tmp_path):
    """Test that v1 databases get migrated to v2."""
    import duckdb
    db_path = tmp_path / "v1.duckdb"
    conn = duckdb.connect(str(db_path))
    conn.execute("""
        CREATE TABLE translations (
            source_text TEXT NOT NULL, source_lang TEXT NOT NULL,
            target_lang TEXT NOT NULL, project_context_hash TEXT NOT NULL,
            string_context_hash TEXT NOT NULL, translated_text TEXT NOT NULL,
            model TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'translated',
            created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY(source_text, source_lang, target_lang, project_context_hash, string_context_hash)
        )
    """)
    conn.execute(
        "INSERT INTO translations (source_text, source_lang, target_lang, project_context_hash, "
        "string_context_hash, translated_text, model) VALUES (?, ?, ?, ?, ?, ?, ?)",
        ["Hello", "EN", "DE", "hash1", "hash2", "Hallo", "gpt-4.1-mini"]
    )
    conn.close()

    store = TranslationStore(db_path)
    store.initialize()

    # Should have migrated — plural_category column should exist
    result = store.query(
        "SELECT column_name FROM information_schema.columns "
        "WHERE table_name = 'translations' AND column_name = 'plural_category'"
    )
    assert len(result) == 1

    # Old data should still be accessible
    result = store.lookup(
        source_text="Hello", source_lang="EN", target_lang="DE",
        project_context_hash="hash1", string_context_hash="hash2",
    )
    assert result == "Hallo"
    store.close()


def test_stats(store):
    store.insert(
        source_text="Hello",
        source_lang="EN",
        target_lang="DE",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
        translated_text="Hallo",
        model="gpt-4.1-mini",
        status="translated",
    )
    store.insert(
        source_text="Hello",
        source_lang="EN",
        target_lang="ES",
        project_context_hash=_hash("ctx"),
        string_context_hash=_hash(""),
        translated_text="Hola",
        model="gpt-4.1-mini",
        status="translated",
    )
    stats = store.stats()
    assert stats["total_translations"] == 2
    assert stats["by_language"]["DE"] == 1
    assert stats["by_language"]["ES"] == 1
    assert stats["total_failed"] == 0
