import { useCallback, useEffect, useState } from 'react';
import { Navigate } from 'react-router-dom';
import { api, formatCredits } from '../api';
import { useAuth } from '../AuthContext';

function useAdCountdown(nextAdAt) {
  const [remaining, setRemaining] = useState(0);

  useEffect(() => {
    if (!nextAdAt) {
      setRemaining(0);
      return undefined;
    }
    const tick = () => {
      const ms = new Date(nextAdAt).getTime() - Date.now();
      setRemaining(Math.max(0, Math.ceil(ms / 1000)));
    };
    tick();
    const id = setInterval(tick, 250);
    return () => clearInterval(id);
  }, [nextAdAt]);

  return remaining;
}

function formatCountdown(sec) {
  const m = Math.floor(sec / 60);
  const s = sec % 60;
  return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
}

export default function ShopPage() {
  const { user, loading, patchUser } = useAuth();
  const [packages, setPackages] = useState([]);
  const [osuTopups, setOsuTopups] = useState([]);
  const [osuTopupsEnabled, setOsuTopupsEnabled] = useState(true);
  const [payments, setPayments] = useState(null);
  const [ad, setAd] = useState(null);
  const [error, setError] = useState('');
  const [message, setMessage] = useState('');
  const [busy, setBusy] = useState(false);
  const [watching, setWatching] = useState(false);
  const [confirmingId, setConfirmingId] = useState(null);

  const remaining = useAdCountdown(ad?.ready ? null : ad?.nextAdAt);

  const load = useCallback(async () => {
    const data = await api.shop();
    setPackages(data.packages || []);
    setOsuTopups(data.osuTopups || []);
    setOsuTopupsEnabled(data.osuTopupsEnabled !== false && (data.osuTopups || []).length > 0);
    setPayments(data.payments || null);
    setAd(data.ad);
    patchUser({
      balance: data.user.balance,
      osuBalance: data.user.osuBalance,
      lastAdAt: data.user.lastAdAt,
    });
  }, [patchUser]);

  useEffect(() => {
    if (!user || user.role === 'admin') return undefined;
    let cancelled = false;
    (async () => {
      try {
        await load();
      } catch (err) {
        if (!cancelled) setError(err.message);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [user?.id, user?.role, load]);

  // After Stripe Checkout redirect (?osu=success|cancel)
  useEffect(() => {
    if (!user || user.role === 'admin') return undefined;
    const params = new URLSearchParams(window.location.search);
    const osu = params.get('osu');
    if (!osu) return undefined;

    const orderId = params.get('order');
    const cleanUrl = () => {
      const url = new URL(window.location.href);
      url.searchParams.delete('osu');
      url.searchParams.delete('order');
      window.history.replaceState({}, '', url.pathname + url.search);
    };

    if (osu === 'cancel') {
      setMessage('Payment cancelled — no osu charged');
      cleanUrl();
      return undefined;
    }

    if (osu !== 'success') return undefined;

    let cancelled = false;
    setMessage('Payment received — confirming osu credit…');
    cleanUrl();

    (async () => {
      for (let i = 0; i < 12; i += 1) {
        if (cancelled) return;
        try {
          if (orderId) {
            const data = await api.shopOsuOrder(orderId);
            if (data.order?.status === 'paid') {
              await load();
              if (!cancelled) {
                setMessage(`+${data.order.osuAmount} osu added to your wallet`);
              }
              return;
            }
          } else {
            await load();
          }
        } catch {
          /* retry */
        }
        await new Promise((r) => setTimeout(r, 800));
      }
      if (!cancelled) {
        await load().catch(() => {});
        setMessage(
          'Payment submitted — if osu is missing, refresh in a few seconds (webhook pending)'
        );
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [user?.id, user?.role, load]);

  const buyCredits = async (packageId) => {
    setBusy(true);
    setError('');
    setMessage('');
    try {
      const data = await api.shopBuy(packageId);
      patchUser({
        balance: data.user.balance,
        osuBalance: data.user.osuBalance,
      });
      setMessage(`Exchanged — +${formatCredits(data.package.credits)} cr`);
      await load();
    } catch (err) {
      setError(err.message);
    } finally {
      setBusy(false);
    }
  };

  const buyOsu = async (packId) => {
    setBusy(true);
    setConfirmingId(packId);
    setError('');
    setMessage('');
    try {
      const checkout = await api.shopOsuCheckout(packId);
      if (checkout.mode === 'mock' && checkout.confirmable) {
        const data = await api.shopOsuConfirm(checkout.order.id);
        patchUser({
          balance: data.user.balance,
          osuBalance: data.user.osuBalance,
        });
        setMessage(
          data.alreadyPaid
            ? 'Order already completed'
            : `+${data.osuGranted} osu added to your wallet`
        );
        await load();
      } else if (checkout.mode === 'stripe' && checkout.url) {
        window.location.assign(checkout.url);
        return;
      } else {
        setError('Payment provider is not ready for live checkout yet');
      }
    } catch (err) {
      setError(err.message);
    } finally {
      setConfirmingId(null);
      setBusy(false);
    }
  };

  const watchAd = async () => {
    setBusy(true);
    setError('');
    setMessage('');
    setWatching(true);
    await new Promise((r) => setTimeout(r, 1800));
    try {
      const data = await api.shopAd();
      patchUser({
        balance: data.user.balance,
        osuBalance: data.user.osuBalance,
        lastAdAt: data.user.lastAdAt,
      });
      setAd(data.ad);
      setMessage(`Ad reward: +${formatCredits(data.reward)} cr`);
    } catch (err) {
      setError(err.message);
      if (err.message?.includes('available in') || err.nextAdAt) {
        try {
          await load();
        } catch {
          /* ignore */
        }
      }
    } finally {
      setWatching(false);
      setBusy(false);
    }
  };

  if (loading) return <p className="muted">Loading…</p>;
  if (!user) return <Navigate to="/login" replace />;
  if (user.role === 'admin') return <Navigate to="/admin" replace />;

  const adReady = ad?.ready || (ad?.nextAdAt && remaining === 0);
  const osuBal = user.osuBalance ?? 0;

  return (
    <div className="shop-page">
      <header className="shop-hero">
        <div className="shop-hero-copy">
          <p className="shop-kicker">CaseOrion Shop</p>
          <h1>Fuel your runs</h1>
          <p className="shop-lede">
            <strong>osu</strong> is the premium wallet — bought with real money, spent on credit
            packs. Credits are for opening cases, vaulting, and battling.
          </p>
        </div>
        <div className="shop-wallet">
          <div className="shop-wallet-row">
            <span className="muted">osu</span>
            <strong className="osu-pill shop-wallet-osu">{osuBal}</strong>
          </div>
          <div className="shop-wallet-row">
            <span className="muted">Credits</span>
            <strong className="balance-pill">{formatCredits(user.balance)} cr</strong>
          </div>
          {payments?.mock ? (
            <p className="shop-mock-note muted">
              Dev payments: mock checkout credits osu instantly.
            </p>
          ) : payments?.provider === 'stripe' ? (
            <p className="shop-mock-note muted">Secure checkout via Stripe.</p>
          ) : null}
        </div>
      </header>

      {error && <div className="error">{error}</div>}
      {message && <div className="ok-msg">{message}</div>}

      {osuTopupsEnabled && osuTopups.length > 0 && (
        <section className="shop-section">
          <div className="shop-section-head">
            <h2>Get osu</h2>
            <p className="muted">Premium top-ups · better rate on larger packs</p>
          </div>
          <div className="shop-osu-grid">
            {osuTopups.map((pack) => (
              <article
                key={pack.id}
                className={`shop-osu-card${pack.badge ? ' has-badge' : ''}${
                  pack.badge === 'Best value' ? ' highlight' : ''
                }${pack.badge === 'Popular' ? ' popular' : ''}`}
              >
                {pack.badge ? <span className="shop-badge">{pack.badge}</span> : null}
                <h3>{pack.name}</h3>
                <p className="shop-osu-amount">
                  {pack.osu} <span>osu</span>
                </p>
                <p className="muted shop-osu-blurb">{pack.blurb}</p>
                <p className="shop-osu-rate muted">{pack.perOsuLabel}</p>
                <button
                  type="button"
                  className="btn shop-buy-btn"
                  disabled={busy}
                  onClick={() => buyOsu(pack.id)}
                >
                  {confirmingId === pack.id
                    ? 'Processing…'
                    : `Buy · ${pack.displayPrice || `€${(pack.priceCents / 100).toFixed(2)}`}`}
                </button>
              </article>
            ))}
          </div>
        </section>
      )}

      <section className="shop-section">
        <div className="shop-section-head">
          <h2>Exchange for credits</h2>
          <p className="muted">
            Spend osu · payout scales with your credit balance (min floor early game)
          </p>
        </div>
        <div className="shop-credit-grid">
          {packages.map((p) => {
            const canAfford = osuBal >= p.osuCost;
            return (
              <article key={p.id} className="shop-credit-card">
                {p.tag ? <span className="shop-badge subtle">{p.tag}</span> : null}
                <h3>{p.name}</h3>
                <p className="pack-credits">+{formatCredits(p.credits)} cr</p>
                <p className="muted shop-credit-scale">
                  {p.balancePct != null ? `${p.balancePct}% of balance` : null}
                  {p.scaled === false ? ' · floor' : ''}
                </p>
                <p className="shop-credit-cost">
                  <span className="osu-pill">{p.osuCost} osu</span>
                </p>
                <button
                  type="button"
                  className="btn secondary"
                  disabled={busy || !canAfford}
                  onClick={() => buyCredits(p.id)}
                  title={canAfford ? undefined : 'Not enough osu'}
                >
                  {canAfford ? 'Exchange' : 'Need osu'}
                </button>
              </article>
            );
          })}
        </div>
      </section>

      <section className="shop-section shop-free">
        <div className="shop-ad-panel">
          <div>
            <h2>Free credits</h2>
            <p className="muted">
              Watch a short ad every minute for {formatCredits(ad?.rewardMin || 10000)}–
              {formatCredits(ad?.rewardMax || 20000)} cr.
            </p>
          </div>
          {watching ? (
            <div className="ad-sim">
              <div className="ad-bar" />
              <p className="muted">Playing ad…</p>
            </div>
          ) : (
            <button
              type="button"
              className="btn secondary"
              disabled={busy || !adReady}
              onClick={watchAd}
            >
              {adReady ? 'Watch ad' : `Ready in ${formatCountdown(remaining)}`}
            </button>
          )}
        </div>
      </section>
    </div>
  );
}
