"""Tests for knowledge export/import.

Cycles 16-20/40: JSON round-trip, Markdown export, selective export,
import with duplicate detection, file I/O.
"""
import json
from datetime import datetime, timedelta

import pytest

_has_sqlite_vec = True
try:
    import sqlite_vec  # noqa: F401
except ImportError:
    _has_sqlite_vec = False


@pytest.fixture
def db(tmp_path):
    from greymatter_core.db import SQLiteDatabase
    return SQLiteDatabase(str(tmp_path / "export_test.db"))


def _insert_knowledge(db, entry_id, title, content, entry_type="pattern",
                       domain="general", created_days_ago=0):
    created = datetime.now() - timedelta(days=created_days_ago)
    db._conn.execute(
        "INSERT INTO knowledge_entries (id, entry_type, title, content, domain, "
        "scope, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
        (entry_id, entry_type, title, content, domain, "cross-cutting",
         created.isoformat(), created.isoformat()),
    )
    db._conn.commit()


def _insert_observation(db, obs_id, title, content, category="general"):
    db._conn.execute(
        "INSERT INTO observations (id, session_id, trigger, title, content, category) "
        "VALUES (?, 'test', 'test', ?, ?, ?)",
        (obs_id, title, content, category),
    )
    db._conn.commit()


# =========================================================================
# JSON Export
# =========================================================================


@pytest.mark.skipif(not _has_sqlite_vec, reason="sqlite_vec not installed")
class TestJSONExport:

    def test_empty_export(self, db):
        from greymatter_core.export import KnowledgeExporter
        exporter = KnowledgeExporter(db)
        data = exporter.to_json()
        assert data["format"] == "greymatter-export"
        assert data["version"] == "1.0"
        assert data["counts"]["knowledge_entries"] == 0

    def test_basic_export(self, db):
        from greymatter_core.export import KnowledgeExporter
        _insert_knowledge(db, "e1", "Test entry", "Some content")
        exporter = KnowledgeExporter(db)
        data = exporter.to_json()
        assert data["counts"]["knowledge_entries"] == 1
        assert data["knowledge_entries"][0]["title"] == "Test entry"

    def test_domain_filter(self, db):
        from greymatter_core.export import KnowledgeExporter
        _insert_knowledge(db, "e1", "Python tip", "content", domain="python")
        _insert_knowledge(db, "e2", "Docker tip", "content", domain="docker")

        exporter = KnowledgeExporter(db)
        data = exporter.to_json(domain="python")
        assert data["counts"]["knowledge_entries"] == 1
        assert data["knowledge_entries"][0]["title"] == "Python tip"

    def test_type_filter(self, db):
        from greymatter_core.export import KnowledgeExporter
        _insert_knowledge(db, "e1", "Correction", "fix", entry_type="correction")
        _insert_knowledge(db, "e2", "Pattern", "habit", entry_type="pattern")

        exporter = KnowledgeExporter(db)
        data = exporter.to_json(entry_type="correction")
        assert data["counts"]["knowledge_entries"] == 1

    def test_includes_observations(self, db):
        from greymatter_core.export import KnowledgeExporter
        _insert_observation(db, "o1", "Saw something", "detail", "deployment")

        exporter = KnowledgeExporter(db)
        data = exporter.to_json(include_observations=True)
        assert data["counts"]["observations"] >= 1

    def test_excludes_observations(self, db):
        from greymatter_core.export import KnowledgeExporter
        _insert_observation(db, "o1", "Saw something", "detail")

        exporter = KnowledgeExporter(db)
        data = exporter.to_json(include_observations=False)
        assert "observations" not in data

    def test_file_export(self, db, tmp_path):
        from greymatter_core.export import KnowledgeExporter
        _insert_knowledge(db, "e1", "Test", "Content")

        exporter = KnowledgeExporter(db)
        out_path = str(tmp_path / "export.json")
        counts = exporter.to_json_file(out_path)

        assert counts["knowledge_entries"] == 1
        with open(out_path) as f:
            data = json.load(f)
        assert data["format"] == "greymatter-export"


# =========================================================================
# Markdown Export
# =========================================================================


@pytest.mark.skipif(not _has_sqlite_vec, reason="sqlite_vec not installed")
class TestMarkdownExport:

    def test_basic_markdown(self, db):
        from greymatter_core.export import KnowledgeExporter
        _insert_knowledge(db, "e1", "Pytest fixtures", "Use fixtures for setup",
                          domain="python")

        exporter = KnowledgeExporter(db)
        md = exporter.to_markdown()
        assert "# GreyMatter Knowledge Export" in md
        assert "## python" in md
        assert "### Pytest fixtures" in md
        assert "Use fixtures for setup" in md

    def test_grouped_by_domain(self, db):
        from greymatter_core.export import KnowledgeExporter
        _insert_knowledge(db, "e1", "Py tip", "content", domain="python")
        _insert_knowledge(db, "e2", "Docker tip", "content", domain="docker")

        exporter = KnowledgeExporter(db)
        md = exporter.to_markdown()
        assert "## docker" in md
        assert "## python" in md

    def test_file_export(self, db, tmp_path):
        from greymatter_core.export import KnowledgeExporter
        _insert_knowledge(db, "e1", "Entry", "Content")

        exporter = KnowledgeExporter(db)
        out_path = str(tmp_path / "export.md")
        count = exporter.to_markdown_file(out_path)
        assert count == 1


# =========================================================================
# JSON Import
# =========================================================================


@pytest.mark.skipif(not _has_sqlite_vec, reason="sqlite_vec not installed")
class TestJSONImport:

    def test_round_trip(self, db):
        """Export then import into fresh DB preserves entries."""
        from greymatter_core.export import KnowledgeExporter, KnowledgeImporter

        _insert_knowledge(db, "e1", "Test entry", "Important knowledge",
                          entry_type="correction", domain="python")

        exporter = KnowledgeExporter(db)
        data = exporter.to_json()

        # Import into same DB — should skip (duplicate)
        importer = KnowledgeImporter(db)
        result = importer.from_json(data)
        assert result["skipped"] == 1
        assert result["imported"] == 0

    def test_import_new_entries(self, db, tmp_path):
        """Import adds entries that don't exist."""
        from greymatter_core.db import SQLiteDatabase
        from greymatter_core.export import KnowledgeExporter, KnowledgeImporter

        # Create and export from source DB
        source_db = SQLiteDatabase(str(tmp_path / "source.db"))
        _insert_knowledge(source_db, "s1", "Source entry", "Knowledge from source",
                          entry_type="expertise", domain="testing")
        exporter = KnowledgeExporter(source_db)
        data = exporter.to_json()

        # Import into target DB
        importer = KnowledgeImporter(db)
        result = importer.from_json(data)
        assert result["imported"] == 1
        assert result["skipped"] == 0

    def test_dedup_on_import(self, db, tmp_path):
        """Duplicate entries (same title + type) are skipped."""
        from greymatter_core.export import KnowledgeImporter

        _insert_knowledge(db, "existing", "Python testing", "Use pytest")

        data = {
            "format": "greymatter-export",
            "version": "1.0",
            "knowledge_entries": [
                {"entry_type": "pattern", "title": "Python testing",
                 "content": "Different content but same title"},
            ],
        }
        importer = KnowledgeImporter(db)
        result = importer.from_json(data)
        assert result["skipped"] == 1

    def test_invalid_format_rejected(self, db):
        from greymatter_core.export import KnowledgeImporter
        importer = KnowledgeImporter(db)
        result = importer.from_json({"format": "wrong"})
        assert "error" in result

    def test_file_import(self, db, tmp_path):
        from greymatter_core.export import KnowledgeExporter, KnowledgeImporter

        _insert_knowledge(db, "e1", "File test", "Content")
        exporter = KnowledgeExporter(db)
        path = str(tmp_path / "test.json")
        exporter.to_json_file(path)

        # Remove original and reimport
        db._conn.execute("DELETE FROM knowledge_entries WHERE id = 'e1'")
        db._conn.commit()

        importer = KnowledgeImporter(db)
        result = importer.from_json_file(path)
        assert result["imported"] == 1
