from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select, func
from typing import Optional
from datetime import date, datetime, timezone

from app.core.deps import DB, CurrentUser, require_any_authenticated
from app.models.payment import Subscription, Payment
from app.models.academic import Package

router = APIRouter(
    prefix="/payments", tags=["Payments"], dependencies=[Depends(require_any_authenticated)]
)


@router.get("/packages", summary="Available Subscription Packages")
async def get_packages(db: DB):
    result = await db.execute(
        select(Package).where(Package.is_active == True).order_by(Package.price)
    )
    return result.scalars().all()


@router.get("/my-subscription", summary="My Current Subscription")
async def get_my_subscription(current_user: CurrentUser, db: DB):
    from app.services.subscription_service import check_premium_access
    return await check_premium_access(db, current_user.id)


@router.get("/my-history", summary="My Payment History")
async def get_payment_history(
    current_user: CurrentUser,
    db: DB,
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
):
    query = select(Payment).where(Payment.user_id == current_user.id)
    total = (await db.execute(select(func.count()).select_from(query.subquery()))).scalar()
    result = await db.execute(
        query.order_by(Payment.created_at.desc())
        .offset((page - 1) * page_size)
        .limit(page_size)
    )
    return {
        "items": result.scalars().all(),
        "total": total,
        "page": page,
        "page_size": page_size,
    }


@router.post("/subscribe/{package_id}", summary="Subscribe to a Package", status_code=201)
async def subscribe(
    package_id: int,
    current_user: CurrentUser,
    db: DB,
    payment_method: str = "mobile_money",
    payment_reference: Optional[str] = None,
    phone_number: Optional[str] = None,
):
    """
    Initiate a subscription payment.
    In production, integrate with MTN Mobile Money / Airtel Money / card processors.
    """
    pkg = await db.execute(select(Package).where(Package.id == package_id, Package.is_active == True))
    pkg_obj = pkg.scalar_one_or_none()
    if not pkg_obj:
        raise HTTPException(status_code=404, detail="Package not found")

    if pkg_obj.price == 0:
        # Freemium - no payment needed
        from app.services.subscription_service import create_subscription
        sub = await create_subscription(db, current_user.id, package_id)
        return {"message": "Free subscription activated", "subscription_id": sub.id}

    # Create pending payment record
    payment = Payment(
        user_id=current_user.id,
        subscription_id=None,  # Will be updated after confirmation
        amount=pkg_obj.price,
        currency=pkg_obj.currency,
        payment_method=payment_method,
        payment_reference=payment_reference,
        phone_number=phone_number,
        status="pending",
        description=f"StemGenius {pkg_obj.name} subscription",
    )
    db.add(payment)
    await db.commit()
    await db.refresh(payment)

    # In production: call mobile money API here
    # For now, return payment details for manual confirmation
    return {
        "payment_id": payment.id,
        "amount": float(pkg_obj.price),
        "currency": pkg_obj.currency,
        "payment_method": payment_method,
        "status": "pending",
        "message": "Payment initiated. Use /payments/confirm/{payment_id} to confirm.",
        "instructions": f"Send {pkg_obj.price} {pkg_obj.currency} to StemGenius via {payment_method}",
    }


@router.post("/confirm/{payment_id}", summary="Confirm Payment (Admin/Webhook)")
async def confirm_payment(
    payment_id: int,
    current_user: CurrentUser,
    db: DB,
    external_reference: Optional[str] = None,
):
    """
    Confirm a payment and activate subscription.
    In production, this is called by payment gateway webhook.
    """
    from app.core.deps import require_admin
    # Allow admin or the user themselves
    payment = await db.execute(
        select(Payment).where(
            Payment.id == payment_id,
            Payment.user_id == current_user.id if current_user.role not in ["admin", "super_admin"] else True,
        )
    )
    payment_obj = payment.scalar_one_or_none()
    if not payment_obj:
        raise HTTPException(status_code=404, detail="Payment not found")

    if payment_obj.status == "completed":
        raise HTTPException(status_code=400, detail="Payment already confirmed")

    # Get the package via amount (simplified matching)
    payment_obj.status = "completed"
    payment_obj.completed_at = datetime.now(timezone.utc)
    if external_reference:
        payment_obj.external_reference = external_reference

    # Activate subscription - find package matching amount
    pkg = await db.execute(
        select(Package).where(Package.price == payment_obj.amount, Package.is_active == True)
        .where(Package.name != "freemium")
    )
    pkg_obj = pkg.scalar_one_or_none()
    if pkg_obj:
        from app.services.subscription_service import create_subscription
        sub = await create_subscription(
            db, payment_obj.user_id, pkg_obj.id, payment_obj.payment_reference
        )
        payment_obj.subscription_id = sub.id

    await db.commit()
    return {"message": "Payment confirmed and subscription activated"}


@router.post("/cancel-subscription", summary="Cancel Current Subscription")
async def cancel_subscription(current_user: CurrentUser, db: DB):
    """Cancel the current active subscription."""
    sub = await db.execute(
        select(Subscription).where(
            Subscription.user_id == current_user.id,
            Subscription.status.in_(["active", "grace_period"]),
        )
    )
    sub_obj = sub.scalar_one_or_none()
    if not sub_obj:
        raise HTTPException(status_code=404, detail="No active subscription found")

    sub_obj.status = "cancelled"
    sub_obj.cancelled_at = datetime.now(timezone.utc)
    await db.commit()
    return {"message": "Subscription cancelled"}
