"""Campaign engine integration tests: materialization, sequencing, uniqueness.

Tests the async service layer directly (materialize_campaign / get_campaign_entities)
against the REAL test database used by the app: per-recipient generated values,
invoice-number uniqueness within a campaign, subject/template/phone/account
assignment plans, preview-mode non-persistence, and exhaustion behavior.
"""
import secrets
import uuid
from datetime import datetime, timedelta, timezone

import pytest

from app.models import (Campaign, CampaignRecipient, CompanyPhoneNumber, EmailTemplate,
                        GmailAccount, OAuthToken, Recipient, RecipientList, SubjectLine,
                        User)
from app.services.campaign_engine import (get_campaign_entities,
                                          materialize_campaign)


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _make_user(db) -> User:
    u = User(email=f"eng{secrets.token_hex(4)}@x.com",
             password_hash="x" * 60, full_name="Eng")
    db.add(u)
    db.commit()
    return u


def _make_list(db, user_id, n=3, prefix="r") -> RecipientList:
    rl = RecipientList(name=f"list-{prefix}-{uuid.uuid4().hex[:6]}", user_id=user_id)
    db.add(rl)
    db.commit()
    for i in range(n):
        db.add(Recipient(list_id=rl.id, email=f"{prefix}{i}-{uuid.uuid4().hex[:6]}@x.com",
                         first_name=f"Eng{prefix}", last_name=str(i),
                         unsub_token=secrets.token_urlsafe(24)))
    db.commit()
    return rl


def _make_subjects(db, user_id, n=3) -> list:
    subs = []
    for i in range(n):
        s = SubjectLine(user_id=user_id, subject=f"Subject {i} %RandomInvoiceNumber%")
        db.add(s)
        subs.append(s)
    db.commit()
    return subs


def _make_templates(db, user_id, n=2, use_invoice=True) -> list:
    tpls = []
    for i in range(n):
        body = f"<p>Hi %FirstName%, total %RandomTotal%."
        if use_invoice:
            body += " Invoice %RandomInvoiceNumber%."
        body += "</p>"
        t = EmailTemplate(user_id=user_id, name=f"tpl-{i}-{uuid.uuid4().hex[:6]}",
                          subject_hint=f"hint {i}",
                          body_html=body)
        db.add(t)
        tpls.append(t)
    db.commit()
    return tpls


def _make_accounts(db, user_id, n=2, status="authorized") -> list:
    accs = []
    for i in range(n):
        a = GmailAccount(user_id=user_id, email=f"eng-acc{i}-{uuid.uuid4().hex[:6]}@gmail.com",
                         status=status, sending_method="api",
                         is_active=(status == "authorized"))
        db.add(a)
        db.commit()
        db.add(OAuthToken(account_id=a.id, access_token=f"tok-{i}",
                          refresh_token=f"ref-{i}",
                          expires_at=datetime.now(timezone.utc) + timedelta(hours=1)))
        db.commit()
        accs.append(a)
    return accs


def _make_phones(db, user_id, n=2) -> list:
    ps = []
    for i in range(n):
        p = CompanyPhoneNumber(user_id=user_id, label=f"line {i}",
                               phone=f"+1555000{i:02d}")
        db.add(p)
        ps.append(p)
    db.commit()
    return ps


def _make_campaign(db, user_id, list_id, subject_ids, template_ids, account_ids,
                   **over) -> Campaign:
    kw = dict(
        user_id=user_id,
        name=over.pop("name", f"engine-{uuid.uuid4().hex[:6]}"),
        recipient_list_id=list_id,
        subject_set_ids=subject_ids,
        template_ids=template_ids,
        account_ids=account_ids,
    )
    kw.update(over)
    c = Campaign(**kw)
    db.add(c)
    db.commit()
