"""admin 写操作 repo(状态改写)。

涉钱的金币/提现复用 app.repositories.wallet(grant_coins / refresh_withdraw_status /
reconcile_pending_withdraws),不在这里重写——重写涉钱逻辑就是给自己埋雷。

set_user_status / update_feedback_status 支持 commit=False,让 router 把"业务写 + 审计写"
放进同一事务一起 commit(原子:改了就有审计、有审计就真改了,见 plan 风险点 1)。
"""
from __future__ import annotations

from datetime import datetime

from sqlalchemy import delete
from sqlalchemy.orm import Session

from app.core.rewards import CN_TZ
from app.models.feedback import Feedback
from app.models.onboarding import OnboardingCompletion
from app.models.price_report import PriceReport
from app.models.user import User


def set_user_status(db: Session, user: User, *, status: str, commit: bool = True) -> User:
    user.status = status
    if commit:
        db.commit()
        db.refresh(user)
    else:
        db.flush()
    return user


def set_user_debug_trace(
    db: Session, user: User, *, enabled: bool, commit: bool = True
) -> User:
    """开关用户「复制调试链接」权限。同 set_user_status：支持 commit=False 让 router 把
    业务写 + 审计写放进同一事务。"""
    user.debug_trace_enabled = enabled
    if commit:
        db.commit()
        db.refresh(user)
    else:
        db.flush()
    return user


def set_user_risk(
    db: Session,
    user: User,
    *,
    is_high_risk: bool,
    note: str | None,
    commit: bool = True,
) -> User:
    """设置人工风险结论和备注，支持与审计日志共用同一事务。"""
    user.is_high_risk = is_high_risk
    user.high_risk_note = note.strip() if is_high_risk and note else None
    if commit:
        db.commit()
        db.refresh(user)
    else:
        db.flush()
    return user


def update_feedback_status(
    db: Session, feedback: Feedback, *, status: str, commit: bool = True
) -> Feedback:
    feedback.status = status
    if commit:
        db.commit()
        db.refresh(feedback)
    else:
        db.flush()
    return feedback


def review_feedback(
    db: Session,
    feedback: Feedback,
    *,
    status: str,
    reviewed_by_admin_id: int,
    reward_coins: int | None = None,
    reject_reason: str | None = None,
    review_note: str | None = None,
    admin_reply: str | None = None,
    commit: bool = True,
) -> Feedback:
    """审核反馈:置 adopted/rejected + 记录奖励/原因/回复留言/审核人/审核时间。

    发金币(wallet.grant_coins)由 router 在同一事务里调,确保状态、金币流水、审计一起提交。
    admin_reply=给用户的回复留言(用户端可见),与 review_note(内部备注)区分。
    """
    feedback.status = status
    feedback.reward_coins = reward_coins
    feedback.reject_reason = reject_reason
    feedback.review_note = review_note
    feedback.admin_reply = admin_reply
    feedback.reviewed_by_admin_id = reviewed_by_admin_id
    feedback.reviewed_at = datetime.now(CN_TZ).replace(tzinfo=None)
    if commit:
        db.commit()
        db.refresh(feedback)
    else:
        db.flush()
    return feedback


def review_price_report(
    db: Session,
    report: PriceReport,
    *,
    status: str,
    reward_coins: int | None = None,
    reject_reason: str | None = None,
    commit: bool = True,
) -> PriceReport:
    """审核上报:置 approved/rejected + 记审核时间;通过填 reward_coins、拒绝填 reject_reason。

    发金币(wallet.grant_coins)不在这里——由 router 在同一事务里调,涉钱逻辑不重写(见模块头注释)。
    """
    report.status = status
    if reward_coins is not None:
        report.reward_coins = reward_coins
    if reject_reason is not None:
        report.reject_reason = reject_reason
    report.reviewed_at = datetime.now(CN_TZ).replace(tzinfo=None)  # 北京 wall-clock,同 created_at
    if commit:
        db.commit()
        db.refresh(report)
    else:
        db.flush()
    return report


def delete_device_onboarding(db: Session, device_id: str, *, commit: bool = True) -> int:
    """删某设备(device_id)的全部 onboarding 完成记录 → 该设备上所有账号下次登录重走引导。
    返回删除行数。支持 commit=False 让 router 把业务写 + 审计写放进同一事务。"""
    n = db.execute(
        delete(OnboardingCompletion).where(OnboardingCompletion.device_id == device_id)
    ).rowcount
    if commit:
        db.commit()
    else:
        db.flush()
    return n


def delete_all_onboarding(db: Session, *, commit: bool = True) -> int:
    """清空 onboarding_completion 表 → 所有用户在所有设备下次登录都重走引导。返回删除行数。
    支持 commit=False(同 delete_device_onboarding)。"""
    n = db.execute(delete(OnboardingCompletion)).rowcount
    if commit:
        db.commit()
    else:
        db.flush()
    return n
