from __future__ import annotations

from datetime import UTC, datetime
from decimal import Decimal

from sqlalchemy import create_engine, func, select
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool

import app.models  # noqa: F401 - 注册完整 metadata
from app.db.base_class import Base
from app.models.commercial_billing import CommercialBillingPeriod
from app.schemas.commercial import CommercialPlanCreate, CommercialSubscriptionCreate
from app.services.commercial_admin import CommercialAdminService
from app.services.commercial_rollover_scheduler import CommercialRolloverScheduler


def test_scheduler_rolls_due_subscription_once_and_respects_leader_lease() -> None:
    engine = create_engine(
        "sqlite+pysqlite:///:memory:",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    Base.metadata.create_all(engine)
    factory = sessionmaker(bind=engine, expire_on_commit=False)
    due = datetime(2026, 2, 1, tzinfo=UTC)
    with factory() as db:
        subscription_id = _seed_due_subscription(db)
        db.commit()

    scheduler = CommercialRolloverScheduler(session_factory=factory)
    first = scheduler._run_once(as_of=due)
    replay = scheduler._run_once(as_of=due)

    assert first["scanned"] == 1
    assert first["rolled_over"] == 1
    assert first["periods_created"] == 1
    assert replay["scanned"] == 0
    with factory() as db:
        assert (
            db.scalar(
                select(func.count())
                .select_from(CommercialBillingPeriod)
                .where(CommercialBillingPeriod.subscription_id == subscription_id)
            )
            == 2
        )

    scheduler._try_acquire_lease = lambda _db: False  # type: ignore[method-assign]
    skipped = scheduler._run_once(as_of=due)
    assert skipped["leader_skipped"] == 1
    engine.dispose()


def _seed_due_subscription(db: Session) -> str:
    start = datetime(2026, 1, 1, tzinfo=UTC)
    due = datetime(2026, 2, 1, tzinfo=UTC)
    admin = CommercialAdminService(db)
    plan = admin.create_plan(
        "tenant-scheduler",
        CommercialPlanCreate(
            plan_code="scheduler",
            name="调度器测试套餐",
            pricing_model="subscription",
            billing_interval="monthly",
            currency="CNY",
            base_fee=Decimal("100"),
            effective_from=start,
        ),
        actor_id="scheduler-test",
    )
    admin.activate_plan(
        "tenant-scheduler",
        plan.id,
        expected_version=plan.version,
    )
    subscription = admin.create_subscription(
        "tenant-scheduler",
        CommercialSubscriptionCreate(
            subscription_key="scheduler-subscription",
            plan_id=plan.id,
            starts_at=start,
            current_period_start=start,
            current_period_end=due,
            seats=1,
            auto_renew=True,
        ),
        actor_id="scheduler-test",
    )
    return subscription.id
