"""Stripe Webhook 处理"""

import json
import logging
import uuid
from datetime import datetime, timedelta

from fastapi import APIRouter, HTTPException, Request
from sqlalchemy import select

from app.compat import UTC
from app.config import settings
from app.db import async_session
from app.models.operations import SubscriptionEvent, TenantSubscription
from app.models.user import Tenant

logger = logging.getLogger(__name__)
router = APIRouter()

STRIPE_WEBHOOK_SECRET = settings.STRIPE_WEBHOOK_SECRET


@router.post("/stripe", response_model=dict, summary="Stripe回调")
async def stripe_webhook(request: Request):
    """接收 Stripe 事件（签名验证 + Idempotency）"""
    body = None
    if not STRIPE_WEBHOOK_SECRET:
        if settings.DEBUG or settings.TESTING:
            logger.warning("Stripe webhook secret not configured — parsing body directly in DEV/TEST mode")
            try:
                body = await request.body()
                event = json.loads(body)
            except Exception:
                raise HTTPException(status_code=400, detail="Invalid payload")
        else:
            return {"status": "not_configured"}
    else:
        try:
            body = await request.body()
        except Exception:
            raise HTTPException(status_code=400, detail="Invalid payload")

        # 签名验证
        sig_header = request.headers.get("stripe-signature", "")
        try:
            import stripe
            event = stripe.Webhook.construct_event(body, sig_header, STRIPE_WEBHOOK_SECRET)
        except (ValueError, stripe.error.SignatureVerificationError):
            raise HTTPException(status_code=400, detail="Invalid signature")
        except Exception:
            raise HTTPException(status_code=400, detail="Invalid payload")

    event_type = event.get("type", "")
    event_obj = event.get("data", {}).get("object", {})
    event_id = event.get("id", "")

    event_type = event.get("type", "")
    event_obj = event.get("data", {}).get("object", {})
    event_id = event.get("id", "")

    async with async_session() as db:
        match event_type:
            case "checkout.session.completed":
                # 订阅创建/升级
                customer_id = event_obj.get("customer")
                subscription_id = event_obj.get("subscription")
                plan_id = event_obj.get("metadata", {}).get("plan_id", "pro")

                if customer_id and subscription_id:
                    # 先按 stripe_customer_id 查找已有订阅
                    sub = await db.execute(
                        select(TenantSubscription).where(
                            TenantSubscription.stripe_customer_id == customer_id
                        )
                    )
                    existing = sub.scalar()

                    if existing:
                        existing.stripe_subscription_id = subscription_id
                        existing.plan_id = plan_id
                        existing.status = "active"
                        resolved_tenant_id = existing.tenant_id
                    else:
                        # 尝试从 metadata 获取 tenant_id，否则跳过
                        tid = event_obj.get("metadata", {}).get("tenant_id")
                        if not tid:
                            return {"status": "skipped", "reason": "missing_tenant_id"}
                        try:
                            resolved_tenant_id = uuid.UUID(tid)
                        except (ValueError, AttributeError):
                            return {"status": "skipped", "reason": "invalid_tenant_id"}
                        db.add(TenantSubscription(
                            id=uuid.uuid4(),
                            tenant_id=resolved_tenant_id,
                            stripe_customer_id=customer_id,
                            stripe_subscription_id=subscription_id,
                            plan_id=plan_id,
                            status="active",
                            current_period_start=datetime.now(UTC),
                            current_period_end=datetime.now(UTC) + timedelta(days=30),
                        ))

                    db.add(SubscriptionEvent(
                        id=uuid.uuid4(),
                        tenant_id=resolved_tenant_id,
                        event_type="upgrade",
                        from_plan=None,
                        to_plan=plan_id,
                        stripe_event_id=event_id,
                        event_metadata={},
                    ))

                    # 更新 tenant.plan_type
                    tenant = await db.execute(select(Tenant).where(Tenant.id == resolved_tenant_id))
                    t = tenant.scalar()
                    if t:
                        t.plan_type = plan_id
                        t.is_personal = False

                    await db.commit()
                    return {"status": "ok", "action": "subscription_created"}

            case "customer.subscription.updated":
                subscription_id = event_obj.get("id")
                status = event_obj.get("status")
                if subscription_id and status:
                    sub = await db.execute(
                        select(TenantSubscription).where(
                            TenantSubscription.stripe_subscription_id == subscription_id
                        )
                    )
                    s = sub.scalar()
                    if s:
                        s.status = status
                        db.add(SubscriptionEvent(
                            id=uuid.uuid4(),
                            tenant_id=s.tenant_id,
                            event_type="status_change",
                            from_plan=s.plan_id,
                            to_plan=s.plan_id,
                            stripe_event_id=event_id,
                            event_metadata={"new_status": status},
                        ))
                        await db.commit()

            case "customer.subscription.deleted":
                subscription_id = event_obj.get("id")
                if subscription_id:
                    sub = await db.execute(
                        select(TenantSubscription).where(
                            TenantSubscription.stripe_subscription_id == subscription_id
                        )
                    )
                    s = sub.scalar()
                    if s:
                        s.status = "canceled"
                        db.add(SubscriptionEvent(
                            id=uuid.uuid4(), tenant_id=s.tenant_id, event_type="cancel",
                            from_plan=s.plan_id, stripe_event_id=event_id, event_metadata={},
                        ))
                        # 降级租户
                        tenant = await db.execute(select(Tenant).where(Tenant.id == s.tenant_id))
                        t = tenant.scalar()
                        if t:
                            t.plan_type = "free"
                        await db.commit()

            case _:
                # 忽略不关心的事件
                pass

    return {"status": "received"}
