/* Billing — Lemon Squeezy paywall, pricing, subscription management */
(function () {
  /** Synced from BILLING_ENABLED at build time (see billing-config.js). */
  const BILLING_ENABLED = window.BILLING_CONFIG?.enabled === true;

  /** Keep in sync with lib/billing/config.ts */
  const PRICING = {
    currency: "CAD",
    proMonthly: 39.39,
    payPerDownload: 9.99,
    ...(window.SEED?.BILLING || {}),
  };

  function isValidEmail(value) {
    const v = String(value || "").trim();
    if (!v) return true;
    return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i.test(v);
  }

  async function getAccessToken() {
    const sb = window.MartenSupabase?.getClient?.();
    if (!sb) return null;
    const { data } = await sb.auth.getSession();
    return data?.session?.access_token || null;
  }

  async function billingFetch(path, options = {}) {
    const token = await getAccessToken();
    if (!token) throw new Error("Not signed in.");

    const res = await fetch(path, {
      ...options,
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
        ...(options.headers || {}),
      },
    });

    const json = await res.json().catch(() => ({}));
    if (!res.ok) throw new Error(json.error || "Billing request failed.");
    return json;
  }

  const FREE_STATUS = {
    configured: false,
    billingDisabled: true,
    plan: "none",
    paymentMethodOnFile: true,
    proActive: false,
    subscriptionStatus: null,
    renewsAt: null,
    endsAt: null,
    lsCustomerId: null,
    pricing: PRICING,
  };

  const MartenBilling = {
    PRICING,

    isEnabled() {
      return BILLING_ENABLED;
    },

    async getStatus() {
      if (!BILLING_ENABLED) return { ...FREE_STATUS };
      return billingFetch("/api/billing/status");
    },

    async startCheckout(plan) {
      const { checkoutUrl } = await billingFetch("/api/billing/checkout", {
        method: "POST",
        body: JSON.stringify({ plan }),
      });
      return checkoutUrl;
    },

    async getPortalUrl() {
      const { portalUrl } = await billingFetch("/api/billing/portal");
      return portalUrl;
    },

    /** Returns { allowed, checkoutUrl?, needsCardSetup?, message? } */
    async authorizeDownload(documentType, documentId) {
      if (!BILLING_ENABLED) return { allowed: true, reason: "billing_disabled" };
      return billingFetch("/api/billing/download", {
        method: "POST",
        body: JSON.stringify({ documentType, documentId }),
      });
    },

    async guestDownloadStatus(guestToken, documentId, stripeSessionId) {
      const qs = new URLSearchParams({ guest_token: guestToken, document_id: documentId });
      if (stripeSessionId) qs.set("session_id", stripeSessionId);
      const res = await fetch(`/api/billing/guest-status?${qs}`);
      const json = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(json.error || "Could not verify payment.");
      return json;
    },

    /** Guest invoice generator — no sign-in. Server returns an error if checkout is not configured. */
    async guestCheckout(documentId, guestToken, email) {
      const res = await fetch("/api/billing/guest-checkout", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ documentId, guestToken, email }),
      });
      const json = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(json.error || "Could not start checkout.");
      return json;
    },

    async completeGuestDownload(guestToken, documentId) {
      const res = await fetch("/api/billing/guest-complete", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ guestToken, documentId }),
      });
      const json = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(json.error || "Could not complete download.");
      return json;
    },

    formatMoney(amount) {
      return new Intl.NumberFormat("en-CA", {
        style: "currency",
        currency: PRICING.currency || "CAD",
      }).format(amount);
    },

    getPayPerDownloadAmount() {
      return PRICING.payPerDownload;
    },

    formatPayPerDownload() {
      return MartenBilling.formatMoney(PRICING.payPerDownload);
    },

    isValidEmail,

    /** Block checkout until invoice form is complete and emails are valid. */
    validateInvoiceCheckout({ business, client, invoice, requireCheckoutEmail = false }) {
      const issues = [];
      const add = (field, label, message) => issues.push({ field, label, message });

      if (!business?.name?.trim()) {
        add("businessName", "Business name", "Enter your business name.");
      }

      const businessEmail = business?.email?.trim() || "";
      if (businessEmail && !isValidEmail(businessEmail)) {
        add("businessEmail", "Your email", "Enter a valid email (e.g. you@studio.com).");
      }

      if (!client?.name?.trim()) {
        add("clientName", "Client name", "Enter your client's name or company.");
      }

      const clientEmail = client?.email?.trim() || "";
      if (clientEmail && !isValidEmail(clientEmail)) {
        add("clientEmail", "Client email", "Enter a valid client email address.");
      }

      if (requireCheckoutEmail) {
        const hasValidBiz = businessEmail && isValidEmail(businessEmail);
        const hasValidClient = clientEmail && isValidEmail(clientEmail);
        if (!hasValidBiz && !hasValidClient) {
          if (!businessEmail && !clientEmail) {
            add(
              "businessEmail",
              "Email",
              "Enter your email or your client's email for payment and receipts."
            );
          } else {
            if (businessEmail && !isValidEmail(businessEmail)) {
              add("businessEmail", "Your email", "Fix your email address before checkout.");
            }
            if (clientEmail && !isValidEmail(clientEmail)) {
              add("clientEmail", "Client email", "Fix the client email address before checkout.");
            }
          }
        }
      }

      if (!invoice?.number?.trim()) {
        add("invoiceNumber", "Invoice number", "Enter an invoice number.");
      }

      if (!invoice?.date) {
        add("invoiceDate", "Invoice date", "Choose an invoice date.");
      }

      if (!invoice?.due) {
        add("invoiceDue", "Due date", "Choose a due date.");
      } else if (invoice?.date && invoice.due < invoice.date) {
        add("invoiceDue", "Due date", "Due date must be on or after the invoice date.");
      }

      const items = invoice?.items || [];
      const lineWithDesc = items.filter((it) => String(it.desc || "").trim());
      if (!lineWithDesc.length) {
        add("lineItems", "Line items", "Add at least one line item with a description.");
      } else {
        lineWithDesc.forEach((it, idx) => {
          const qty = Number(it.qty);
          if (!Number.isFinite(qty) || qty <= 0) {
            add(`lineItemQty_${idx}`, `Line ${idx + 1} quantity`, "Quantity must be greater than zero.");
          }
          const rate = Number(it.rate);
          if (!Number.isFinite(rate) || rate < 0) {
            add(`lineItemRate_${idx}`, `Line ${idx + 1} rate`, "Rate must be zero or a positive number.");
          }
        });
      }

      if (!issues.length) return { ok: true, issues: [] };

      const message =
        issues.length === 1
          ? `${issues[0].label}: ${issues[0].message}`
          : `Please fix ${issues.length} fields before continuing.`;

      return { ok: false, message, issues };
    },

    isProActive(status) {
      return Boolean(status?.proActive);
    },

    needsPaymentSetup(status) {
      if (!BILLING_ENABLED || status?.billingDisabled) return false;
      return Boolean(status?.configured && !status?.paymentMethodOnFile);
    },
  };

  window.MartenBilling = MartenBilling;

  function isPayPerDownloadUser(status) {
    return Boolean(status && !status.proActive && status.plan === "pay_per_download");
  }

  MartenBilling.isPayPerDownloadUser = isPayPerDownloadUser;

  /* ---------- Pricing cards (landing + upgrade) ---------- */
  function PricingCards({ onSelectPlan, compact = false, currentPlan = null, proOnly = false, landingPricing = false }) {
    const proPrice = MartenBilling.formatMoney(PRICING.proMonthly);
    const dlPrice = MartenBilling.formatMoney(PRICING.payPerDownload);

    if (landingPricing) {
      return (
        <div className="pricing-grid pricing-grid-landing">
          <article className={"pricing-card pricing-card-featured " + (currentPlan === "pro" ? "current" : "")}>
            <p className="pricing-kicker">Full studio</p>
            <h3>Pro Monthly</h3>
            <p className="pricing-amount">
              {proPrice}<span>/month</span>
            </p>
            <ul className="pricing-features">
              <li><Icon name="check" size={14} /> Unlimited invoice &amp; paystub downloads</li>
              <li><Icon name="check" size={14} /> Expenses, payroll, clients &amp; reports</li>
              <li><Icon name="check" size={14} /> Secure cloud workspace — sign in required</li>
            </ul>
            {onSelectPlan && (
              <button type="button" className="btn primary pricing-cta" onClick={() => onSelectPlan("pro")}>
                Get started with Pro
              </button>
            )}
          </article>

          <article className="pricing-card pricing-card-guest">
            <p className="pricing-kicker">One invoice</p>
            <h3>Pay per download</h3>
            <p className="pricing-amount">
              {dlPrice}<span>/invoice</span>
            </p>
            <ul className="pricing-features">
              <li><Icon name="check" size={14} /> No account — fill form &amp; preview free</li>
              <li><Icon name="check" size={14} /> Pay once to download your PDF</li>
              <li><Icon name="check" size={14} /> Secure checkout via Stripe</li>
            </ul>
            <a href="/invoice" className="btn pricing-cta">
              Create invoice
            </a>
          </article>
        </div>
      );
    }

    if (proOnly) {
      return (
        <div className="pricing-grid pricing-grid-single">
          <article className={"pricing-card pricing-card-featured " + (currentPlan === "pro" ? "current" : "")}>
            <p className="pricing-kicker">Pro plan</p>
            <h3>Pro Monthly</h3>
            <p className="pricing-amount">
              {proPrice}<span>/month</span>
            </p>
            <ul className="pricing-features">
              <li><Icon name="check" size={14} /> Unlimited invoice &amp; paystub downloads</li>
              <li><Icon name="check" size={14} /> Full workspace — expenses, payroll, reports</li>
              <li><Icon name="check" size={14} /> Cancel anytime from Settings</li>
            </ul>
            {onSelectPlan && (
              <button type="button" className="btn primary pricing-cta" onClick={() => onSelectPlan("pro")}>
                {currentPlan === "pro" ? "Current plan" : "Get started with Pro"}
              </button>
            )}
          </article>
        </div>
      );
    }

    return (
      <div className={"pricing-grid " + (compact ? "compact" : "")}>
        <article className={"pricing-card " + (currentPlan === "pro" ? "current" : "")}>
          <p className="pricing-kicker">Best value</p>
          <h3>Pro Monthly</h3>
          <p className="pricing-amount">
            {proPrice}<span>/month</span>
          </p>
          <ul className="pricing-features">
            <li><Icon name="check" size={14} /> Unlimited invoice &amp; paystub downloads</li>
            <li><Icon name="check" size={14} /> Full workspace — expenses, payroll, reports</li>
            <li><Icon name="check" size={14} /> Cancel anytime from Settings</li>
          </ul>
          {onSelectPlan && (
            <button type="button" className="btn primary pricing-cta" onClick={() => onSelectPlan("pro")}>
              {currentPlan === "pro" ? "Current plan" : "Subscribe to Pro"}
            </button>
          )}
        </article>

        <article className={"pricing-card " + (currentPlan === "pay_per_download" ? "current" : "")}>
          <p className="pricing-kicker">Flexible</p>
          <h3>Pay per download</h3>
          <p className="pricing-amount">
            {dlPrice}<span>/download</span>
          </p>
          <ul className="pricing-features">
            <li><Icon name="check" size={14} /> Card required at signup</li>
            <li><Icon name="check" size={14} /> Pay only when you export a PDF</li>
            <li><Icon name="check" size={14} /> Upgrade to Pro anytime</li>
          </ul>
          {onSelectPlan && (
            <button type="button" className="btn pricing-cta" onClick={() => onSelectPlan("pay_per_download")}>
              {currentPlan === "pay_per_download" ? "Current plan" : "Choose pay per download"}
            </button>
          )}
        </article>
      </div>
    );
  }

  /* ---------- Invoice validation modal ---------- */
  function InvoiceValidationModal({ open, onClose, issues, title }) {
    if (!open || !issues?.length) return null;
    return (
      <>
        <div className="modal-scrim" onClick={onClose}></div>
        <div className="modal billing-modal" role="alertdialog" aria-labelledby="invoice-validation-title">
          <div className="modal-head">
            <div>
              <div className="kicker">Check your form</div>
              <h3 id="invoice-validation-title">{title || "Some details need attention"}</h3>
              <p className="modal-sub">Fix the fields below, then try again.</p>
            </div>
            <button type="button" className="iconbtn" onClick={onClose} aria-label="Close">
              <Icon name="close" />
            </button>
          </div>
          <div className="modal-body">
            <ul className="validation-issue-list">
              {issues.map((issue) => (
                <li key={issue.field}>
                  <strong>{issue.label}</strong>
                  <span>{issue.message}</span>
                </li>
              ))}
            </ul>
          </div>
          <div className="modal-foot">
            <button type="button" className="btn primary" onClick={onClose}>
              Go back to form
            </button>
          </div>
        </div>
      </>
    );
  }

  /* ---------- Paywall modal (per-download charge) ---------- */
  function PaywallModal({ open, onClose, documentType, documentId, onProceed, busy }) {
    if (!open) return null;
    const label = documentType === "paystub" ? "pay statement" : "invoice";
    const price = MartenBilling.formatMoney(PRICING.payPerDownload);

    return (
      <>
        <div className="modal-scrim" onClick={onClose}></div>
        <div className="modal billing-modal">
          <div className="modal-head">
            <div>
              <div className="kicker">Download</div>
              <h3>Export this {label}?</h3>
              <p className="modal-sub">
                Pro members download free. On the pay-per-download plan, each PDF export is {price} (CAD).
              </p>
            </div>
            <button type="button" className="iconbtn" onClick={onClose} aria-label="Close">
              <Icon name="close" />
            </button>
          </div>
          <div className="modal-body">
            <div className="billing-paywall-price">
              <span className="billing-paywall-label">Due now</span>
              <strong>{price}</strong>
            </div>
            <p className="help" style={{ margin: 0 }}>
              You&apos;ll complete payment securely, then your download starts automatically.
            </p>
          </div>
          <div className="modal-foot">
            <button type="button" className="btn ghost" onClick={onClose} disabled={busy}>Cancel</button>
            <button type="button" className="btn primary" onClick={onProceed} disabled={busy}>
              {busy ? "Redirecting…" : <>Pay {price} &amp; download</>}
            </button>
          </div>
        </div>
      </>
    );
  }

  /* ---------- Upgrade modal ---------- */
  function UpgradeModal({ open, onClose, billingStatus, toast }) {
    const [busy, setBusy] = React.useState(null);

    if (!open) return null;

    const start = async (plan) => {
      setBusy(plan);
      try {
        const url = await MartenBilling.startCheckout(plan);
        window.location.href = url;
      } catch (e) {
        toast(e.message || "Could not start checkout.");
        setBusy(null);
      }
    };

    return (
      <>
        <div className="modal-scrim" onClick={onClose}></div>
        <div className="modal billing-modal billing-modal-wide">
          <div className="modal-head">
            <div>
              <div className="kicker">Plans</div>
              <h3>Upgrade your workspace</h3>
              <p className="modal-sub">Choose unlimited Pro downloads or keep paying per export.</p>
            </div>
            <button type="button" className="iconbtn" onClick={onClose}><Icon name="close" /></button>
          </div>
          <div className="modal-body">
            <PricingCards
              onSelectPlan={start}
              compact
              currentPlan={billingStatus?.proActive ? "pro" : billingStatus?.plan}
            />
          </div>
        </div>
      </>
    );
  }

  /* ---------- Post-signup: card required ---------- */
  function BillingOnboarding({ email, onComplete, toast, proOnly = true }) {
    const [busy, setBusy] = React.useState(null);

    const start = async (plan) => {
      setBusy(plan);
      try {
        const checkoutPlan = plan === "pro" ? "pro" : "card_setup";
        const url = await MartenBilling.startCheckout(checkoutPlan);
        window.location.href = url;
      } catch (e) {
        toast(e.message || "Could not start checkout.");
        setBusy(null);
      }
    };

    return (
      <div className="billing-onboarding">
        <div className="billing-onboarding-inner">
          <p className="landing-kicker">One more step</p>
          <h1>Subscribe to Pro</h1>
          <p className="billing-onboarding-lead">
            Add your card to unlock the full workspace with unlimited PDF downloads.
            {email ? <> Signed in as <b>{email}</b>.</> : null}
          </p>
          <PricingCards onSelectPlan={start} currentPlan={null} proOnly={proOnly} />
          <p className="auth-footnote">
            Payments are processed securely by Lemon Squeezy. You can change or cancel your plan in Settings.
          </p>
          {onComplete && (
            <button type="button" className="btn ghost" style={{ marginTop: 16 }} onClick={onComplete}>
              Skip for now (downloads disabled)
            </button>
          )}
        </div>
      </div>
    );
  }

  /* ---------- Settings: subscription management ---------- */
  function BillingSettings({ billingStatus, onRefresh, toast }) {
    const [busy, setBusy] = React.useState(false);
    const [upgradeOpen, setUpgradeOpen] = React.useState(false);

    if (billingStatus?.billingDisabled) {
      return (
        <div className="billing-settings-card">
          <p className="help" style={{ margin: 0 }}>
            Your workspace is included with your account. Sign in with email to use all features.
          </p>
        </div>
      );
    }

    const planLabel =
      billingStatus?.proActive ? "Pro Monthly (active)"
      : billingStatus?.plan === "pay_per_download" ? "Pay per download"
      : "No plan selected";

    const openPortal = async () => {
      setBusy(true);
      try {
        const url = await MartenBilling.getPortalUrl();
        window.open(url, "_blank", "noopener,noreferrer");
      } catch (e) {
        toast(e.message || "Could not open billing portal.");
      } finally {
        setBusy(false);
      }
    };

    return (
      <>
        <div className="billing-settings-card">
          <div className="billing-settings-row">
            <div>
              <div className="kicker">Current plan</div>
              <strong className="billing-plan-name">{planLabel}</strong>
              {billingStatus?.proActive && billingStatus?.renewsAt && (
                <p className="help">Renews {new Date(billingStatus.renewsAt).toLocaleDateString()}</p>
              )}
              {billingStatus?.subscriptionStatus && !billingStatus?.proActive && (
                <p className="help">Subscription status: {billingStatus.subscriptionStatus}</p>
              )}
            </div>
            <div className="billing-settings-actions">
              {!billingStatus?.proActive && (
                <button type="button" className="btn primary" onClick={() => setUpgradeOpen(true)}>
                  Upgrade to Pro
                </button>
              )}
              {billingStatus?.paymentMethodOnFile && (
                <button type="button" className="btn" onClick={openPortal} disabled={busy}>
                  Manage billing
                </button>
              )}
              <button type="button" className="btn ghost" onClick={onRefresh} disabled={busy}>
                Refresh status
              </button>
            </div>
          </div>
          {!billingStatus?.paymentMethodOnFile && (
            <div className="auth-message" style={{ marginTop: 14 }}>
              Add a payment method to enable PDF downloads.
            </div>
          )}
          {billingStatus?.plan === "pay_per_download" && !billingStatus?.proActive && (
            <p className="help" style={{ marginTop: 12, marginBottom: 0 }}>
              Each invoice or paystub download is {MartenBilling.formatMoney(PRICING.payPerDownload)} CAD.
            </p>
          )}
        </div>
        <UpgradeModal
          open={upgradeOpen}
          onClose={() => setUpgradeOpen(false)}
          billingStatus={billingStatus}
          toast={toast}
        />
      </>
    );
  }

  window.PricingCards = PricingCards;
  window.PaywallModal = PaywallModal;
  window.InvoiceValidationModal = InvoiceValidationModal;
  window.UpgradeModal = UpgradeModal;
  window.BillingOnboarding = BillingOnboarding;
  window.BillingSettings = BillingSettings;
})();
