"""Pulls audience members from Mailchimp."""

import os
import sys
from typing import Any

import mailchimp_marketing

INCLUDED_STATUSES = {"subscribed", "unsubscribed"}


def fetch_members(config: dict) -> list[dict[str, Any]]:
    """Return audience members across the configured audience IDs.

    Skipped:
      - Members whose email domain is in `filters.internal_domains`.
      - Members whose status isn't in INCLUDED_STATUSES (excludes pending, cleaned,
        archived, transactional — none of which represent a real newsletter signup).
      - Members with no signup timestamp anywhere on the record.

    If `mailchimp.audience_ids` still contains the placeholder, this prints the available
    audiences and exits — so first-time setup is just "run it once and copy the IDs."
    """
    api_key = os.environ["MAILCHIMP_API_KEY"]
    server = os.environ.get("MAILCHIMP_SERVER_PREFIX") or _derive_server(api_key)

    mc_config = config.get("mailchimp", {})
    audience_ids = mc_config.get("audience_ids", [])
    internal_domains = {
        d.lower() for d in config.get("filters", {}).get("internal_domains", [])
    }

    if not audience_ids or any("REPLACE" in str(a) for a in audience_ids):
        return _list_audiences_and_exit(api_key, server)

    client = mailchimp_marketing.Client()
    client.set_config({"api_key": api_key, "server": server})

    records: list[dict[str, Any]] = []
    skipped_no_email = 0
    skipped_status: dict[str, int] = {}
    skipped_internal = 0
    skipped_no_signup_time = 0

    for audience_id in audience_ids:
        print(
            f"Fetching members from audience {audience_id}...",
            file=sys.stderr,
            flush=True,
        )
        offset = 0
        page_size = 1000
        while True:
            response = client.lists.get_list_members_info(
                audience_id, count=page_size, offset=offset
            )
            members = response.get("members", [])
            if not members:
                break

            for m in members:
                email = m.get("email_address", "")
                if not email:
                    skipped_no_email += 1
                    continue

                status = m.get("status")
                if status not in INCLUDED_STATUSES:
                    skipped_status[status] = skipped_status.get(status, 0) + 1
                    continue

                domain = email.rsplit("@", 1)[-1].strip().lower()
                if domain in internal_domains:
                    skipped_internal += 1
                    continue

                ts_signup = m.get("timestamp_signup") or m.get("timestamp_opt")
                if not ts_signup:
                    skipped_no_signup_time += 1
                    continue

                records.append(
                    {
                        "email": email,
                        "audience_id": audience_id,
                        "status": status,
                        "timestamp_signup": ts_signup,
                        "source": m.get("source"),
                        "merge_fields": m.get("merge_fields", {}),
                    }
                )

            if len(members) < page_size:
                break
            offset += page_size

    print(
        f"  {len(records)} members fetched, "
        f"{skipped_no_email} skipped (no email), "
        f"{skipped_no_signup_time} skipped (no signup time), "
        f"{skipped_internal} skipped (internal domain), "
        f"{skipped_status} skipped by status.",
        file=sys.stderr,
        flush=True,
    )
    return records


def _derive_server(api_key: str) -> str:
    """Mailchimp API keys end with -<server>, e.g. -us1, -us21."""
    if "-" not in api_key:
        raise RuntimeError(
            "Cannot derive Mailchimp server prefix from API key (no '-us<n>' suffix). "
            "Set MAILCHIMP_SERVER_PREFIX in .env explicitly."
        )
    return api_key.rsplit("-", 1)[-1]


def _list_audiences_and_exit(api_key: str, server: str) -> list:
    client = mailchimp_marketing.Client()
    client.set_config({"api_key": api_key, "server": server})
    print(
        "config.yaml has no real mailchimp.audience_ids set. Available audiences:",
        file=sys.stderr,
    )
    response = client.lists.get_all_lists(count=100)
    for lst in response.get("lists", []):
        print(
            f"  id={lst['id']}  name={lst['name']!r}  "
            f"members={lst['stats']['member_count']}",
            file=sys.stderr,
        )
    print(
        "\nAdd one or more of those IDs to mailchimp.audience_ids in config.yaml.",
        file=sys.stderr,
    )
    raise SystemExit(2)


if __name__ == "__main__":
    import json

    import yaml
    from dotenv import load_dotenv

    load_dotenv()
    with open("config.yaml") as f:
        config = yaml.safe_load(f)
    members = fetch_members(config)
    print(f"\nFetched {len(members)} members.")
    if members:
        print("Sample record:")
        print(json.dumps(members[0], indent=2, default=str))
