"""Version management (publish) router."""

from datetime import datetime

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

from app.database import get_db
from app.models.house import House
from app.models.publish_version import PublishVersion
from app.models.user import User
from app.schemas.publish_version import (
    PublishVersionCreate,
    PublishVersionRead,
    PublishVersionReview,
    PublishVersionSubmitReview,
)
from app.services.auth_service import get_current_user
from app.services.publish_service import create_snapshot, validate_house
from app.utils.helpers import generate_uuid, paginate

router = APIRouter()


# ── Helpers ────────────────────────────────────────────────────────────── #

def get_version_or_404(version_id: str, db: Session) -> PublishVersion:
    version = (
        db.query(PublishVersion)
        .filter(PublishVersion.id == version_id)
        .first()
    )
    if not version:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="版本不存在",
        )
    return version


# ── Endpoints ──────────────────────────────────────────────────────────── #

@router.get(
    "/api/houses/{hid}/versions",
    response_model=dict,
    summary="获取房屋版本列表",
)
def list_versions(
    hid: str,
    page: int = Query(1, ge=1),
    size: int = Query(20, ge=1, le=100),
    db: Session = Depends(get_db),
    _: User = Depends(get_current_user),
):
    """List all versions for a house (paginated)."""
    house = db.query(House).filter(House.id == hid).first()
    if not house:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="房屋不存在",
        )

    query = (
        db.query(PublishVersion)
        .filter(PublishVersion.house_id == hid)
        .order_by(PublishVersion.version_number.desc())
    )
    result = paginate(query, page=page, size=size)

    return {
        "items": [
            PublishVersionRead.model_validate(v) for v in result["items"]
        ],
        "total": result["total"],
        "page": result["page"],
        "size": result["size"],
        "pages": result["pages"],
    }


@router.get(
    "/api/houses/{hid}/versions/{vid}",
    response_model=PublishVersionRead,
    summary="获取版本详情",
)
def get_version(
    hid: str,
    vid: str,
    db: Session = Depends(get_db),
    _: User = Depends(get_current_user),
):
    """Get a specific version."""
    version = get_version_or_404(vid, db)

    if version.house_id != hid:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="版本不属于该房屋",
        )

    return PublishVersionRead.model_validate(version)


@router.post(
    "/api/houses/{hid}/versions",
    response_model=PublishVersionRead,
    status_code=status.HTTP_201_CREATED,
    summary="创建草稿版本",
)
def create_version(
    hid: str,
    body: PublishVersionCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Create a new draft version with a snapshot of the current house state."""
    house = db.query(House).filter(House.id == hid).first()
    if not house:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="房屋不存在",
        )

    # Check version_number uniqueness within house
    existing = (
        db.query(PublishVersion)
        .filter(
            PublishVersion.house_id == hid,
            PublishVersion.version_number == body.version_number,
        )
        .first()
    )
    if existing:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"版本号 {body.version_number} 已存在",
        )

    # Create snapshot
    try:
        snapshot = create_snapshot(hid, db)
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e),
        )

    version = PublishVersion(
        id=generate_uuid(),
        house_id=hid,
        version_number=body.version_number,
        status="draft",
        snapshot_data=snapshot,
        parent_version_id=body.parent_version_id,
        created_by=current_user.id,
        changelog=body.changelog,
        created_at=datetime.utcnow(),
        updated_at=datetime.utcnow(),
    )
    db.add(version)
    db.commit()
    db.refresh(version)

    return PublishVersionRead.model_validate(version)


@router.post(
    "/api/versions/{id}/submit",
    response_model=PublishVersionRead,
    summary="提交版本审核",
)
def submit_version(
    id: str,
    body: PublishVersionSubmitReview = PublishVersionSubmitReview(),
    db: Session = Depends(get_db),
    _: User = Depends(get_current_user),
):
    """Submit a draft version for review."""
    version = get_version_or_404(id, db)

    if version.status != "draft":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"当前状态为 '{version.status}'，无法提交审核",
        )

    # Run validation before submitting
    issues = validate_house(version.house_id, db)
    errors = [i for i in issues if i.get("severity") == "error"]
    if errors:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "message": "房屋存在验证错误，无法提交",
                "issues": errors,
            },
        )

    version.status = "pending_review"
    version.submitted_at = datetime.utcnow()
    version.updated_at = datetime.utcnow()
    if body.changelog:
        version.changelog = body.changelog

    db.commit()
    db.refresh(version)

    return PublishVersionRead.model_validate(version)


@router.post(
    "/api/versions/{id}/approve",
    response_model=PublishVersionRead,
    summary="审核通过版本",
)
def approve_version(
    id: str,
    body: PublishVersionReview = PublishVersionReview(
        status="approved", review_notes=None
    ),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Approve a version that is pending review."""
    version = get_version_or_404(id, db)

    if version.status != "pending_review":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"当前状态为 '{version.status}'，无法审批",
        )

    version.status = "approved"
    version.reviewed_at = datetime.utcnow()
    version.reviewed_by = current_user.id
    version.updated_at = datetime.utcnow()
    if body.review_notes:
        version.review_notes = body.review_notes

    db.commit()
    db.refresh(version)

    return PublishVersionRead.model_validate(version)


@router.post(
    "/api/versions/{id}/reject",
    response_model=PublishVersionRead,
    summary="驳回版本",
)
def reject_version(
    id: str,
    body: PublishVersionReview = PublishVersionReview(
        status="rejected", review_notes=None
    ),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Reject a version that is pending review."""
    version = get_version_or_404(id, db)

    if version.status != "pending_review":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"当前状态为 '{version.status}'，无法驳回",
        )

    version.status = "archived"
    version.reviewed_at = datetime.utcnow()
    version.reviewed_by = current_user.id
    version.updated_at = datetime.utcnow()
    if body.review_notes:
        version.review_notes = body.review_notes

    db.commit()
    db.refresh(version)

    return PublishVersionRead.model_validate(version)


@router.post(
    "/api/versions/{id}/publish",
    response_model=PublishVersionRead,
    summary="发布版本",
)
def publish_version(
    id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Publish an approved version."""
    version = get_version_or_404(id, db)

    if version.status != "approved":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"当前状态为 '{version.status}'，无法发布",
        )

    # Update house status to published
    house = db.query(House).filter(House.id == version.house_id).first()
    if house:
        house.status = "published"
        house.updated_at = datetime.utcnow()

    version.status = "published"
    version.published_at = datetime.utcnow()
    version.published_by = current_user.id
    version.updated_at = datetime.utcnow()

    db.commit()
    db.refresh(version)

    return PublishVersionRead.model_validate(version)


@router.post(
    "/api/versions/{id}/rollback",
    response_model=PublishVersionRead,
    summary="回滚版本",
)
def rollback_version(
    id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Rollback a published version."""
    version = get_version_or_404(id, db)

    if version.status != "published":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"当前状态为 '{version.status}'，无法回滚",
        )

    # Create a new draft version as rollback target
    house = db.query(House).filter(House.id == version.house_id).first()
    if not house:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="房屋不存在",
        )

    # Find next version number
    max_version = (
        db.query(PublishVersion)
        .filter(PublishVersion.house_id == version.house_id)
        .order_by(PublishVersion.version_number.desc())
        .first()
    )
    next_version_number = (max_version.version_number + 1) if max_version else 1

    # Restore snapshot data
    rollback_version = PublishVersion(
        id=generate_uuid(),
        house_id=version.house_id,
        version_number=next_version_number,
        status="draft",
        snapshot_data=version.snapshot_data,
        parent_version_id=version.id,
        rolled_back_from_id=version.id,
        created_by=current_user.id,
        changelog=f"回滚到版本 {version.version_number}",
        created_at=datetime.utcnow(),
        updated_at=datetime.utcnow(),
    )
    db.add(rollback_version)

    # Mark old version as rolled_back
    version.status = "rolled_back"
    version.updated_at = datetime.utcnow()

    db.commit()
    db.refresh(rollback_version)

    return PublishVersionRead.model_validate(rollback_version)


@router.get(
    "/api/versions/{id}/validate",
    response_model=dict,
    summary="验证版本",
)
def validate_version(
    id: str,
    db: Session = Depends(get_db),
    _: User = Depends(get_current_user),
):
    """Validate the house data for a version."""
    version = get_version_or_404(id, db)

    issues = validate_house(version.house_id, db)

    errors = [i for i in issues if i.get("severity") == "error"]
    warnings = [i for i in issues if i.get("severity") == "warning"]

    return {
        "version_id": id,
        "valid": len(errors) == 0,
        "error_count": len(errors),
        "warning_count": len(warnings),
        "issues": issues,
    }
