from datetime import datetime, timezone

from fastapi.testclient import TestClient
from sqlmodel import Session

from app.core.config import get_settings
from app.db.session import init_db, reset_db_for_tests
from app.main import app
from app.models.core import (
    ActivityEvent,
    AnalyticsImportBatch,
    AnalyticsPostSnapshot,
    ContentScript,
    ExternalPost,
    Idea,
    PostDraft,
    Provider,
    Theme,
    VideoAsset,
    VideoStatus,
)


def setup_test_db(tmp_path):
    settings = get_settings()
    settings.database_url = "sqlite://"
    settings.storage_root = tmp_path / "storage"
    engine = init_db(settings)
    reset_db_for_tests(engine)
    return engine, TestClient(app)


def create_video(session: Session, *, external_youtube_id: str | None = None) -> VideoAsset:
    family = Theme(title="Everyday Red Flags", priority=10, description="Scam explainers")
    session.add(family)
    session.commit()
    session.refresh(family)
    video = VideoAsset(
        candidate_id="real_video",
        package_id="package_real_001",
        source="prepared_package",
        file_path="/tmp/video.mp4",
        file_size=1,
        checksum="real-checksum",
        working_title="This Small Fee Can Expose Your Card",
        topic_id=family.id,
        series="Everyday Red Flags",
        external_youtube_id=external_youtube_id,
        status=VideoStatus.ready_for_review,
    )
    session.add(video)
    session.commit()
    session.refresh(video)
    session.add(PostDraft(video_asset_id=video.id, provider=Provider.youtube, title="YouTube CSV title", external_post_id=external_youtube_id))
    session.add(ContentScript(family_id=family.id, video_asset_id=video.id, package_id=video.package_id, title=video.working_title, hook="A tiny delivery fee can be the trap.", status="produced"))
    session.add(Idea(topic_id=family.id, title="Fake customs fee SMS", priority=99, status="idea"))
    session.commit()
    return video


def add_snapshot(session: Session, *, external_id: str, title: str, video: VideoAsset | None = None, is_demo: bool = False, views: int = 120):
    batch = AnalyticsImportBatch(provider=Provider.youtube, snapshot_at=datetime(2026, 6, 6, tzinfo=timezone.utc), status="imported", source_label="demo" if is_demo else "Youtube 260606", is_demo=is_demo, import_batch_label="demo" if is_demo else "Youtube 260606")
    session.add(batch)
    session.commit()
    post = ExternalPost(provider=Provider.youtube, external_post_id=external_id, title=title, video_asset_id=video.id if video else None, source_label=batch.source_label, is_demo=is_demo, import_batch_label=batch.import_batch_label)
    session.add(post)
    session.commit()
    session.add(AnalyticsPostSnapshot(batch_id=batch.id, provider=Provider.youtube, external_post_id=external_id, title=title, video_asset_id=video.id if video else None, views=views, views_delta=40, impression_ctr_pct=3.2, retention_proxy_pct=11.6, subscribers_delta=2, snapshot_at=batch.snapshot_at, source_label=batch.source_label, is_demo=is_demo, import_batch_label=batch.import_batch_label, trend="rising"))
    session.commit()


def test_demo_data_hidden_from_normal_results(tmp_path):
    engine, client = setup_test_db(tmp_path)
    with Session(engine) as session:
        add_snapshot(session, external_id="demo123", title="Fixture title", is_demo=True, views=999)
    response = client.get("/api/analytics/video-results")
    assert response.status_code == 200
    assert response.json()["items"] == []


def test_display_name_prefers_linked_package_title(tmp_path):
    engine, client = setup_test_db(tmp_path)
    with Session(engine) as session:
        video = create_video(session, external_youtube_id="yt_real_1")
        add_snapshot(session, external_id="yt_real_1", title="CSV title should be subline", video=video)
    item = client.get("/api/analytics/video-results").json()["items"][0]
    assert item["title"] == "This Small Fee Can Expose Your Card"
    assert item["youtube_title"] == "CSV title should be subline"
    assert item["package_id"] == "package_real_001"


def test_mapping_by_youtube_video_id_works(tmp_path):
    engine, client = setup_test_db(tmp_path)
    with Session(engine) as session:
        video = create_video(session, external_youtube_id="yt_match")
        add_snapshot(session, external_id="yt_match", title="Different title", video=None)
        video_id = video.id
    response = client.post("/api/analytics/map-post", json={"external_post_id": "yt_match", "video_asset_id": video_id})
    assert response.status_code == 200
    item = client.get("/api/analytics/video-results").json()["items"][0]
    assert item["linked"] is True
    assert item["package_id"] == "package_real_001"


def test_content_family_and_recommendation_endpoints(tmp_path):
    engine, client = setup_test_db(tmp_path)
    with Session(engine) as session:
        video = create_video(session, external_youtube_id="yt_reco")
        add_snapshot(session, external_id="yt_reco", title="CSV", video=video)
    families = client.get("/api/content/families").json()
    assert families["summary"]["families_count"] == 1
    assert families["items"][0]["scripts_count"] == 1
    rec = client.get("/api/content/recommendations/next").json()
    assert rec["family"] == "Everyday Red Flags"
    assert rec["recommended_action"] in {"produce_variant", "add_idea"}


def test_settings_and_logs_endpoints(tmp_path):
    engine, client = setup_test_db(tmp_path)
    with Session(engine) as session:
        session.add(ActivityEvent(entity_type="video", entity_id="v1", event_type="metadata_saved", label="Metadata saved", payload_json={"token": "secret"}))
        session.commit()
    updated = client.patch("/api/settings", json={"google_drive_analytics_folder": "TrueTraceShorts/Analyse/Youtube 260606", "demo_mode": False})
    assert updated.status_code == 200
    assert updated.json()["settings"]["demo_mode"] is False
    logs = client.get("/api/logs").json()["items"]
    assert logs
    assert logs[0]["payload"].get("token") == "[REDACTED]"
