"""미래 준비 — 모바일 푸시알림 디바이스 등록·발송·이력."""
from __future__ import annotations
import logging
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel
from sqlalchemy import select, desc
from sqlalchemy.ext.asyncio import AsyncSession
from core.auth import get_current_user, require_admin_role
from database import get_db
from models import User, PushDevice, PushLog

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/push", tags=["미래준비-푸시알림"])


class DeviceRegister(BaseModel):
    token: str
    platform: str = "android"


class PushSend(BaseModel):
    title: str
    body: str
    category: str = "general"
    user_ids: list[int] = []


async def _send_to_device(device: PushDevice, title: str, body: str, category: str) -> bool:
    """FCM/Expo 푸시 발송 (온프레미스: 메신저 WebSocket으로 대체)."""
    try:
        import httpx
        async with httpx.AsyncClient(timeout=5) as c:
            r = await c.post("http://127.0.0.1:9001/api/messenger/push", json={
                "token": device.token,
                "platform": device.platform,
                "title": title,
                "body": body,
                "category": category,
            })
        return r.status_code == 200
    except Exception as e:
        logger.warning("푸시 발송 실패 device=%s: %s", device.id, e)
        return False


@router.post("/register")
async def register_device(
    req: DeviceRegister,
    db: AsyncSession = Depends(get_db),
    user: User = Depends(get_current_user),
):
    """디바이스 토큰 등록 (중복이면 갱신)."""
    existing = await db.execute(
        select(PushDevice).where(PushDevice.token == req.token).limit(1)
    )
    device = existing.scalar_one_or_none()
    if device:
        device.active = True
        device.last_used_at = datetime.utcnow()
    else:
        device = PushDevice(
            user_id=user.id, token=req.token, platform=req.platform,
            registered_at=datetime.utcnow(),
        )
        db.add(device)
    await db.commit()
    await db.refresh(device)
    return {"ok": True, "device_id": device.id}


@router.delete("/register/{token}")
async def unregister_device(
    token: str,
    db: AsyncSession = Depends(get_db),
    user: User = Depends(get_current_user),
):
    """디바이스 토큰 비활성화."""
    row = await db.execute(
        select(PushDevice).where(PushDevice.token == token, PushDevice.user_id == user.id).limit(1)
    )
    device = row.scalar_one_or_none()
    if not device:
        raise HTTPException(404, "디바이스 없음")
    device.active = False
    await db.commit()
    return {"ok": True}


@router.post("/send")
async def send_push(
    req: PushSend,
    db: AsyncSession = Depends(get_db),
    user: User = Depends(require_admin_role),
):
    """관리자 푸시알림 발송."""
    q = select(PushDevice).where(PushDevice.active == True)
    if req.user_ids:
        q = q.where(PushDevice.user_id.in_(req.user_ids))
    rows = await db.execute(q)
    devices = rows.scalars().all()

    sent = 0
    for device in devices:
        success = await _send_to_device(device, req.title, req.body, req.category)
        log = PushLog(
            device_id=device.id, title=req.title, body=req.body,
            category=req.category, success=success, sent_at=datetime.utcnow(),
        )
        db.add(log)
        if success:
            sent += 1

    await db.commit()
    return {"ok": True, "sent": sent, "total": len(devices)}


@router.get("/logs")
async def push_logs(
    limit: int = 50,
    db: AsyncSession = Depends(get_db),
    user: User = Depends(get_current_user),
):
    """푸시 발송 이력."""
    rows = await db.execute(
        select(PushLog).order_by(desc(PushLog.sent_at)).limit(limit)
    )
    return [{
        "id": l.id, "title": l.title, "body": l.body[:100],
        "category": l.category, "success": l.success, "sent_at": l.sent_at,
    } for l in rows.scalars().all()]


@router.get("/devices")
async def list_devices(
    db: AsyncSession = Depends(get_db),
    user: User = Depends(require_admin_role),
):
    """등록된 디바이스 목록."""
    rows = await db.execute(
        select(PushDevice).where(PushDevice.active == True).order_by(desc(PushDevice.registered_at))
    )
    return [{
        "id": d.id, "user_id": d.user_id, "platform": d.platform,
        "registered_at": d.registered_at, "last_used_at": d.last_used_at,
    } for d in rows.scalars().all()]
