# #region TestDictionaryImport [C:3] [TYPE Module] [SEMANTICS test, dictionary, import, export]
# @BRIEF Validate DictionaryImportExport operations.
# @RELATION BINDS_TO -> [DictionaryImportExport]
# @TEST_EDGE  import_invalid_format -> ValueError for missing required columns

import csv
import io
import pytest

from sqlalchemy import create_engine, event
from sqlalchemy.orm import Session, sessionmaker

from src.models.translate import Base
from src.plugins.translate.dictionary import DictionaryManager


# region db_session [TYPE Fixture]
@pytest.fixture
def db_session():
    engine = create_engine("sqlite:///:memory:", echo=False)
    @event.listens_for(engine, "connect")
    def _set_sqlite_pragma(dbapi_connection, connection_record):
        cursor = dbapi_connection.cursor()
        cursor.execute("PRAGMA foreign_keys=ON")
        cursor.close()
    Base.metadata.create_all(bind=engine)
    session = sessionmaker(bind=engine)()
    try:
        yield session
    finally:
        session.close()
        Base.metadata.drop_all(bind=engine)
# endregion db_session


class TestImportOverwrite:
    """Verify CSV import with overwrite conflict mode."""

    # region test_import_csv_overwrite [C:2] [TYPE Function]
    def test_import_csv_overwrite(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
        DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")

        csv_content = "source_term,target_term,context_notes,source_language,target_language\nhello,HELLO,,en,es\nworld,mundo,,en,es"
        result = DictionaryManager.import_entries(db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite")
        assert result["total"] == 2
        assert result["created"] == 1
        assert result["updated"] == 1
        assert result["skipped"] == 0

        entries, _ = DictionaryManager.list_entries(db_session, d.id)
        hello_entry = [e for e in entries if e.source_term_normalized == "hello"][0]
        assert hello_entry.target_term == "HELLO"
    # endregion test_import_csv_overwrite


class TestImportKeepExisting:
    """Verify CSV import with keep_existing conflict mode."""

    # region test_import_csv_keep_existing [C:2] [TYPE Function]
    def test_import_csv_keep_existing(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
        DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")

        csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
        result = DictionaryManager.import_entries(db_session, d.id, csv_content, delimiter=",", on_conflict="keep_existing")
        assert result["created"] == 1
        assert result["updated"] == 0
        assert result["skipped"] == 1

        entries, _ = DictionaryManager.list_entries(db_session, d.id)
        hello_entry = [e for e in entries if e.source_term_normalized == "hello"][0]
        assert hello_entry.target_term == "hola"
    # endregion test_import_csv_keep_existing


class TestImportCancel:
    """Verify CSV import with cancel conflict mode."""

    # region test_import_csv_cancel_on_conflict [C:2] [TYPE Function]
    def test_import_csv_cancel_on_conflict(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
        DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")

        csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
        result = DictionaryManager.import_entries(db_session, d.id, csv_content, delimiter=",", on_conflict="cancel")
        assert result["total"] == 2
        assert result["created"] == 1
        assert result["updated"] == 0
        assert len(result["errors"]) == 1
        assert "Conflict" in result["errors"][0]["error"]
    # endregion test_import_csv_cancel_on_conflict


class TestImportFormat:
    """Verify import format handling."""

    # region test_import_tsv [C:2] [TYPE Function]
    def test_import_tsv(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
        tsv_content = "source_term\ttarget_term\tsource_language\ttarget_language\nhello\thola\ten\tes\nworld\tmundo\ten\tes"
        result = DictionaryManager.import_entries(db_session, d.id, tsv_content, delimiter="\t", on_conflict="overwrite")
        assert result["created"] == 2
        assert result["total"] == 2
    # endregion test_import_tsv

    # region test_import_invalid_format [C:2] [TYPE Function]
    def test_import_invalid_format(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
        with pytest.raises(ValueError, match="source_term"):
            DictionaryManager.import_entries(db_session, d.id, "name,value\nhello,hola", delimiter=",", on_conflict="overwrite")
    # endregion test_import_invalid_format

    # region test_import_empty_rows [C:2] [TYPE Function]
    def test_import_empty_rows(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
        csv_content = "source_term,target_term\nhello,hola\n,world\nfoo,"
        result = DictionaryManager.import_entries(db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite")
        assert result["created"] == 1
        assert len(result["errors"]) == 2
    # endregion test_import_empty_rows

    # region test_import_preview [C:2] [TYPE Function]
    def test_import_preview(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
        DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")

        csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
        result = DictionaryManager.import_entries(db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite", preview_only=True)
        assert len(result["preview"]) == 2
        assert result["preview"][0]["is_conflict"] is True
        assert result["preview"][0]["existing_target_term"] == "hola"
        assert result["preview"][1]["is_conflict"] is False

        entries, total = DictionaryManager.list_entries(db_session, d.id)
        assert total == 1
    # endregion test_import_preview


class TestExportEntries:
    """Verify export functionality."""

    # region test_export_entries [C:2] [TYPE Function]
    def test_export_entries(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Export Test", source_dialect="a", target_dialect="b")
        DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
        DictionaryManager.add_entry(db_session, d.id, "world", "мир", source_language="en", target_language="ru")

        csv_output = DictionaryManager.export_entries(db_session, d.id)
        assert "source_language" in csv_output
        assert "target_language" in csv_output
        assert "en" in csv_output
        assert "ru" in csv_output

        reader = csv.DictReader(io.StringIO(csv_output))
        rows = list(reader)
        assert len(rows) == 2
        assert rows[0]["source_language"] == "en"
        assert rows[0]["target_language"] == "ru"
    # endregion test_export_entries

    # region test_import_with_default_language [C:2] [TYPE Function]
    def test_import_with_default_language(self, db_session: Session):
        d = DictionaryManager.create_dictionary(db_session, name="Default Lang Import", source_dialect="a", target_dialect="b")
        csv_content = "source_term,target_term\nhello,привет\nworld,мир"
        result = DictionaryManager.import_entries(
            db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite",
            default_source_language="en", default_target_language="ru",
        )
        assert result["created"] == 2

        entries, _ = DictionaryManager.list_entries(db_session, d.id)
        for e in entries:
            assert e.source_language == "en"
            assert e.target_language == "ru"
    # endregion test_import_with_default_language
# #endregion TestDictionaryImport
