"""
Model tests for DataImport and DataExport
"""

import pytest

pytestmark = [pytest.mark.unit, pytest.mark.models]

from datetime import datetime, timedelta
from app import create_app, db
from app.models import User, DataImport, DataExport


@pytest.fixture
def app():
    """Create application for testing (minimal config to avoid circular imports)."""
    app = create_app(
        {
            "TESTING": True,
            "SQLALCHEMY_DATABASE_URI": "sqlite:///:memory:",
            "WTF_CSRF_ENABLED": False,
            "FLASK_ENV": "testing",
            "SECRET_KEY": "test-secret-key-do-not-use-in-production-1234567890",
        }
    )
    with app.app_context():
        db.create_all()
        user = User(username="testuser", role="user")
        db.session.add(user)
        db.session.commit()
        yield app
        db.session.remove()
        db.drop_all()


class TestDataImportModel:
    """Test DataImport model"""

    def test_create_import(self, app):
        """Test creating a data import record"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()

            data_import = DataImport(user_id=user.id, import_type="csv", source_file="test.csv")
            db.session.add(data_import)
            db.session.commit()

            assert data_import.id is not None
            assert data_import.user_id == user.id
            assert data_import.import_type == "csv"
            assert data_import.source_file == "test.csv"
            assert data_import.status == "pending"
            assert data_import.total_records == 0
            assert data_import.successful_records == 0
            assert data_import.failed_records == 0

    def test_import_lifecycle(self, app):
        """Test import record lifecycle"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            # Create import
            data_import = DataImport(user_id=user.id, import_type="toggl", source_file="Toggl Workspace 12345")
            db.session.add(data_import)
            db.session.commit()

            # Start processing
            data_import.start_processing()
            assert data_import.status == "processing"

            # Update progress
            data_import.update_progress(100, 95, 5)
            assert data_import.total_records == 100
            assert data_import.successful_records == 95
            assert data_import.failed_records == 5

            # Partial complete
            data_import.partial_complete()
            assert data_import.status == "partial"
            assert data_import.completed_at is not None

    def test_import_complete(self, app):
        """Test import completion"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_import = DataImport(user_id=user.id, import_type="harvest")
            db.session.add(data_import)
            db.session.commit()

            data_import.start_processing()
            data_import.update_progress(50, 50, 0)
            data_import.complete()

            assert data_import.status == "completed"
            assert data_import.completed_at is not None

    def test_import_fail(self, app):
        """Test import failure"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_import = DataImport(user_id=user.id, import_type="csv")
            db.session.add(data_import)
            db.session.commit()

            data_import.start_processing()
            data_import.fail("Connection error")

            assert data_import.status == "failed"
            assert data_import.completed_at is not None
            assert data_import.error_log is not None

    def test_import_add_error(self, app):
        """Test adding errors to import"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_import = DataImport(user_id=user.id, import_type="csv")
            db.session.add(data_import)
            db.session.commit()

            data_import.add_error("Invalid date format", {"row": 5})
            data_import.add_error("Missing project", {"row": 10})

            import json

            errors = json.loads(data_import.error_log)
            assert len(errors) == 2
            assert errors[0]["error"] == "Invalid date format"

    def test_import_set_summary(self, app):
        """Test setting import summary"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_import = DataImport(user_id=user.id, import_type="csv")
            db.session.add(data_import)
            db.session.commit()

            summary = {"total": 100, "successful": 95, "failed": 5, "duration": 30.5}
            data_import.set_summary(summary)

            import json

            stored_summary = json.loads(data_import.import_summary)
            assert stored_summary["total"] == 100
            assert stored_summary["duration"] == 30.5

    def test_import_to_dict(self, app):
        """Test converting import to dictionary"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_import = DataImport(user_id=user.id, import_type="csv", source_file="test.csv")
            db.session.add(data_import)
            db.session.commit()

            data_import.update_progress(10, 8, 2)

            import_dict = data_import.to_dict()

            assert import_dict["id"] == data_import.id
            assert import_dict["user"] == "testuser"
            assert import_dict["import_type"] == "csv"
            assert import_dict["total_records"] == 10
            assert import_dict["successful_records"] == 8
            assert import_dict["failed_records"] == 2


class TestDataExportModel:
    """Test DataExport model"""

    def test_create_export(self, app):
        """Test creating a data export record"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_export = DataExport(user_id=user.id, export_type="gdpr", export_format="json")
            db.session.add(data_export)
            db.session.commit()

            assert data_export.id is not None
            assert data_export.user_id == user.id
            assert data_export.export_type == "gdpr"
            assert data_export.export_format == "json"
            assert data_export.status == "pending"

    def test_export_lifecycle(self, app):
        """Test export record lifecycle"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            # Create export
            data_export = DataExport(user_id=user.id, export_type="filtered", export_format="csv")
            db.session.add(data_export)
            db.session.commit()

            # Start processing
            data_export.start_processing()
            assert data_export.status == "processing"

            # Complete
            data_export.complete("/tmp/export.csv", 2048, 150)
            assert data_export.status == "completed"
            assert data_export.file_path == "/tmp/export.csv"
            assert data_export.file_size == 2048
            assert data_export.record_count == 150
            assert data_export.completed_at is not None
            assert data_export.expires_at is not None

    def test_export_fail(self, app):
        """Test export failure"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_export = DataExport(user_id=user.id, export_type="backup", export_format="json")
            db.session.add(data_export)
            db.session.commit()

            data_export.start_processing()
            data_export.fail("Disk full")

            assert data_export.status == "failed"
            assert data_export.error_message == "Disk full"
            assert data_export.completed_at is not None

    def test_export_with_filters(self, app):
        """Test export with filters"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            filters = {"start_date": "2024-01-01", "end_date": "2024-12-31", "project_id": 5, "billable_only": True}

            data_export = DataExport(user_id=user.id, export_type="filtered", export_format="json", filters=filters)
            db.session.add(data_export)
            db.session.commit()

            import json

            stored_filters = json.loads(data_export.filters)
            assert stored_filters["start_date"] == "2024-01-01"
            assert stored_filters["billable_only"] is True

    def test_export_expiration(self, app):
        """Test export expiration"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_export = DataExport(user_id=user.id, export_type="gdpr", export_format="json")
            db.session.add(data_export)
            db.session.commit()

            # Not expired yet
            assert not data_export.is_expired()

            # Complete and check expiration
            data_export.complete("/tmp/test.json", 1024, 100)
            assert not data_export.is_expired()  # Should expire in 7 days

            # Set expiration to past
            data_export.expires_at = datetime.utcnow() - timedelta(days=1)
            db.session.commit()

            assert data_export.is_expired()

    def test_export_to_dict(self, app):
        """Test converting export to dictionary"""
        with app.app_context():
            user = User.query.filter_by(username="testuser").first()
            data_export = DataExport(user_id=user.id, export_type="gdpr", export_format="zip")
            db.session.add(data_export)
            db.session.commit()

            data_export.complete("/tmp/export.zip", 4096, 500)

            export_dict = data_export.to_dict()

            assert export_dict["id"] == data_export.id
            assert export_dict["user"] == "testuser"
            assert export_dict["export_type"] == "gdpr"
            assert export_dict["export_format"] == "zip"
            assert export_dict["file_size"] == 4096
            assert export_dict["record_count"] == 500
            assert "expires_at" in export_dict
            assert "is_expired" in export_dict
