"""Custom Flask CLI commands.

Registered on the application in the factory via ``app.cli.add_command``.
"""

from __future__ import annotations

import click
from flask.cli import with_appcontext

from app.extensions import db
from app.models import Advertisement, Category
from app.models.enums import AdvertisementPlacement, AdvertisementType

# Default marketplace categories for a fresh install.
DEFAULT_CATEGORIES = [
    ("Textbooks", "Course books, study guides and notes."),
    ("Electronics", "Laptops, phones, accessories and gadgets."),
    ("Furniture", "Desks, chairs, lamps and dorm furniture."),
    ("Stationery", "Pens, notebooks and supplies."),
    ("Clothing", "Apparel, footwear and accessories."),
    ("Sports & Fitness", "Gym gear, bikes and sports equipment."),
    ("Other", "Anything that does not fit another category."),
]


@click.command("seed-categories")
@with_appcontext
def seed_categories() -> None:
    """Create the default marketplace categories (idempotent)."""
    created = 0
    for order, (name, description) in enumerate(DEFAULT_CATEGORIES, start=1):
        exists = db.session.scalar(db.select(Category).filter_by(name=name))
        if exists:
            continue
        db.session.add(
            Category(
                name=name,
                description=description,
                display_order=order,
                is_active=True,
            )
        )
        created += 1
    db.session.commit()
    click.echo(f"Seeded {created} new categor{'y' if created == 1 else 'ies'}.")


# Default internal promotions (ProvatSoft ecosystem) + a rewarded ad. Data-driven:
# adding a new promotion is a row, not a code change. (title, description,
# type, placement, redirect_url, priority)
DEFAULT_ADVERTISEMENTS = [
    (
        "SkillUp by ProvatSoft",
        "Level up with industry-ready courses built for students. Learn, build, get hired.",
        AdvertisementType.BANNER,
        AdvertisementPlacement.LANDING,
        "https://provatsoft.com/skillup",
        10,
    ),
    (
        "Build with ProvatSoft",
        "Custom software, web and mobile apps for teams and startups.",
        AdvertisementType.BANNER,
        AdvertisementPlacement.MARKETPLACE,
        "https://provatsoft.com",
        10,
    ),
    (
        "SkillUp — student discount",
        "Free campus workshops and discounted certifications this semester.",
        AdvertisementType.BANNER,
        AdvertisementPlacement.SIDEBAR,
        "https://provatsoft.com/skillup",
        10,
    ),
    (
        "Watch to unlock messages",
        "A short sponsored message from the ProvatSoft ecosystem.",
        AdvertisementType.REWARDED,
        AdvertisementPlacement.CHAT,
        "https://provatsoft.com",
        10,
    ),
]


@click.command("seed-advertisements")
@with_appcontext
def seed_advertisements() -> None:
    """Create the default ProvatSoft promotions and rewarded ad (idempotent)."""
    created = 0
    for title, description, ad_type, placement, url, priority in DEFAULT_ADVERTISEMENTS:
        exists = db.session.scalar(
            db.select(Advertisement).filter_by(title=title, placement=placement)
        )
        if exists:
            continue
        db.session.add(
            Advertisement(
                title=title,
                description=description,
                advertisement_type=ad_type,
                placement=placement,
                redirect_url=url,
                priority=priority,
                is_active=True,
            )
        )
        created += 1
    db.session.commit()
    click.echo(f"Seeded {created} new advertisement(s).")


@click.command("create-admin")
@click.argument("email")
@click.option("--name", default="Administrator", help="Display name for the admin.")
@click.password_option()
@with_appcontext
def create_admin(email: str, name: str, password: str) -> None:
    """Create a Super Admin account, or promote an existing user to admin."""
    from werkzeug.security import generate_password_hash

    from app.models import User, UserProfile
    from app.models.enums import UserRole

    normalized = email.strip().lower()
    user = db.session.scalar(db.select(User).filter_by(email=normalized))
    if user is None:
        user = User(
            email=normalized,
            password_hash=generate_password_hash(password),
            role=UserRole.SUPER_ADMIN,
            is_verified=True,
        )
        user.profile = UserProfile(full_name=name.strip())
        db.session.add(user)
        db.session.commit()
        click.echo(f"Created Super Admin: {normalized}")
    else:
        user.role = UserRole.SUPER_ADMIN
        user.password_hash = generate_password_hash(password)
        db.session.commit()
        click.echo(f"Promoted existing user to Super Admin: {normalized}")


@click.command("send-test-email")
@click.argument("recipient")
@with_appcontext
def send_test_email(recipient: str) -> None:
    """Send a diagnostic email to RECIPIENT, bypassing the OTP flow entirely.

    Prints the resolved mail configuration and the exact SMTP outcome. Use this
    to prove email delivery independently of registration:
        flask send-test-email you@example.com
    If this fails, the problem is mail configuration/credentials; if it
    succeeds, delivery works and any missing OTP email is inside the OTP flow.
    """
    from flask import current_app
    from flask_mail import Message

    from app.extensions import mail

    cfg = current_app.config
    click.echo("Mail configuration in use:")
    for key in ("MAIL_SERVER", "MAIL_PORT", "MAIL_USE_TLS", "MAIL_USE_SSL",
                "MAIL_USERNAME", "MAIL_DEFAULT_SENDER", "MAIL_SUPPRESS_SEND"):
        click.echo(f"  {key:20} = {cfg.get(key)!r}")
    pw = cfg.get("MAIL_PASSWORD")
    click.echo(f"  {'MAIL_PASSWORD':20} = {'set (len %d)' % len(pw) if pw else 'MISSING'}")

    if cfg.get("MAIL_SUPPRESS_SEND"):
        click.echo("WARNING: MAIL_SUPPRESS_SEND is True — no email will actually be sent.")

    click.echo(f"\nSending test email to {recipient} ...")
    try:
        mail.send(Message(
            subject="Student Bazaar — test email",
            recipients=[recipient],
            body="This is a Student Bazaar mail-delivery test. If you received "
                 "this, SMTP is configured correctly.",
        ))
    except Exception as exc:  # surfaced, never swallowed
        click.echo(f"FAILED: {type(exc).__name__}: {exc}")
        raise SystemExit(1)
    click.echo("SUCCESS: email handed off to the SMTP server. Check the inbox (and spam).")


@click.command("cleanup-trusted-devices")
@with_appcontext
def cleanup_trusted_devices() -> None:
    """Delete expired trusted-device records (safe housekeeping).

    Expired rows can no longer authenticate anything, so removing them keeps the
    table tidy. Idempotent; safe to run from cron:
        flask cleanup-trusted-devices
    """
    from app.auth.trusted_devices import cleanup_expired

    removed = cleanup_expired()
    click.echo(f"Removed {removed} expired trusted device(s).")


def register_cli(app) -> None:
    """Attach custom commands to the application's CLI."""
    app.cli.add_command(seed_categories)
    app.cli.add_command(seed_advertisements)
    app.cli.add_command(create_admin)
    app.cli.add_command(send_test_email)
    app.cli.add_command(cleanup_trusted_devices)
