from __future__ import annotations

from datetime import UTC, datetime
from typing import Any

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.db.models import Publication, ScholarProfile, ScholarPublication
from app.services.portability.constants import EXPORT_SCHEMA_VERSION


def _exported_at_iso() -> str:
    return datetime.now(UTC).replace(microsecond=0).isoformat()


def _serialize_export_scholar(profile: ScholarProfile) -> dict[str, Any]:
    return {
        "scholar_id": profile.scholar_id,
        "display_name": profile.display_name,
        "is_enabled": bool(profile.is_enabled),
        "profile_image_override_url": profile.profile_image_override_url,
    }


def _serialize_export_publication(row: tuple[Any, ...]) -> dict[str, Any]:
    (
        scholar_id,
        cluster_id,
        fingerprint_sha256,
        title_raw,
        year,
        citation_count,
        author_text,
        venue_text,
        pub_url,
        pdf_url,
        is_read,
    ) = row
    return {
        "scholar_id": scholar_id,
        "cluster_id": cluster_id,
        "fingerprint_sha256": fingerprint_sha256,
        "title": title_raw,
        "year": year,
        "citation_count": int(citation_count or 0),
        "author_text": author_text,
        "venue_text": venue_text,
        "pub_url": pub_url,
        "pdf_url": pdf_url,
        "is_read": bool(is_read),
    }


async def export_user_data(
    db_session: AsyncSession,
    *,
    user_id: int,
) -> dict[str, Any]:
    scholars_result = await db_session.execute(
        select(ScholarProfile).where(ScholarProfile.user_id == user_id).order_by(ScholarProfile.id.asc())
    )
    publication_result = await db_session.execute(
        select(
            ScholarProfile.scholar_id,
            Publication.cluster_id,
            Publication.fingerprint_sha256,
            Publication.title_raw,
            Publication.year,
            Publication.citation_count,
            Publication.author_text,
            Publication.venue_text,
            Publication.pub_url,
            Publication.pdf_url,
            ScholarPublication.is_read,
        )
        .join(ScholarPublication, ScholarPublication.scholar_profile_id == ScholarProfile.id)
        .join(Publication, Publication.id == ScholarPublication.publication_id)
        .where(ScholarProfile.user_id == user_id)
        .order_by(ScholarPublication.created_at.desc(), Publication.id.desc())
    )
    scholars = [_serialize_export_scholar(profile) for profile in scholars_result.scalars().all()]
    publications = [_serialize_export_publication(row) for row in publication_result.all()]
    return {
        "schema_version": EXPORT_SCHEMA_VERSION,
        "exported_at": _exported_at_iso(),
        "scholars": scholars,
        "publications": publications,
    }
