"""
Suppliers domain: signup wizard, lead feed, dashboard, and supplier-facing features.
"""

import json
from pathlib import Path

from quart import Blueprint, flash, g, jsonify, redirect, render_template, request, url_for
from werkzeug.utils import secure_filename

from ..core import (
    capture_waitlist_email,
    config,
    count_where,
    csrf_protect,
    execute,
    feature_gate,
    fetch_all,
    fetch_one,
    get_all_price_ids,
    get_price_id,
    is_flag_enabled,
)
from ..i18n import get_translations

bp = Blueprint(
    "suppliers",
    __name__,
    template_folder=str(Path(__file__).parent / "templates"),
    url_prefix="/suppliers",
)


# =============================================================================
# Helpers
# =============================================================================

PLAN_FEATURES = {
    "supplier_basic": {
        "name": "Basic",
        "monthly_price": 0,
        "yearly_price": 0,
        "yearly_monthly_equivalent": 0,
        "monthly_credits": 0,
        "paddle_key_monthly": "supplier_basic_monthly",
        "paddle_key_yearly": "supplier_basic_yearly",
        "feature_keys": [
            "plan_basic_f1",
            "plan_basic_f2",
            "plan_basic_f3",
            "plan_basic_f4",
            "plan_basic_f5",
            "plan_basic_f6",
            "plan_basic_f7",
        ],
    },
    "supplier_growth": {
        "name": "Growth",
        "monthly_price": 199,
        "yearly_price": 1799,
        "yearly_monthly_equivalent": 150,
        "monthly_credits": 30,
        "paddle_key_monthly": "supplier_growth",
        "paddle_key_yearly": "supplier_growth_yearly",
        "feature_keys": [
            "plan_growth_f1",
            "plan_growth_f2",
            "plan_growth_f3",
            "plan_growth_f4",
        ],
    },
    "supplier_pro": {
        "name": "Pro",
        "monthly_price": 499,
        "yearly_price": 4499,
        "yearly_monthly_equivalent": 375,
        "monthly_credits": 100,
        "paddle_key_monthly": "supplier_pro",
        "paddle_key_yearly": "supplier_pro_yearly",
        "includes": ["logo", "highlight", "verified"],
        "feature_keys": [
            "plan_pro_f1",
            "plan_pro_f2",
            "plan_pro_f3",
            "plan_pro_f4",
            "plan_pro_f5",
        ],
    },
}

BOOST_OPTIONS = [
    {
        "key": "boost_logo",
        "type": "logo",
        "name_key": "sd_boost_logo_name",
        "price": 29,
        "desc_key": "sd_boost_logo_desc",
    },
    {
        "key": "boost_highlight",
        "type": "highlight",
        "name_key": "sd_boost_highlight_name",
        "price": 39,
        "desc_key": "sd_boost_highlight_desc",
    },
    {
        "key": "boost_verified",
        "type": "verified",
        "name_key": "sd_boost_verified_name",
        "price": 49,
        "desc_key": "sd_boost_verified_desc",
    },
    {
        "key": "boost_card_color",
        "type": "card_color",
        "name_key": "sd_boost_card_color_name",
        "price": 59,
        "desc_key": "sd_boost_card_color_desc",
    },
]

CREDIT_PACK_OPTIONS = [
    {"key": "credits_25", "amount": 25, "price": 99},
    {"key": "credits_50", "amount": 50, "price": 179},
    {"key": "credits_100", "amount": 100, "price": 329},
    {"key": "credits_250", "amount": 250, "price": 749},
]

SERVICE_CATEGORIES = [
    "manufacturer",
    "turnkey",
    "consultant",
    "hall_builder",
    "turf",
    "lighting",
    "software",
    "industry_body",
    "franchise",
]

COUNTRIES = [
    "DE",
    "ES",
    "IT",
    "FR",
    "PT",
    "GB",
    "NL",
    "BE",
    "SE",
    "DK",
    "FI",
    "NO",
    "AT",
    "SI",
    "IS",
    "CH",
    "EE",
    "US",
    "CA",
    "MX",
    "BR",
    "AR",
    "AE",
    "SA",
    "TR",
    "CN",
    "IN",
    "SG",
    "ID",
    "TH",
    "AU",
    "ZA",
    "EG",
]


def _parse_accumulated(form_or_args):
    """Parse accumulated JSON from form data or query args."""
    raw = form_or_args.get("_accumulated", "{}")
    try:
        return json.loads(raw)
    except (json.JSONDecodeError, TypeError):
        return {}


def _get_supplier_for_user(user_id: int):
    """Get the supplier record claimed by a user."""
    return fetch_one("SELECT * FROM suppliers WHERE claimed_by = ?", (user_id,))


# =============================================================================
# Auth decorator
# =============================================================================


def _supplier_required(f):
    """Require authenticated user with a claimed supplier on any paid tier (basic, growth, pro)."""
    from functools import wraps

    @wraps(f)
    async def decorated(*args, **kwargs):
        t = get_translations(g.get("lang") or "en")
        if not g.get("user"):
            await flash(t["sd_flash_signin"], "warning")
            return redirect(url_for("auth.login", next=request.path))
        supplier = await fetch_one(
            "SELECT * FROM suppliers WHERE claimed_by = ? AND tier IN ('basic', 'growth', 'pro')",
            (g.user["id"],),
        )
        if not supplier:
            await flash(t["sd_flash_active_plan"], "warning")
            return redirect(url_for("suppliers.signup"))
        g.supplier = supplier
        return await f(*args, **kwargs)

    return decorated


def _lead_tier_required(f):
    """Require authenticated user with growth or pro tier (lead credit access)."""
    from functools import wraps

    @wraps(f)
    async def decorated(*args, **kwargs):
        t = get_translations(g.get("lang") or "en")
        if not g.get("user"):
            await flash(t["sd_flash_signin"], "warning")
            return redirect(url_for("auth.login", next=request.path))
        supplier = await fetch_one(
            "SELECT * FROM suppliers WHERE claimed_by = ? AND tier IN ('growth', 'pro')",
            (g.user["id"],),
        )
        if not supplier:
            await flash(t["sd_flash_lead_access"], "warning")
            return redirect(url_for("suppliers.dashboard"))
        g.supplier = supplier
        return await f(*args, **kwargs)

    return decorated


# =============================================================================
# Signup Wizard
# =============================================================================


@bp.route("/signup")
@feature_gate(
    "supplier_signup", "suppliers/waitlist.html",
    plan=lambda: request.args.get("plan", "supplier_growth"),
    plans=lambda: PLAN_FEATURES,
)
async def signup():
    """Render signup wizard shell with step 1."""
    # Normal signup wizard flow
    claim_slug = request.args.get("claim", "")
    prefill = {}
    if claim_slug:
        supplier = await fetch_one("SELECT * FROM suppliers WHERE slug = ?", (claim_slug,))
        if supplier:
            prefill = {
                "claim_slug": claim_slug,
                "supplier_id": supplier["id"],
                "supplier_name": supplier["name"],
            }

    return await render_template(
        "suppliers/signup.html",
        data=prefill,
        step=1,
        plans=PLAN_FEATURES,
        boosts=BOOST_OPTIONS,
        credit_packs=CREDIT_PACK_OPTIONS,
    )


@bp.route("/signup/waitlist", methods=["POST"])
@csrf_protect
async def signup_waitlist():
    """Capture supplier waitlist submission."""
    form = await request.form
    email = form.get("email", "").strip().lower()
    plan = form.get("plan", "supplier_growth")

    if not email or "@" not in email:
        t = get_translations(g.get("lang") or "en")
        await flash(t["sd_flash_valid_email"], "error")
        return redirect(url_for("suppliers.signup", plan=plan))

    # Capture to DB with intent="supplier", but email confirmation uses plan name
    await capture_waitlist_email(email, intent="supplier", plan=plan, email_intent=plan)

    return await render_template(
        "suppliers/waitlist_confirmed.html",
        email=email,
        plan=plan,
        plans=PLAN_FEATURES,
    )


@bp.route("/signup/step/<int:step>", methods=["POST"])
@csrf_protect
async def signup_step(step: int):
    """HTMX endpoint — validate current step and return next step partial."""
    form = await request.form
    accumulated = _parse_accumulated(form)

    # Merge current step's fields
    for k, v in form.items():
        if k.startswith("_") or k == "csrf_token":
            continue
        accumulated[k] = v

    # Handle multi-value checkboxes
    boosts = form.getlist("boosts")
    if boosts:
        accumulated["boosts"] = boosts

    next_step = step + 1
    if next_step > 4:
        next_step = 4

    # Determine included boosts from plan
    plan = accumulated.get("plan", "supplier_growth")
    plan_info = PLAN_FEATURES.get(plan, PLAN_FEATURES["supplier_growth"])
    included_boosts = plan_info.get("includes", [])

    # Compute order summary for step 4
    order = _compute_order(accumulated, included_boosts, get_translations(g.lang))

    return await render_template(
        f"suppliers/partials/signup_step_{next_step}.html",
        data=accumulated,
        step=next_step,
        plans=PLAN_FEATURES,
        boosts=BOOST_OPTIONS,
        credit_packs=CREDIT_PACK_OPTIONS,
        included_boosts=included_boosts,
        order=order,
    )


def _compute_order(data: dict, included_boosts: list, t: dict) -> dict:
    """Compute order summary from accumulated wizard state."""
    plan = data.get("plan", "supplier_growth")
    plan_info = PLAN_FEATURES.get(plan, PLAN_FEATURES["supplier_growth"])
    period = data.get("billing_period", "yearly")

    if period == "yearly":
        plan_price = plan_info["yearly_price"]
        plan_price_display = plan_info["yearly_monthly_equivalent"]
        billing_label = t["sd_billing_yearly"].format(price=plan_price)
    else:
        plan_price = plan_info["monthly_price"]
        plan_price_display = plan_info["monthly_price"]
        billing_label = t["sd_billing_monthly"]

    one_time = 0
    selected_boosts = data.get("boosts", [])
    boost_monthly = 0
    for b in BOOST_OPTIONS:
        if b["type"] in selected_boosts and b["type"] not in included_boosts:
            boost_monthly += b["price"]

    credit_pack = data.get("credit_pack", "")
    for cp in CREDIT_PACK_OPTIONS:
        if cp["key"] == credit_pack:
            one_time += cp["price"]

    return {
        "plan_name": plan_info["name"],
        "plan_price": plan_price,
        "plan_price_display": plan_price_display,
        "billing_label": billing_label,
        "billing_period": period,
        "boost_monthly": boost_monthly,
        "monthly_total": plan_price_display + boost_monthly,
        "one_time_total": one_time,
        "credit_pack": credit_pack,
    }


@bp.route("/signup/checkout", methods=["POST"])
@csrf_protect
async def signup_checkout():
    """Validate form, return checkout JSON (Paddle overlay or Stripe redirect)."""
    from ..billing.routes import _provider

    form = await request.form
    accumulated = _parse_accumulated(form)

    # Merge final step fields
    for k, v in form.items():
        if k.startswith("_") or k == "csrf_token":
            continue
        accumulated[k] = v

    plan = accumulated.get("plan", "supplier_growth")
    plan_info = PLAN_FEATURES.get(plan, {})
    period = accumulated.get("billing_period", "yearly")
    price_key = (
        plan_info.get("paddle_key_yearly", plan)
        if period == "yearly"
        else plan_info.get("paddle_key_monthly", plan)
    )
    plan_price_id = await get_price_id(price_key)
    if not plan_price_id:
        return jsonify({"error": "Invalid plan selected. Run setup first."}), 400

    # Build items list
    items = [{"priceId": plan_price_id, "quantity": 1}]

    # Add boost add-ons
    included_boosts = plan_info.get("includes", [])
    selected_boosts = accumulated.get("boosts", [])
    if isinstance(selected_boosts, str):
        selected_boosts = [selected_boosts]

    for b in BOOST_OPTIONS:
        if b["type"] in selected_boosts and b["type"] not in included_boosts:
            price_id = await get_price_id(b["key"])
            if price_id:
                items.append({"priceId": price_id, "quantity": 1})

    # Add credit pack (one-time)
    credit_pack = accumulated.get("credit_pack", "")
    if credit_pack:
        price_id = await get_price_id(credit_pack)
        if price_id:
            items.append({"priceId": price_id, "quantity": 1})

    # Get or create user
    email = accumulated.get("contact_email", "").strip().lower()
    if not email:
        return jsonify({"error": "Email is required."}), 400

    from ..auth.routes import create_user, get_user_by_email

    user = await get_user_by_email(email)
    if not user:
        user_id = await create_user(email)
    else:
        user_id = user["id"]

    # Resolve supplier_id
    supplier_id = accumulated.get("supplier_id", "")
    if not supplier_id:
        claim_slug = accumulated.get("claim_slug", "")
        if claim_slug:
            sup = await fetch_one("SELECT id FROM suppliers WHERE slug = ?", (claim_slug,))
            if sup:
                supplier_id = str(sup["id"])

    # Save profile fields on supplier (if claiming)
    if supplier_id:
        sid = int(supplier_id)
        await execute(
            """UPDATE suppliers SET
               contact_name = ?, contact_email = ?, contact_phone = ?,
               short_description = ?, service_categories = ?, service_area = ?,
               years_in_business = ?, project_count = ?
               WHERE id = ? AND claimed_by IS NULL""",
            (
                accumulated.get("contact_name", ""),
                email,
                accumulated.get("contact_phone", ""),
                accumulated.get("short_description", ""),
                accumulated.get("service_categories", ""),
                accumulated.get("service_area", ""),
                int(accumulated.get("years_in_business", 0) or 0),
                int(accumulated.get("project_count", 0) or 0),
                sid,
            ),
        )

    custom_data = {
        "user_id": str(user_id),
        "supplier_id": str(supplier_id) if supplier_id else "",
        "plan": plan,
    }

    payload = _provider().build_multi_item_checkout_payload(
        items=items,
        custom_data=custom_data,
        success_url=f"{config.BASE_URL}/suppliers/signup/success",
    )
    return jsonify(payload)


@bp.route("/claim/<slug>")
async def claim(slug: str):
    """Verify supplier is unclaimed and redirect to signup with pre-fill."""
    supplier = await fetch_one(
        "SELECT * FROM suppliers WHERE slug = ? AND claimed_by IS NULL", (slug,)
    )
    if not supplier:
        t = get_translations(g.get("lang") or "en")
        await flash(t["sd_flash_claim_error"], "warning")
        return redirect(url_for("directory.index"))
    return redirect(url_for("suppliers.signup", claim=slug))


@bp.route("/signup/success")
async def signup_success():
    """Post-checkout confirmation page."""
    return await render_template("suppliers/signup_success.html")


# =============================================================================
# Supplier Lead Feed
# =============================================================================


async def _get_lead_feed_data(supplier, country="", heat="", timeline="", q="", limit=50):
    """Shared query for lead feed — used by standalone and dashboard."""
    wheres = ["lr.lead_type = 'quote'", "lr.status = 'new'", "lr.verified_at IS NOT NULL", "lr.visible_from <= datetime('now')"]
    params: list = []

    if country:
        wheres.append("lr.country = ?")
        params.append(country)
    if heat:
        wheres.append("lr.heat_score = ?")
        params.append(heat)
    if timeline:
        wheres.append("lr.timeline = ?")
        params.append(timeline)
    if q:
        wheres.append("(lr.country LIKE ? OR lr.facility_type LIKE ? OR lr.additional_info LIKE ?)")
        like_q = f"%{q}%"
        params.extend([like_q, like_q, like_q])

    where = " AND ".join(wheres)
    params.append(limit)

    leads = await fetch_all(
        f"""SELECT lr.*,
            (SELECT lf.id FROM lead_forwards lf WHERE lf.lead_id = lr.id AND lf.supplier_id = ? LIMIT 1) as forward_id,
            (SELECT lf.created_at FROM lead_forwards lf WHERE lf.lead_id = lr.id AND lf.supplier_id = ? LIMIT 1) as forward_created_at,
            (SELECT lf.guarantee_claimed_at FROM lead_forwards lf WHERE lf.lead_id = lr.id AND lf.supplier_id = ? LIMIT 1) as guarantee_claimed_at,
            (SELECT lf.id FROM lead_forwards lf WHERE lf.lead_id = lr.id AND lf.supplier_id = ? LIMIT 1) IS NOT NULL as is_unlocked,
            (SELECT COUNT(*) FROM lead_forwards lf2 WHERE lf2.lead_id = lr.id) as bidder_count
            FROM lead_requests lr
            WHERE {where}
            ORDER BY lr.created_at DESC LIMIT ?""",
        (supplier["id"], supplier["id"], supplier["id"], supplier["id"], *params),
    )

    countries = await fetch_all(
        "SELECT DISTINCT country FROM lead_requests WHERE country IS NOT NULL AND country != '' AND lead_type = 'quote' ORDER BY country"
    )

    return leads, [c["country"] for c in countries]


@bp.route("/leads")
@_lead_tier_required
async def lead_feed():
    """Lead feed for paying suppliers (standalone page)."""
    supplier = g.supplier
    country = request.args.get("country", "")
    heat = request.args.get("heat", "")

    leads, countries = await _get_lead_feed_data(supplier, country, heat)

    return await render_template(
        "suppliers/lead_feed.html",
        leads=leads,
        supplier=supplier,
        countries=countries,
        current_country=country,
        current_heat=heat,
    )


@bp.route("/leads/<token>/unlock", methods=["POST"])
@_lead_tier_required
@csrf_protect
async def unlock_lead(token: str):
    """Spend credits to unlock a lead. Returns full-details card via HTMX."""
    if not await is_flag_enabled("lead_unlock"):
        return jsonify({"error": "Lead unlock is not available yet."}), 403

    from ..credits import InsufficientCredits
    from ..credits import unlock_lead as do_unlock

    supplier = g.supplier

    # Resolve opaque token to integer ID for internal operations
    lead_row = await fetch_one("SELECT id FROM lead_requests WHERE token = ?", (token,))
    if not lead_row:
        return jsonify({"error": "Lead not found."}), 404
    lead_id = lead_row["id"]

    try:
        result = await do_unlock(supplier["id"], lead_id)
    except InsufficientCredits as e:
        return await render_template(
            "suppliers/partials/lead_card_error.html",
            balance=e.balance,
            required=e.required,
            lead_id=lead_id,
        )
    except ValueError as e:
        return await render_template(
            "suppliers/partials/lead_card_error.html",
            error=str(e),
            lead_id=lead_id,
        )

    # Enqueue lead forward email
    from ..worker import enqueue

    lang = g.get("lang", "en")
    await enqueue(
        "send_lead_forward_email",
        {
            "lead_id": lead_id,
            "supplier_id": supplier["id"],
            "lang": lang,
        },
    )

    # Notify entrepreneur on first unlock
    lead = result["lead"]
    if lead.get("unlock_count", 0) <= 1:
        await enqueue("send_lead_matched_notification", {"lead_id": lead_id, "lang": lang})

    # Return full details card
    full_lead = await fetch_one("SELECT * FROM lead_requests WHERE id = ?", (lead_id,))
    updated_supplier = await fetch_one("SELECT * FROM suppliers WHERE id = ?", (supplier["id"],))

    # Look up linked scenario
    scenario_id = None
    if full_lead and full_lead.get("user_id"):
        scenario = await fetch_one(
            "SELECT id FROM scenarios WHERE user_id = ? AND deleted_at IS NULL ORDER BY updated_at DESC LIMIT 1",
            (full_lead["user_id"],),
        )
        if scenario:
            scenario_id = scenario["id"]

    return await render_template(
        "suppliers/partials/lead_card_unlocked.html",
        lead=full_lead,
        supplier=updated_supplier,
        credit_cost=result["credit_cost"],
        scenario_id=scenario_id,
        forward_id=result["forward_id"],
    )


@bp.route("/leads/<int:forward_id>/guarantee-claim", methods=["POST"])
@_lead_tier_required
@csrf_protect
async def guarantee_claim(forward_id: int):
    """Claim lead-back guarantee: return credits for a non-responding lead.

    Validates the 3–30 day window and contact method, then calls
    credits.refund_lead_guarantee(). Returns an updated lead card partial.
    """
    from ..credits import GuaranteeAlreadyClaimed, GuaranteeWindowClosed, refund_lead_guarantee

    t = get_translations(g.get("lang") or "en")
    supplier = g.supplier

    form = await request.form
    contact_method = form.get("contact_method", "")
    if contact_method not in ("email", "phone", "both"):
        return t["sd_guarantee_window_error"], 400

    try:
        await refund_lead_guarantee(
            supplier["id"], forward_id, contact_method
        )
    except GuaranteeAlreadyClaimed:
        return t["sd_guarantee_already_claimed"], 409
    except GuaranteeWindowClosed:
        return t["sd_guarantee_window_error"], 409
    except AssertionError:
        return "Lead not found.", 404

    updated_supplier = await fetch_one(
        "SELECT * FROM suppliers WHERE id = ?", (supplier["id"],)
    )
    forward = await fetch_one(
        """SELECT lf.*, lr.*
           FROM lead_forwards lf
           JOIN lead_requests lr ON lf.lead_id = lr.id
           WHERE lf.id = ?""",
        (forward_id,),
    )

    return await render_template(
        "suppliers/partials/lead_card_unlocked.html",
        lead=forward,
        supplier=updated_supplier,
        guarantee_claimed=True,
        guarantee_success_msg=t["sd_guarantee_success"],
    )


FORWARD_STATUSES = ["sent", "viewed", "contacted", "quoted", "won", "lost", "no_response"]


@bp.route("/leads/<token>/respond", methods=["POST"])
@_lead_tier_required
@csrf_protect
async def lead_respond(token: str):
    """Update response status on a forwarded lead. HTMX or full-page."""
    supplier = g.supplier
    form = await request.form
    new_status = form.get("status", "")
    note = form.get("note", "").strip()

    if new_status not in FORWARD_STATUSES:
        return "Invalid status", 422

    lead_row = await fetch_one(
        "SELECT id FROM lead_requests WHERE token = ?", (token,)
    )
    if not lead_row:
        return "Lead not found", 404

    from ..core import utcnow_iso
    await execute(
        """UPDATE lead_forwards
           SET status = ?, supplier_note = ?, status_updated_at = ?
           WHERE lead_id = ? AND supplier_id = ?""",
        (new_status, note or None, utcnow_iso(), lead_row["id"], supplier["id"]),
    )
    return "", 204


@bp.route("/leads/cta/<cta_token>")
async def lead_cta_contacted(cta_token: str):
    """One-click CTA from forward email: mark as contacted, redirect to dashboard."""
    row = await fetch_one(
        "SELECT id, lead_id, supplier_id, status FROM lead_forwards WHERE cta_token = ?",
        (cta_token,),
    )
    if not row:
        return redirect(url_for("suppliers.dashboard"))

    if row["status"] == "sent":
        from ..core import utcnow_iso
        await execute(
            "UPDATE lead_forwards SET status = 'contacted', status_updated_at = ? WHERE id = ?",
            (utcnow_iso(), row["id"]),
        )
    return redirect(url_for("suppliers.dashboard") + "?tab=leads")


# =============================================================================
# Supplier Dashboard
# =============================================================================


@bp.route("/dashboard")
@_supplier_required
async def dashboard():
    """Dashboard shell — defaults to overview tab."""
    supplier = g.supplier
    tab = request.args.get("tab", "overview")
    return await render_template(
        "suppliers/dashboard.html",
        supplier=supplier,
        active_tab=tab,
    )


@bp.route("/dashboard/overview")
@_supplier_required
async def dashboard_overview():
    """HTMX partial — overview tab content."""
    supplier = g.supplier

    # Leads unlocked count
    leads_unlocked = await count_where(
        "lead_forwards WHERE supplier_id = ?", (supplier["id"],)
    )

    # New leads matching supplier's area since last login
    service_area = (supplier.get("service_area") or "").split(",")
    service_area = [c.strip() for c in service_area if c.strip()]
    new_leads_count = 0
    if service_area:
        placeholders = ",".join("?" * len(service_area))
        new_leads_count = await count_where(
            f"""lead_requests
                WHERE lead_type = 'quote' AND status = 'new' AND verified_at IS NOT NULL
                AND country IN ({placeholders})
                AND NOT EXISTS (SELECT 1 FROM lead_forwards WHERE lead_id = lead_requests.id AND supplier_id = ?)""",
            (*service_area, supplier["id"]),
        )
    else:
        new_leads_count = await count_where(
            """lead_requests
               WHERE lead_type = 'quote' AND status = 'new' AND verified_at IS NOT NULL
               AND NOT EXISTS (SELECT 1 FROM lead_forwards WHERE lead_id = lead_requests.id AND supplier_id = ?)""",
            (supplier["id"],),
        )

    # Recent activity (last 10 events from credit_ledger + lead_forwards)
    recent_activity = await fetch_all(
        """SELECT 'credit' as type, event_type, delta, note, created_at
           FROM credit_ledger WHERE supplier_id = ?
           UNION ALL
           SELECT 'forward' as type, 'lead_unlock' as event_type, -credit_cost as delta,
                  'Lead #' || lead_id as note, created_at
           FROM lead_forwards WHERE supplier_id = ?
           ORDER BY created_at DESC LIMIT 10""",
        (supplier["id"], supplier["id"]),
    )

    # Active boosts
    active_boosts = await fetch_all(
        "SELECT * FROM supplier_boosts WHERE supplier_id = ? AND status = 'active'",
        (supplier["id"],),
    )

    # Enquiry count for Basic tier
    enquiry_count = 0
    if supplier.get("tier") == "basic":
        enquiry_count = await count_where(
            "supplier_enquiries WHERE supplier_id = ?", (supplier["id"],)
        )

    return await render_template(
        "suppliers/partials/dashboard_overview.html",
        supplier=supplier,
        leads_unlocked=leads_unlocked,
        new_leads_count=new_leads_count,
        recent_activity=recent_activity,
        active_boosts=active_boosts,
        enquiry_count=enquiry_count,
    )


@bp.route("/dashboard/leads")
@_lead_tier_required
async def dashboard_leads():
    """HTMX partial — lead feed tab in dashboard context."""
    supplier = g.supplier
    country = request.args.get("country", "")
    heat = request.args.get("heat", "")
    timeline = request.args.get("timeline", "")
    q = request.args.get("q", "").strip()

    leads, countries = await _get_lead_feed_data(supplier, country, heat, timeline, q)

    # Parse supplier's service area for region matching
    service_area = [c.strip() for c in (supplier.get("service_area") or "").split(",") if c.strip()]

    # Look up scenario IDs for unlocked leads
    scenario_ids = {}
    unlocked_user_ids = [
        lead["user_id"] for lead in leads if lead.get("is_unlocked") and lead.get("user_id")
    ]
    if unlocked_user_ids:
        placeholders = ",".join("?" * len(unlocked_user_ids))
        scenarios = await fetch_all(
            f"SELECT user_id, id FROM scenarios WHERE user_id IN ({placeholders}) AND deleted_at IS NULL ORDER BY updated_at DESC",
            tuple(unlocked_user_ids),
        )
        for s in scenarios:
            if s["user_id"] not in scenario_ids:
                scenario_ids[s["user_id"]] = s["id"]

    return await render_template(
        "suppliers/partials/dashboard_leads.html",
        leads=leads,
        supplier=supplier,
        countries=countries,
        current_country=country,
        current_heat=heat,
        current_timeline=timeline,
        current_q=q,
        service_area=service_area,
        scenario_ids=scenario_ids,
    )


@bp.route("/dashboard/listing", methods=["GET"])
@_supplier_required
async def dashboard_listing():
    """HTMX partial — My Listing tab."""
    supplier = g.supplier

    # Get active boosts for preview
    boosts = await fetch_all(
        "SELECT boost_type FROM supplier_boosts WHERE supplier_id = ? AND status = 'active'",
        (supplier["id"],),
    )
    active_boosts = [b["boost_type"] for b in boosts]

    return await render_template(
        "suppliers/partials/dashboard_listing.html",
        supplier=supplier,
        active_boosts=active_boosts,
        service_categories=SERVICE_CATEGORIES,
        countries=COUNTRIES,
    )


@bp.route("/dashboard/listing/preview")
@_supplier_required
async def dashboard_listing_preview():
    """HTMX partial — returns just the preview card with form values overlaid."""
    supplier = g.supplier
    args = request.args

    # Overlay form values onto supplier dict for preview
    preview = dict(supplier)
    for field in ("name", "tagline", "short_description", "website"):
        if args.get(field) is not None:
            preview[field] = args.get(field)

    boosts = await fetch_all(
        "SELECT boost_type FROM supplier_boosts WHERE supplier_id = ? AND status = 'active'",
        (supplier["id"],),
    )
    active_boosts = [b["boost_type"] for b in boosts]

    return await render_template(
        "suppliers/partials/dashboard_listing_preview.html",
        supplier=preview,
        active_boosts=active_boosts,
    )


@bp.route("/dashboard/listing", methods=["POST"])
@_supplier_required
@csrf_protect
async def dashboard_listing_save():
    """Save listing edits, return updated partial."""
    supplier = g.supplier
    form = await request.form

    # Handle file uploads
    files = await request.files
    logo_file = files.get("logo_file")
    logo_path = supplier.get("logo_file") or ""
    if logo_file and logo_file.filename:
        upload_dir = Path(__file__).parent.parent / "static" / "uploads" / "logos"
        upload_dir.mkdir(parents=True, exist_ok=True)
        filename = secure_filename(f"{supplier['id']}_{logo_file.filename}")
        save_path = upload_dir / filename
        await logo_file.save(str(save_path))
        logo_path = f"/static/uploads/logos/{filename}"

    cover_file = files.get("cover_file")
    cover_path = supplier.get("cover_image") or ""
    if cover_file and cover_file.filename:
        upload_dir = Path(__file__).parent.parent / "static" / "uploads" / "covers"
        upload_dir.mkdir(parents=True, exist_ok=True)
        filename = secure_filename(f"{supplier['id']}_{cover_file.filename}")
        save_path = upload_dir / filename
        await cover_file.save(str(save_path))
        cover_path = f"/static/uploads/covers/{filename}"

    # Multi-select categories
    categories = form.getlist("service_categories")
    categories_str = ",".join(categories)

    # Multi-select service area
    areas = form.getlist("service_area")
    area_str = ",".join(areas)

    # Multi-value services offered
    services = form.getlist("services_offered")
    services_str = ",".join(services)

    await execute(
        """UPDATE suppliers SET
           name = ?, tagline = ?, short_description = ?, long_description = ?,
           website = ?, contact_name = ?, contact_email = ?, contact_phone = ?,
           service_categories = ?, service_area = ?,
           years_in_business = ?, project_count = ?,
           logo_file = ?, cover_image = ?,
           services_offered = ?, contact_role = ?,
           linkedin_url = ?, instagram_url = ?, youtube_url = ?
           WHERE id = ?""",
        (
            form.get("name", supplier["name"]),
            form.get("tagline", ""),
            form.get("short_description", ""),
            form.get("long_description", ""),
            form.get("website", ""),
            form.get("contact_name", ""),
            form.get("contact_email", ""),
            form.get("contact_phone", ""),
            categories_str,
            area_str,
            int(form.get("years_in_business", 0) or 0),
            int(form.get("project_count", 0) or 0),
            logo_path,
            cover_path,
            services_str,
            form.get("contact_role", ""),
            form.get("linkedin_url", ""),
            form.get("instagram_url", ""),
            form.get("youtube_url", ""),
            supplier["id"],
        ),
    )

    # Reload supplier and boosts
    updated_supplier = await fetch_one("SELECT * FROM suppliers WHERE id = ?", (supplier["id"],))
    boosts = await fetch_all(
        "SELECT boost_type FROM supplier_boosts WHERE supplier_id = ? AND status = 'active'",
        (supplier["id"],),
    )
    active_boosts = [b["boost_type"] for b in boosts]

    return await render_template(
        "suppliers/partials/dashboard_listing.html",
        supplier=updated_supplier,
        active_boosts=active_boosts,
        service_categories=SERVICE_CATEGORIES,
        countries=COUNTRIES,
        saved=True,
    )


@bp.route("/dashboard/boosts")
@_supplier_required
async def dashboard_boosts():
    """HTMX partial — Boost & Upsells tab."""
    supplier = g.supplier

    active_boosts = await fetch_all(
        "SELECT * FROM supplier_boosts WHERE supplier_id = ? AND status = 'active'",
        (supplier["id"],),
    )

    # Resolve price IDs for buy buttons (from active provider)
    price_ids = await get_all_price_ids()

    return await render_template(
        "suppliers/partials/dashboard_boosts.html",
        supplier=supplier,
        active_boosts=active_boosts,
        boost_options=BOOST_OPTIONS,
        credit_packs=CREDIT_PACK_OPTIONS,
        plan_features=PLAN_FEATURES,
        price_ids=price_ids,
    )
