// CartDrawer — unified Favourites + Quote-request drawer.
//
// Despite the legacy "Cart" filename, this drawer is the single place
// to see every tile the visitor has hearted, AND to give the studio
// the three pieces of info that turn a "list of tiles I like" into an
// actionable quote:
//   · which SIZE the customer wants (when the tile is sold in multiple)
//   · the AREA they need to cover, in m²
//   · the QTY they want, in pieces
//
// When the chosen size is parseable (e.g. "60×60"), area and qty are
// automatically derived from each other — type 12 m² of a 60×60 tile
// and qty auto-fills with 34 pieces (always rounded up so the
// customer doesn't end up short). The customer can override either
// field manually at any point; the dependent field stops auto-filling
// once the user touches it.
//
// All three fields persist via the existing visitor cart endpoint
// (PUT /api/account/cart, scoped by the `vid` cookie) so quantities
// survive drawer-close, page reload, and same-device return visits.
//
// The drawer's "Request a quote" CTA hands the whole selection
// (with sizes + areas + pieces per tile) to Quote.jsx via
// navigate('quote', { tiles: [...], sqm }).
const { useEffect, useState } = React;

// Parse a size string like "60 × 60", "60x60", "30×60 cm" into a
// {w, h} pair of centimetres. Returns null if it doesn't look like a
// rectangle size — we never guess. The × character used in the
// catalogue is the multiplication sign (U+00D7), but we accept x / X
// too so old data or admin typos still work.
function parseSizeCm(str) {
  if (!str) return null;
  const m = String(str).match(/(\d+(?:\.\d+)?)\s*[×xX*]\s*(\d+(?:\.\d+)?)/);
  if (!m) return null;
  const w = parseFloat(m[1]);
  const h = parseFloat(m[2]);
  if (!w || !h) return null;
  return { w, h };
}
// m² per single piece of that size (60×60 cm → 0.36 m²/piece).
function m2PerPiece(sizeStr) {
  const s = parseSizeCm(sizeStr);
  if (!s) return null;
  return (s.w / 100) * (s.h / 100);
}

function CartDrawer({ open, onClose, tileMap, navigate }) {
  const { favourites, cart, toggleFavourite, updateCartItem, MAX_FAVOURITES, isCartFull } = useAccount();

  useEffect(() => {
    if (open) document.body.style.overflow = 'hidden';
    else document.body.style.overflow = '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);

  if (!open) return null;

  const favTiles = (favourites || [])
    .map(id => tileMap[id])
    .filter(Boolean);

  // Look up the live cart entry for a tile. We resolve defaults
  // here so the row component never has to deal with undefined.
  function cartFor(tile) {
    const existing = (cart || []).find(c => c.tileId === tile.id) || {};
    // Default chosen size = the tile's first listed size (so the
    // customer doesn't always have to manually pick on tiles that
    // come in one size only).
    const sizes = tile.sizes || (tile.size ? [tile.size] : []);
    return {
      size: existing.size || sizes[0] || '',
      sqm:  existing.sqm  || 0,
      qty:  existing.qty  || 0,
    };
  }

  // Total estimated coverage across the whole selection.
  const totalSqm = favTiles.reduce((sum, t) => sum + (cartFor(t).sqm || 0), 0);
  const totalQty = favTiles.reduce((sum, t) => sum + (cartFor(t).qty || 0), 0);

  // Payload handed to Quote.jsx — now includes size + sqm + qty per
  // tile so the studio's email has everything they need to price the
  // job without a follow-up email.
  const quotePrefill = {
    tiles: favTiles.map(t => {
      const c = cartFor(t);
      return {
        name:   t.name,
        size:   c.size,
        finish: (t.finishes && t.finishes[0]) || t.finish || '',
        sqm:    c.sqm || undefined,
        qty:    c.qty || undefined,
      };
    }),
    sqm: totalSqm > 0 ? String(totalSqm) : '',
  };

  function goQuote() {
    onClose();
    navigate('quote', quotePrefill);
  }

  function thumbFor(t) {
    return (t.sightImages && t.sightImages[0])
        || (t.images && t.images[0])
        || t.img
        || '';
  }

  return (
    <>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.45)', zIndex: 199, backdropFilter: 'blur(4px)' }}/>
      <div style={{
        position: 'fixed', top: 0, right: 0, bottom: 0, width: 'min(520px, 100vw)',
        background: 'var(--cream)', zIndex: 200, display: 'flex', flexDirection: 'column',
        boxShadow: '-20px 0 80px rgba(0,0,0,0.18)',
      }}>
        <div style={{ padding: '22px 28px', borderBottom: '1px solid var(--cream-deep)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <p className="t-label" style={{ color: 'var(--terracotta)', marginBottom: '4px' }}>Your selection</p>
            <p style={{ fontFamily: 'var(--serif)', fontSize: '22px', fontWeight: 400 }}>
              {favTiles.length} {favTiles.length === 1 ? 'tile' : 'tiles'}
              {/* Count badge — shows once the visitor has accumulated
                  a serious selection, so they have visible warning
                  before they bump into the cap. Turns terracotta when
                  full to flag they can't add more. */}
              {favTiles.length >= MAX_FAVOURITES - 10 && (
                <span style={{
                  marginLeft: '10px',
                  fontFamily: 'var(--sans)', fontSize: '11px', fontWeight: 500,
                  letterSpacing: '0.1em', textTransform: 'uppercase',
                  color: isCartFull ? 'var(--terracotta)' : 'var(--dark-mid)',
                }}>
                  {favTiles.length} / {MAX_FAVOURITES}
                </span>
              )}
            </p>
          </div>
          <button onClick={onClose} aria-label="Close" style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '22px', color: 'var(--dark-mid)' }}>✕</button>
        </div>

        {/* Cap banner — only when the selection is full. Sticky at the
            top of the scroll area so it stays in view while the
            customer scrolls to remove tiles. */}
        {isCartFull && (
          <div style={{
            padding: '12px 28px',
            background: 'rgba(176, 85, 42, 0.08)',
            borderBottom: '1px solid var(--cream-deep)',
            fontFamily: 'var(--sans)', fontSize: '12.5px',
            lineHeight: 1.5, color: 'var(--terracotta)',
          }}>
            <strong>You've hit the limit ({MAX_FAVOURITES} tiles).</strong> Submit a quote or remove some tiles to add more.
          </div>
        )}

        <div style={{ flex: 1, overflowY: 'auto', padding: '14px 22px' }}>
          {favTiles.length === 0 && (
            <div style={{ textAlign: 'center', padding: '48px 20px', color: 'var(--dark-mid)' }}>
              <svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" style={{ marginBottom: '10px' }}>
                <path d="M12 21s-7-4.35-7-10a4 4 0 0 1 7-2.65A4 4 0 0 1 19 11c0 5.65-7 10-7 10z"/>
              </svg>
              <p style={{ fontFamily: 'var(--serif)', fontSize: '22px', fontWeight: 300, marginBottom: '10px' }}>No favourites yet</p>
              <p style={{ fontFamily: 'var(--sans)', fontSize: '13px', color: 'var(--dark-mid)', marginBottom: '24px' }}>Tap the heart on any tile to save it here, then send your whole selection to the studio for a quote.</p>
              <button onClick={() => { onClose(); navigate('collections'); }} className="btn btn-dark" style={{ justifyContent: 'center' }}>Browse tiles</button>
            </div>
          )}

          {favTiles.map(tile => (
            <CartRow
              key={tile.id}
              tile={tile}
              current={cartFor(tile)}
              thumb={thumbFor(tile)}
              onChange={(patch) => updateCartItem(tile.id, patch)}
              onRemove={() => {
                toggleFavourite(tile.id);
                // Clear cart row alongside the heart so we don't keep
                // a dangling size/qty/area for a tile the user has
                // unfavourited.
                updateCartItem(tile.id, { size: '', sqm: 0, qty: 0 });
              }}
              onOpen={() => { onClose(); navigate('product', tile); }}
            />
          ))}
        </div>

        {favTiles.length > 0 && (
          <div style={{ padding: '18px 28px', borderTop: '1px solid var(--cream-deep)', background: 'white' }}>
            <button
              onClick={goQuote}
              className="btn btn-dark"
              style={{ width: '100%', justifyContent: 'center', padding: '15px', display: 'flex', alignItems: 'center', gap: '10px' }}
            >
              <span>Request a quote for {favTiles.length} {favTiles.length === 1 ? 'tile' : 'tiles'}</span>
              <span aria-hidden>→</span>
            </button>
            <p style={{ fontFamily: 'var(--sans)', fontSize: '11px', color: 'var(--dark-mid)', textAlign: 'center', marginTop: '10px', letterSpacing: '0.06em' }}>
              {(totalSqm > 0 || totalQty > 0)
                ? `${totalSqm > 0 ? totalSqm.toFixed(2) + ' m²' : ''}${totalSqm > 0 && totalQty > 0 ? ' · ' : ''}${totalQty > 0 ? totalQty + ' pcs' : ''} · Quoted per project · London dispatch`
                : 'Quoted per project · London dispatch · No obligation'}
            </p>
          </div>
        )}
      </div>
    </>
  );
}

// ─── A single tile row ────────────────────────────────────────────
// Size dropdown (or static text if only one size) + Area input +
// Qty input. Area and qty auto-derive from each other when the
// chosen size is parseable. The user can override either field;
// once they touch it the auto-fill stops blowing their value away.
function CartRow({ tile, current, thumb, onChange, onRemove, onOpen }) {
  const sizes  = tile.sizes || (tile.size ? [tile.size] : []);
  const finish = (tile.finishes && tile.finishes[0]) || tile.finish || '';

  // Local state mirrors the current cart row so typing feels
  // instantaneous (no waiting on the server round-trip per keystroke).
  // Parent commits on change.
  const [size, setSize] = useState(current.size);
  const [sqmStr, setSqmStr] = useState(current.sqm ? String(current.sqm) : '');
  const [qtyStr, setQtyStr] = useState(current.qty ? String(current.qty) : '');
  // Track which field the user last touched. The OTHER field
  // auto-derives. Starts 'none' so neither field overrides the other
  // until the user actually types.
  const [lastEdited, setLastEdited] = useState('none');

  // Re-sync from props when the cart updates from elsewhere (e.g.
  // user opened a product page and added it, then re-opened drawer).
  useEffect(() => { setSize(current.size); }, [current.size]);
  useEffect(() => {
    if (lastEdited !== 'sqm') setSqmStr(current.sqm ? String(current.sqm) : '');
  }, [current.sqm]);
  useEffect(() => {
    if (lastEdited !== 'qty') setQtyStr(current.qty ? String(current.qty) : '');
  }, [current.qty]);

  const ppm = m2PerPiece(size); // m² per piece; null if size unparseable

  // Auto-fill the partner field when one is edited.
  function onAreaChange(v) {
    setSqmStr(v);
    setLastEdited('sqm');
    const sqmNum = Number(v);
    const next = { sqm: sqmNum || 0 };
    if (ppm && sqmNum > 0) {
      const pcs = Math.ceil(sqmNum / ppm);
      next.qty = pcs;
      setQtyStr(String(pcs));
    } else if (!v) {
      next.qty = 0;
      setQtyStr('');
    }
    onChange(next);
  }
  function onQtyChange(v) {
    setQtyStr(v);
    setLastEdited('qty');
    const qtyNum = Math.floor(Number(v) || 0);
    const next = { qty: qtyNum };
    if (ppm && qtyNum > 0) {
      // Round area to 2 dp — we don't need more precision than that.
      const a = Math.round(qtyNum * ppm * 100) / 100;
      next.sqm = a;
      setSqmStr(String(a));
    } else if (!v) {
      next.sqm = 0;
      setSqmStr('');
    }
    onChange(next);
  }
  function onSizeChange(v) {
    setSize(v);
    setLastEdited('none');
    // When the size changes, recompute the partner field from
    // whichever of area/qty was last manually set, so the customer
    // doesn't have to re-type. If both are empty, just write the size.
    const patch = { size: v };
    const newPpm = m2PerPiece(v);
    const sqmNum = Number(sqmStr);
    const qtyNum = Math.floor(Number(qtyStr) || 0);
    if (newPpm) {
      if (sqmNum > 0) {
        const pcs = Math.ceil(sqmNum / newPpm);
        patch.qty = pcs;
        setQtyStr(String(pcs));
      } else if (qtyNum > 0) {
        const a = Math.round(qtyNum * newPpm * 100) / 100;
        patch.sqm = a;
        setSqmStr(String(a));
      }
    }
    onChange(patch);
  }

  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '76px 1fr', gap: '14px',
      padding: '14px 6px',
      borderBottom: '1px solid var(--cream-deep)',
    }}>
      <button
        type="button"
        onClick={onOpen}
        className="tile-frame"
        style={{ aspectRatio: '1', overflow: 'hidden', border: 'none', padding: 0, cursor: 'pointer', alignSelf: 'flex-start' }}
      >
        <img src={thumb} alt={tile.name} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}/>
      </button>

      <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
        {/* Header: name + remove */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: '10px' }}>
          <button
            type="button"
            onClick={onOpen}
            style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', textAlign: 'left', flex: 1 }}
          >
            <p style={{ fontFamily: 'var(--serif)', fontSize: '15px', fontWeight: 400, color: 'var(--dark)', lineHeight: 1.2 }}>{tile.name}</p>
            {tile.collection && (
              <p style={{ fontFamily: 'var(--sans)', fontSize: '9.5px', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--terracotta)', marginTop: '3px' }}>{tile.collection}</p>
            )}
            {finish && (
              <p style={{ fontFamily: 'var(--sans)', fontSize: '11px', color: 'var(--dark-mid)', marginTop: '2px' }}>{finish}</p>
            )}
          </button>
          <button
            onClick={onRemove}
            aria-label="Remove"
            style={{ background: 'none', border: 'none', cursor: 'pointer', fontFamily: 'var(--sans)', fontSize: '10.5px', color: 'var(--dark-mid)', textTransform: 'uppercase', letterSpacing: '0.08em', padding: '4px' }}
          >Remove</button>
        </div>

        {/* Three-field row: size · area · qty */}
        <div style={{
          display: 'grid',
          // Size column flexes to fit its content; area + qty fixed.
          gridTemplateColumns: 'minmax(0, 1fr) 96px 96px',
          gap: '8px',
          alignItems: 'end',
        }}>
          <FieldGroup label="Size">
            {sizes.length > 1 ? (
              <select value={size} onChange={(e) => onSizeChange(e.target.value)} style={selStyle}>
                {sizes.map(s => <option key={s} value={s}>{s}</option>)}
              </select>
            ) : (
              <input
                type="text"
                value={size}
                onChange={(e) => onSizeChange(e.target.value)}
                placeholder={sizes[0] || 'e.g. 60×60'}
                style={inpStyle}
              />
            )}
          </FieldGroup>
          <FieldGroup label="Area (m²)">
            <input
              type="number" min="0" step="0.1" inputMode="decimal"
              placeholder="—"
              value={sqmStr}
              onChange={(e) => onAreaChange(e.target.value)}
              style={{ ...inpStyle, textAlign: 'right' }}
            />
          </FieldGroup>
          <FieldGroup label="Qty (pcs)">
            <input
              type="number" min="0" step="1" inputMode="numeric"
              placeholder="—"
              value={qtyStr}
              onChange={(e) => onQtyChange(e.target.value)}
              style={{ ...inpStyle, textAlign: 'right' }}
            />
          </FieldGroup>
        </div>

        {/* Hint: when size parses, tell the customer area/qty auto-derive */}
        {ppm && (
          <p style={{
            fontFamily: 'var(--sans)', fontSize: '10px',
            color: 'var(--dark-mid)', letterSpacing: '0.06em',
            margin: 0,
          }}>
            {`Each ${size} piece covers ${ppm.toFixed(2)} m² — area and pieces auto-fill from each other.`}
          </p>
        )}
      </div>
    </div>
  );
}

// ─── Field wrapper — uniform label + control ──────────────────────
function FieldGroup({ label, children }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: '3px' }}>
      <span style={{
        fontFamily: 'var(--sans)', fontSize: '9.5px',
        letterSpacing: '0.12em', textTransform: 'uppercase',
        color: 'var(--dark-mid)',
      }}>{label}</span>
      {children}
    </label>
  );
}

const inpStyle = {
  width: '100%',
  padding: '6px 8px',
  border: '1px solid var(--cream-deep)',
  background: 'white',
  fontFamily: 'var(--sans)', fontSize: '12px',
  color: 'var(--dark)',
  outline: 'none',
  borderRadius: 0,
};
const selStyle = { ...inpStyle, padding: '5px 8px' };

Object.assign(window, { CartDrawer });
