from __future__ import annotations

from typing import Literal

from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import func, select
from sqlalchemy.orm import Session

from app.api.pagination import page_result
from app.core.database import get_db
from app.core.dependencies import get_current_admin
from app.core.responses import api_success
from app.models.admin import Admin
from app.models.ai_config import ContentGenerationConfig
from app.schemas.admin import (
    ContentGenerationConfigSaveRequest,
    ContentGenerationPreviewRequest,
    ContentGenerationTestRequest,
)
from app.services.admin_service import OperationLogService
from app.services.content_generation_config_service import (
    SAMPLE_VALUES,
    ContentGenerationConfigService,
    ContentGenerationType,
    config_detail,
)

router = APIRouter()


@router.get("/content-generation/config/{config_type}")
def get_content_generation_config(
    config_type: Literal["help_card", "share_draft"],
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    row = _config_with_admin(db, config_type)
    return api_success(config_detail(config_type, row[0], row[1].name if row and row[1] else None) if row else config_detail(config_type, None))


@router.put("/content-generation/config/{config_type}")
def save_content_generation_config(
    config_type: Literal["help_card", "share_draft"],
    payload: ContentGenerationConfigSaveRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    config = ContentGenerationConfigService.save(
        db,
        config_type=config_type,
        template_content=payload.templateContent,
        instruction_content=payload.instructionContent,
        updated_by=current_admin.id,
    )
    OperationLogService.write(
        db,
        admin_id=current_admin.id,
        module="content_generation",
        action=f"save_{config_type}",
        target_id=config.id,
    )
    db.commit()
    db.refresh(config)
    return api_success(config_detail(config_type, config, current_admin.name))


@router.post("/content-generation/config/{config_type}/reset")
def reset_content_generation_config(
    config_type: Literal["help_card", "share_draft"],
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    config = ContentGenerationConfigService.reset(
        db,
        config_type=config_type,
        updated_by=current_admin.id,
    )
    OperationLogService.write(
        db,
        admin_id=current_admin.id,
        module="content_generation",
        action=f"reset_{config_type}",
        target_id=config.id,
    )
    db.commit()
    db.refresh(config)
    return api_success(config_detail(config_type, config, current_admin.name))


@router.get("/content-generation/config/{config_type}/history")
def content_generation_history(
    config_type: Literal["help_card", "share_draft"],
    page: int = Query(default=1, ge=1),
    pageSize: int = Query(default=10, ge=5, le=100),
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    total = db.scalar(
        select(func.count(ContentGenerationConfig.id)).where(ContentGenerationConfig.config_type == config_type)
    ) or 0
    current_id = db.scalar(
        select(ContentGenerationConfig.id)
        .where(ContentGenerationConfig.config_type == config_type)
        .order_by(ContentGenerationConfig.updated_at.desc(), ContentGenerationConfig.id.desc())
        .limit(1)
    )
    rows = db.execute(
        select(ContentGenerationConfig, Admin)
        .outerjoin(Admin, Admin.id == ContentGenerationConfig.updated_by)
        .where(ContentGenerationConfig.config_type == config_type)
        .order_by(ContentGenerationConfig.updated_at.desc(), ContentGenerationConfig.id.desc())
        .offset((page - 1) * pageSize)
        .limit(pageSize)
    ).all()
    items = [_history_item(config, admin, current_id=current_id) for config, admin in rows]
    return api_success(page_result(items, total=total, page=page, page_size=pageSize))


@router.get("/content-generation/config/{config_type}/history/{config_id}")
def content_generation_history_detail(
    config_type: Literal["help_card", "share_draft"],
    config_id: int,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    row = db.execute(
        select(ContentGenerationConfig, Admin)
        .outerjoin(Admin, Admin.id == ContentGenerationConfig.updated_by)
        .where(
            ContentGenerationConfig.id == config_id,
            ContentGenerationConfig.config_type == config_type,
        )
    ).first()
    if row is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="内容生成配置版本不存在")
    return api_success(config_detail(config_type, row[0], row[1].name if row[1] else None))


@router.post("/content-generation/config/{config_type}/history/{config_id}/restore")
def restore_content_generation_config(
    config_type: Literal["help_card", "share_draft"],
    config_id: int,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    restored = ContentGenerationConfigService.restore(
        db,
        config_type=config_type,
        source_config_id=config_id,
        updated_by=current_admin.id,
    )
    OperationLogService.write(
        db,
        admin_id=current_admin.id,
        module="content_generation",
        action=f"restore_{config_type}",
        target_id=restored.id,
    )
    db.commit()
    db.refresh(restored)
    return api_success(config_detail(config_type, restored, current_admin.name))


@router.post("/content-generation/preview")
def preview_content_generation(
    payload: ContentGenerationPreviewRequest,
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    return api_success({"content": ContentGenerationConfigService.preview(payload.configType, payload.templateContent)})


@router.post("/content-generation/test")
def test_content_generation(
    payload: ContentGenerationTestRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    values = dict(SAMPLE_VALUES)
    values.update(
        {
            "issue": payload.sampleText.strip()[:3000],
            "summary": payload.sampleText.strip()[:6000],
            "current_focus": "（请由 AI 根据测试材料整理）",
            "next_observation": "（请由 AI 根据测试材料整理）",
            "teacher_question": "（请由 AI 根据测试材料整理）",
        }
    )
    generated, used_fallback = ContentGenerationConfigService.generate_values(
        db,
        config_type=payload.configType,
        instruction_content=payload.instructionContent,
        values=values,
        user_id=None,
    )
    content = ContentGenerationConfigService.render(payload.configType, payload.templateContent, generated)
    OperationLogService.write(
        db,
        admin_id=current_admin.id,
        module="content_generation",
        action=f"test_{payload.configType}",
    )
    db.commit()
    return api_success({"content": content, "usedFallback": used_fallback})


def _config_with_admin(db: Session, config_type: ContentGenerationType):
    return db.execute(
        select(ContentGenerationConfig, Admin)
        .outerjoin(Admin, Admin.id == ContentGenerationConfig.updated_by)
        .where(ContentGenerationConfig.config_type == config_type)
        .order_by(ContentGenerationConfig.updated_at.desc(), ContentGenerationConfig.id.desc())
        .limit(1)
    ).first()


def _history_item(config: ContentGenerationConfig, admin: Admin | None, *, current_id: int | None) -> dict:
    compact = " ".join(config.template_content.split())
    return {
        "id": config.id,
        "configType": config.config_type,
        "preview": compact[:140],
        "templateCharCount": len(config.template_content),
        "instructionCharCount": len(config.instruction_content),
        "changeType": config.change_type,
        "sourceConfigId": config.source_config_id,
        "updatedByName": admin.name if admin else "未知管理员",
        "updatedAt": config.updated_at,
        "isCurrent": config.id == current_id,
    }
