from __future__ import annotations

from datetime import UTC, datetime

from fastapi import HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models.chat import ChatSession, TopicSession
from app.models.growth import ShareDraft, TopicSummary
from app.models.user import User
from app.core.auth_context import ChatAccessScope
from app.services.content_generation_config_service import ContentGenerationConfigService
from app.services.chat_service import chat_scope_filters
from app.services.entitlement_service import EntitlementService
from app.services.growth_profile_service import GrowthProfileService, topic_summary_dict


class ShareDraftService:
    @staticmethod
    def generate_for_session(db: Session, *, user: User, session: ChatSession) -> ShareDraft:
        entitlement = EntitlementService.active_entitlement(db, user)
        if not entitlement.allow_share_draft:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="当前权益暂不支持生成班级分享稿")

        topic = _latest_topic(db, user=user, session=session)
        if topic is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="当前会话还没有可生成分享稿的主题")

        summary = GrowthProfileService.generate_topic_summary(db, user=user, topic=topic)
        content, _ = ContentGenerationConfigService.generate_content(
            db,
            config_type="share_draft",
            values=_share_draft_values(topic=topic, summary=summary),
            user_id=user.id,
        )
        draft = ShareDraft(
            user_id=user.id,
            topic_session_id=topic.id,
            summary_id=summary.id,
            content=content,
            source="topic_summary",
        )
        topic.share_draft_generated = 1
        db.add_all([topic, draft])
        db.commit()
        db.refresh(draft)
        return draft

    @staticmethod
    def list_user_drafts(
        db: Session,
        *,
        user: User,
        scope: ChatAccessScope | None = None,
        limit: int = 20,
    ) -> list[ShareDraft]:
        scope = scope or ChatAccessScope.direct()
        return list(
            db.scalars(
                select(ShareDraft)
                .join(TopicSession, TopicSession.id == ShareDraft.topic_session_id)
                .join(ChatSession, ChatSession.id == TopicSession.chat_session_id)
                .where(ShareDraft.user_id == user.id, *chat_scope_filters(scope))
                .order_by(ShareDraft.created_at.desc(), ShareDraft.id.desc())
                .limit(limit)
            )
        )

    @staticmethod
    def mark_copied(
        db: Session,
        *,
        user: User,
        draft_id: int,
        scope: ChatAccessScope | None = None,
    ) -> ShareDraft:
        draft = _user_draft(db, user=user, draft_id=draft_id, scope=scope)
        if draft is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="分享稿不存在")
        draft.copied = 1
        draft.copied_at = _now()
        db.add(draft)
        db.commit()
        db.refresh(draft)
        return draft

    @staticmethod
    def delete(
        db: Session,
        *,
        user: User,
        draft_id: int,
        scope: ChatAccessScope | None = None,
    ) -> None:
        draft = _user_draft(db, user=user, draft_id=draft_id, scope=scope)
        if draft is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="分享稿不存在")
        db.delete(draft)
        db.commit()


def share_draft_dict(draft: ShareDraft) -> dict:
    return {
        "id": draft.id,
        "userId": draft.user_id,
        "topicSessionId": draft.topic_session_id,
        "summaryId": draft.summary_id,
        "content": draft.content,
        "source": draft.source,
        "copied": bool(draft.copied),
        "copiedAt": draft.copied_at,
        "createdAt": draft.created_at,
    }


def _latest_topic(db: Session, *, user: User, session: ChatSession) -> TopicSession | None:
    return db.scalar(
        select(TopicSession)
        .where(TopicSession.user_id == user.id, TopicSession.chat_session_id == session.id)
        .order_by(TopicSession.updated_at.desc(), TopicSession.id.desc())
        .limit(1)
    )


def _share_draft_values(*, topic: TopicSession, summary: TopicSummary) -> dict[str, str]:
    data = topic_summary_dict(summary) or {}
    return {
        "topic_title": topic.title,
        "issue": topic.core_question or topic.title,
        "summary": data.get("summary") or "（请用自己的话补充）",
        "current_focus": data.get("currentFocus") or "（请补充）",
        "next_observation": data.get("nextObservation") or "（请补充）",
    }


def _now() -> datetime:
    return datetime.now(UTC).replace(tzinfo=None)


def _user_draft(
    db: Session,
    *,
    user: User,
    draft_id: int,
    scope: ChatAccessScope | None,
) -> ShareDraft | None:
    scope = scope or ChatAccessScope.direct()
    return db.scalar(
        select(ShareDraft)
        .join(TopicSession, TopicSession.id == ShareDraft.topic_session_id)
        .join(ChatSession, ChatSession.id == TopicSession.chat_session_id)
        .where(
            ShareDraft.id == draft_id,
            ShareDraft.user_id == user.id,
            *chat_scope_filters(scope),
        )
    )
