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 TeacherHelpCard, 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 HelpCardService:
    @staticmethod
    def generate_for_session(db: Session, *, user: User, session: ChatSession) -> TeacherHelpCard:
        entitlement = EntitlementService.active_entitlement(db, user)
        if not entitlement.allow_help_card:
            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="help_card",
            values=_help_card_values(user=user, topic=topic, summary=summary),
            user_id=user.id,
        )
        card = TeacherHelpCard(
            user_id=user.id,
            topic_session_id=topic.id,
            summary_id=summary.id,
            content=content,
            source="topic_summary",
        )
        topic.help_card_generated = 1
        db.add_all([topic, card])
        db.commit()
        db.refresh(card)
        return card

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

    @staticmethod
    def mark_copied(
        db: Session,
        *,
        user: User,
        card_id: int,
        scope: ChatAccessScope | None = None,
    ) -> TeacherHelpCard:
        card = _user_card(db, user=user, card_id=card_id, scope=scope)
        if card is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="求助卡不存在")
        card.copied = 1
        card.copied_at = _now()
        db.add(card)
        db.commit()
        db.refresh(card)
        return card

    @staticmethod
    def delete(
        db: Session,
        *,
        user: User,
        card_id: int,
        scope: ChatAccessScope | None = None,
    ) -> None:
        card = _user_card(db, user=user, card_id=card_id, scope=scope)
        if card is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="求助卡不存在")
        db.delete(card)
        db.commit()


def help_card_dict(card: TeacherHelpCard) -> dict:
    return {
        "id": card.id,
        "userId": card.user_id,
        "topicSessionId": card.topic_session_id,
        "summaryId": card.summary_id,
        "content": card.content,
        "source": card.source,
        "copied": bool(card.copied),
        "copiedAt": card.copied_at,
        "createdAt": card.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 _help_card_values(*, user: User, topic: TopicSession, summary: TopicSummary) -> dict[str, str]:
    data = topic_summary_dict(summary) or {}
    return {
        "student_name": user.name or user.nickname or user.phone,
        "topic_title": topic.title,
        "topic_time": f"{_format_time(topic.started_at)} - {_format_time(topic.ended_at) if topic.ended_at else '进行中'}",
        "issue": topic.core_question or "（请补充）",
        "summary": data.get("summary") or "（暂无摘要）",
        "current_focus": data.get("currentFocus") or topic.core_question or "（请补充）",
        "next_observation": data.get("nextObservation") or "（请补充）",
        "teacher_question": "（请把最想确认的一两个问题写在这里）",
    }


def _format_time(value: datetime | None) -> str:
    if value is None:
        return "未知"
    return value.strftime("%Y-%m-%d %H:%M")


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


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