class TestGetCampaignEntities:
    def test_loads_all_entities(self, db_engine):
        from sqlalchemy.orm import Session
        with Session(db_engine, expire_on_commit=False) as db:
            f = _seed_fixture(db)
            import asyncio
            from app.db.session import AsyncSessionLocal

            async def runner():
                async with AsyncSessionLocal() as s:
                    c = await s.get(Campaign, f["campaign"].id)
                    return await get_campaign_entities(s, c)

            subs, tpls, phones, accs = asyncio.run(runner())
        assert [s.id for s in subs] == [s.id for s in f["subjects"]]
        assert [t.id for t in tpls] == [t.id for t in f["templates"]]
        assert {p.id for p in phones} == {p.id for p in f["phones"]}
        assert {a.id for a in accs} == {a.id for a in f["accounts"]}

    def test_drops_unauthorized_accounts_and_inactive_phones(self, db_engine):
        from sqlalchemy.orm import Session
        with Session(db_engine, expire_on_commit=False) as db:
            u = _make_user(db)
            rl = _make_list(db, u.id, n=1)
            subs = _make_subjects(db, u.id, n=1)
            tpls = _make_templates(db, u.id, n=1)
            ok = _make_accounts(db, u.id, n=1)[0]
            bad = GmailAccount(user_id=u.id, email=f"bad-{uuid.uuid4().hex[:6]}@gmail.com",
                               status="expired", sending_method="api", is_active=False)
            db.add(bad)
            db.commit()
            off_phone = CompanyPhoneNumber(user_id=u.id, label="off", phone="+1999",
                                           is_active=False)
            db.add(off_phone)
            db.commit()
            c = _make_campaign(db, u.id, rl.id, [s.id for s in subs],
                               [t.id for t in tpls], [ok.id, bad.id])
            import asyncio
            from app.db.session import AsyncSessionLocal

            async def runner():
                async with AsyncSessionLocal() as s:
                    camp = await s.get(Campaign, c.id)
                    return await get_campaign_entities(s, camp)

            subs2, tpls2, phones2, accs2 = asyncio.run(runner())
        assert [a.id for a in accs2] == [ok.id]  # only authorized+active account
        assert off_phone.id not in {p.id for p in phones2}

    def test_missing_ids_resolved_honestly(self, db_engine):
        from sqlalchemy.orm import Session
        with Session(db_engine, expire_on_commit=False) as db:
            f = _seed_fixture(db)
            camp = f["campaign"]
            camp.subject_set_ids = [f["subjects"][0].id, 999999]
            camp.template_ids = [f["templates"][0].id, 888888]
            db.commit()
            import asyncio
            from app.db.session import AsyncSessionLocal

            async def runner():
                async with AsyncSessionLocal() as s:
                    c = await s.get(Campaign, camp.id)
                    return await get_campaign_entities(s, c)

            subs, tpls, _, _ = asyncio.run(runner())
        assert [s.id for s in subs] == [f["subjects"][0].id]
        assert [t.id for t in tpls] == [f["templates"][0].id]
