"""
Console script to send email digests to shop subscribers.

Usage:
    digest_sender data/development.ini --frequency immediate
    digest_sender data/development.ini --frequency daily
    digest_sender data/development.ini --frequency weekly --dry-run

Cron setup:
    */5 * * * *  /path/to/env/bin/digest_sender /path/to/production.ini --frequency immediate
    0 8 * * *    /path/to/env/bin/digest_sender /path/to/production.ini --frequency daily
    0 8 * * 1    /path/to/env/bin/digest_sender /path/to/production.ini --frequency weekly
"""

import argparse
import sys
import logging
import transaction

from pyramid.paster import bootstrap, setup_logging

from ..models.meta import now_timestamp
from ..models.shop import Shop
from ..models.product import Product
from ..models.shop_subscription import (
    FREQUENCY_DAILY,
    FREQUENCY_WEEKLY,
    FREQUENCY_IMMEDIATE,
    get_verified_subscriptions_for_shop,
)
from .mail import send_email
from .mail_messages import DIGEST_TEXT, DIGEST_HTML

logger = logging.getLogger(__name__)


def parse_args(argv):
    p = argparse.ArgumentParser(
        description="Send email digests to shop subscribers"
    )
    p.add_argument("config_uri", help="Pyramid config file, e.g. development.ini")
    p.add_argument(
        "--frequency",
        choices=["immediate", "daily", "weekly"],
        required=True,
        help="Which frequency of subscribers to process",
    )
    p.add_argument(
        "--dry-run",
        action="store_true",
        help="Log what would be sent without actually sending",
    )
    return p.parse_args(argv[1:])


def get_new_items_for_subscriber(dbsession, shop, since_timestamp):
    """Query new public products created after since_timestamp."""
    return (
        dbsession.query(Product)
        .filter(
            Product.shop_id == shop.id,
            Product.visibility == 1,
            Product.created_timestamp > since_timestamp,
        )
        .order_by(Product.created_timestamp.desc())
        .all()
    )


def build_digest_text(shop_name, items, unsubscribe_url):
    """Build plain text digest email."""
    item_lines = []
    for item in items:
        label = "Product" if item.is_sellable else "Content"
        item_lines.append(f"- [{label}] {item.title}")
    items_text = "\n".join(item_lines)
    return DIGEST_TEXT.format(shop_name, items_text, unsubscribe_url)


def build_digest_html(shop_name, items, unsubscribe_url, get_endpoint=""):
    """Build HTML digest email."""
    item_parts = []
    for item in items:
        label = "Product" if item.is_sellable else "Content"
        thumbnail = ""
        if "thumbnail1" in item.extensions and get_endpoint:
            thumbnail = (
                f'<img src="{get_endpoint}/{item.s3_path}/thumbnail1?ts={item.updated_timestamp}" '
                f'style="border: 1px solid #ddd; border-radius: 4px; max-width: 120px; '
                f'max-height: 120px; width: auto; height: auto;" /><br/>'
            )
        item_parts.append(
            f'<p>{thumbnail}<b>{item.title}</b> <span style="color: #888;">({label})</span></p>'
        )
    items_html = "\n".join(item_parts)
    subject = f"New from {shop_name}"
    return DIGEST_HTML.format(subject, shop_name, items_html, unsubscribe_url)


def run(env, frequency_str, dry_run=False):
    """Process all shops and send digests."""
    freq_map = {
        "immediate": FREQUENCY_IMMEDIATE,
        "daily": FREQUENCY_DAILY,
        "weekly": FREQUENCY_WEEKLY,
    }
    frequency = freq_map.get(frequency_str, FREQUENCY_DAILY)
    request = env["request"]
    dbsession = request.dbsession
    settings = request.registry.settings

    # Email settings
    default_sender = "no-reply@makepostsell.com"
    sender_email = settings.get("app.email.sender", default_sender)
    relay = settings.get("app.email.relay", "localhost")
    dkim_private_key_path = settings.get("app.email.dkim_private_key_path", "")
    dkim_selector = settings.get("app.email.dkim_selector", "")
    dkim_signature_algorithm = settings.get(
        "app.email.dkim_signature_algorithm", "ed25519-sha256"
    )
    get_endpoint = settings.get("app.bucket.secure_uploads.get_endpoint", "")

    shops = (
        dbsession.query(Shop)
        .filter(Shop.subscriptions_enabled == True)
        .filter(Shop.environment == 0)  # MPS-14: exclude non-production shops
        .all()
    )

    for shop in shops:
        subscribers = get_verified_subscriptions_for_shop(
            dbsession, shop.id, frequency=frequency
        )

        if not subscribers:
            logger.info(f"Shop '{shop.name}': no {frequency_str} subscribers")
            continue

        for sub in subscribers:
            items = get_new_items_for_subscriber(
                dbsession, shop, sub.last_digest_timestamp
            )

            if not items:
                logger.info(
                    f"Shop '{shop.name}': no new items for {sub.email} since last digest"
                )
                continue

            unsubscribe_url = f"{request.host_url}/unsubscribe/{sub.unsubscribe_token}"

            subject = f"New from {shop.name}"
            message_text = build_digest_text(shop.name, items, unsubscribe_url)
            message_html = build_digest_html(
                shop.name, items, unsubscribe_url, get_endpoint
            )

            if dry_run:
                logger.info(
                    f"[DRY RUN] Would send digest to {sub.email} for shop '{shop.name}' "
                    f"with {len(items)} item(s)"
                )
            else:
                try:
                    send_email(
                        sub.email,
                        sender_email,
                        subject,
                        message_text,
                        message_html,
                        relay,
                        dkim_private_key_path,
                        dkim_selector,
                        dkim_signature_algorithm,
                    )
                    logger.info(
                        f"Sent digest to {sub.email} for shop '{shop.name}' "
                        f"with {len(items)} item(s)"
                    )
                except Exception as e:
                    logger.error(
                        f"Failed to send digest to {sub.email} for shop '{shop.name}': {e}"
                    )
                    continue

            # Update last_digest_timestamp
            sub.last_digest_timestamp = now_timestamp()


def main(argv=sys.argv):
    args = parse_args(argv)
    setup_logging(args.config_uri)

    logger.info(
        f"Digest sender started: frequency={args.frequency}, dry_run={args.dry_run}"
    )

    with bootstrap(args.config_uri) as env:
        try:
            with transaction.manager:
                run(env, args.frequency, args.dry_run)
        finally:
            logger.info("Digest sender finished")


if __name__ == "__main__":
    main()
