"""
Tests pour ScrapingPipeline.
"""

from dataclasses import dataclass
from datetime import datetime

import pytest

from pricewatch.app.core.schema import DebugInfo, DebugStatus, FetchMethod, ProductSnapshot
from pricewatch.app.db.connection import get_session, init_db, reset_engine
from pricewatch.app.db.models import Product
from pricewatch.app.scraping.pipeline import ScrapingPipeline


@dataclass
class FakeDbConfig:
    url: str


@dataclass
class FakeAppConfig:
    db: FakeDbConfig
    debug: bool = False
    enable_db: bool = True


@pytest.fixture(autouse=True)
def reset_db_engine():
    """Reset l'engine global entre les tests."""
    reset_engine()
    yield
    reset_engine()


def test_pipeline_persists_snapshot():
    """Le pipeline persiste un snapshot en base SQLite."""
    config = FakeAppConfig(db=FakeDbConfig(url="sqlite:///:memory:"))
    init_db(config)

    snapshot = ProductSnapshot(
        source="amazon",
        url="https://example.com/product",
        fetched_at=datetime(2026, 1, 14, 12, 30, 0),
        title="Produit pipeline",
        price=99.99,
        currency="EUR",
        reference="B08PIPE",
        debug=DebugInfo(method=FetchMethod.HTTP, status=DebugStatus.SUCCESS),
    )

    pipeline = ScrapingPipeline(config=config)
    product_id = pipeline.process_snapshot(snapshot, save_to_db=True)

    assert product_id is not None

    with get_session(config) as session:
        assert session.query(Product).count() == 1


def test_pipeline_respects_disable_flag():
    """Le pipeline ignore la persistence si enable_db=False."""
    config = FakeAppConfig(db=FakeDbConfig(url="sqlite:///:memory:"), enable_db=False)
    init_db(config)

    snapshot = ProductSnapshot(
        source="amazon",
        url="https://example.com/product",
        fetched_at=datetime(2026, 1, 14, 12, 45, 0),
        title="Produit pipeline",
        price=99.99,
        currency="EUR",
        reference="B08PIPE",
        debug=DebugInfo(method=FetchMethod.HTTP, status=DebugStatus.SUCCESS),
    )

    pipeline = ScrapingPipeline(config=config)
    product_id = pipeline.process_snapshot(snapshot, save_to_db=True)

    assert product_id is None
    with get_session(config) as session:
        assert session.query(Product).count() == 0


def test_pipeline_db_error_adds_note(monkeypatch):
    """Une erreur DB ajoute une note et retourne None."""
    from sqlalchemy.exc import SQLAlchemyError

    class DummyError(SQLAlchemyError):
        pass

    def raise_session(*args, **kwargs):
        raise DummyError("db down")

    monkeypatch.setattr("pricewatch.app.scraping.pipeline.get_session", raise_session)

    snapshot = ProductSnapshot(
        source="amazon",
        url="https://example.com/product",
        fetched_at=datetime(2026, 1, 14, 13, 0, 0),
        title="Produit",
        price=10.0,
        currency="EUR",
        reference="B08PIPE",
        debug=DebugInfo(method=FetchMethod.HTTP, status=DebugStatus.SUCCESS),
    )

    pipeline = ScrapingPipeline(config=FakeAppConfig(db=FakeDbConfig(url="sqlite:///:memory:")))
    product_id = pipeline.process_snapshot(snapshot, save_to_db=True)

    assert product_id is None
    assert any("Persistence DB echouee" in note for note in snapshot.debug.notes)
