// PortailClient — Portail client public partageable (PR 2.3 Vague 2)
//
// Route SANS login : #/portail/:share_token
// Le courtier cree une selection via /broker/shares puis envoie le lien
// public a son client. Le client peut consulter, liker, dire "pas
// interesse" ou poser une question sur chaque bien.
//
// Conventions : React global, hooks alias (suffixe PC = PortailClient),
// pas d'import/export ES.

(function () {
  'use strict';

  const {
    useState: usePC,
    useEffect: useEPC,
    useMemo: useMPC,
  } = React;

  // ── Helpers ────────────────────────────────────────────────────────────────
  function _fmtCAD(n) {
    if (n == null) return '—';
    try {
      return new Intl.NumberFormat('fr-CA', {
        style: 'currency', currency: 'CAD', maximumFractionDigits: 0,
      }).format(n);
    } catch (_) {
      return Math.round(n) + ' $';
    }
  }

  function _fmtDate(ts) {
    if (!ts) return '';
    try {
      return new Intl.DateTimeFormat('fr-CA', {
        day: '2-digit', month: 'long', year: 'numeric',
      }).format(new Date(ts));
    } catch (_) {
      return new Date(ts).toLocaleDateString();
    }
  }

  function _isHexColor(s) {
    return /^#[0-9A-Fa-f]{6}$/.test(s || '');
  }

  // ── Sous-composant : modal question ──────────────────────────────────────
  function QuestionModal({ open, listing, onClose, onSubmit, brandColor }) {
    const [text, setText] = usePC('');
    const [sending, setSending] = usePC(false);
    const [errMsg, setErrMsg] = usePC('');

    useEPC(() => {
      if (!open) { setText(''); setErrMsg(''); setSending(false); }
    }, [open]);

    if (!open) return null;

    async function handleSubmit(e) {
      e.preventDefault();
      const v = text.trim();
      if (!v) { setErrMsg('Veuillez ecrire votre question.'); return; }
      setSending(true);
      setErrMsg('');
      const r = await onSubmit(v);
      setSending(false);
      if (!r.ok) {
        setErrMsg(r.error && r.error.message ? r.error.message : 'Erreur lors de l\'envoi.');
      }
    }

    return (
      <div
        role="dialog"
        aria-modal="true"
        style={{
          position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.55)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          zIndex: 1000, padding: 16,
        }}
        onClick={onClose}
      >
        <form
          onClick={(e) => e.stopPropagation()}
          onSubmit={handleSubmit}
          style={{
            background: '#fff', borderRadius: 12, padding: 24,
            maxWidth: 480, width: '100%',
            boxShadow: '0 20px 60px rgba(0,0,0,0.25)',
          }}
        >
          <h3 style={{ margin: '0 0 6px', fontSize: 17, fontWeight: 700, color: '#0f172a' }}>
            Poser une question
          </h3>
          {listing && (
            <div style={{ fontSize: 13, color: '#64748b', marginBottom: 12 }}>
              {listing.address || listing.id}
            </div>
          )}
          <textarea
            value={text}
            onChange={(e) => setText(e.target.value)}
            placeholder="Ex. Quels sont les revenus actuels ? Le toit est-il recent ?"
            rows={5}
            style={{
              width: '100%', padding: 10, borderRadius: 8,
              border: '1px solid #cbd5e1', fontSize: 14, fontFamily: 'inherit',
              resize: 'vertical', boxSizing: 'border-box',
            }}
            maxLength={4000}
            autoFocus
          />
          {errMsg && (
            <div style={{ color: '#dc2626', fontSize: 13, marginTop: 8 }}>{errMsg}</div>
          )}
          <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 14 }}>
            <button
              type="button"
              onClick={onClose}
              style={{
                padding: '8px 16px', borderRadius: 8,
                background: 'transparent', border: '1px solid #cbd5e1',
                color: '#475569', cursor: 'pointer', fontSize: 14,
              }}
            >
              Annuler
            </button>
            <button
              type="submit"
              disabled={sending}
              style={{
                padding: '8px 16px', borderRadius: 8,
                background: brandColor || '#0F172A', color: '#fff',
                border: 'none', cursor: sending ? 'wait' : 'pointer', fontSize: 14, fontWeight: 600,
                opacity: sending ? 0.7 : 1,
              }}
            >
              {sending ? 'Envoi…' : 'Envoyer'}
            </button>
          </div>
        </form>
      </div>
    );
  }

  // ── Card listing avec actions ────────────────────────────────────────────
  function ListingPublicCard({ listing, brandColor, sent, onAction }) {
    const acted = sent[listing.id] || null;
    const photo = listing.photo_url;

    const actionBtn = (action, label, icon, color) => {
      const isActive = acted === action;
      return (
        <button
          type="button"
          onClick={() => onAction(listing, action)}
          aria-pressed={isActive}
          style={{
            flex: 1,
            padding: '8px 6px',
            borderRadius: 8,
            border: '1.5px solid ' + (isActive ? color : '#e2e8f0'),
            background: isActive ? color + '15' : '#fff',
            color: isActive ? color : '#475569',
            fontSize: 12,
            fontWeight: isActive ? 700 : 500,
            cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            gap: 4,
          }}
        >
          <span aria-hidden="true">{icon}</span>
          <span>{label}</span>
        </button>
      );
    };

    return (
      <article
        style={{
          background: '#fff',
          border: '1px solid #e2e8f0',
          borderRadius: 12,
          overflow: 'hidden',
          display: 'flex', flexDirection: 'column',
          boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
        }}
      >
        <div style={{
          height: 180,
          background: '#f1f5f9 center / cover no-repeat'
                    + (photo ? ` url(${JSON.stringify(photo)})` : ''),
          position: 'relative',
        }}>
          {!photo && (
            <div style={{
              position: 'absolute', inset: 0,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: '#94a3b8', fontSize: 32,
            }}>🏠</div>
          )}
        </div>
        <div style={{ padding: 14, display: 'flex', flexDirection: 'column', gap: 6, flex: 1 }}>
          <div style={{ fontSize: 18, fontWeight: 700, color: '#0f172a' }}>
            {_fmtCAD(listing.price)}
          </div>
          <div style={{ fontSize: 13, color: '#475569', lineHeight: 1.4 }}>
            {listing.address || '—'}
            {listing.city ? ', ' + listing.city : ''}
          </div>
          <div style={{ fontSize: 12, color: '#64748b' }}>
            {[
              listing.property_type,
              listing.total_units ? listing.total_units + ' unite' + (listing.total_units > 1 ? 's' : '') : null,
              listing.bedrooms ? listing.bedrooms + ' ch.' : null,
              listing.year_built ? 'Construit ' + listing.year_built : null,
            ].filter(Boolean).join(' • ')}
          </div>
          <div style={{ display: 'flex', gap: 6, marginTop: 'auto', paddingTop: 10 }}>
            {actionBtn('like', 'J\'aime', '👍', '#16a34a')}
            {actionBtn('dislike', 'Pas pour moi', '👎', '#dc2626')}
            {actionBtn('question', 'Question', '💬', brandColor || '#0F172A')}
          </div>
          {acted && (
            <div style={{ fontSize: 11, color: '#16a34a', textAlign: 'center', marginTop: 4 }}>
              Reaction envoyee, merci !
            </div>
          )}
        </div>
      </article>
    );
  }

  // ── Composant principal ──────────────────────────────────────────────────
  function PortailClient({ shareToken }) {
    const [loading, setLoading] = usePC(true);
    const [error, setError] = usePC(null); // { status, message }
    const [payload, setPayload] = usePC(null);
    const [sent, setSent] = usePC({}); // listing_id -> action
    const [questionFor, setQuestionFor] = usePC(null); // listing object

    // Fetch initial — robuste si brokerApi n'est pas chargee.
    useEPC(() => {
      let cancelled = false;
      async function load() {
        const api = window.vestora && window.vestora.brokerApi;
        if (!api || typeof api.getPublicShare !== 'function') {
          if (!cancelled) {
            setError({ status: 0, message: 'Module API indisponible.' });
            setLoading(false);
          }
          return;
        }
        const r = await api.getPublicShare(shareToken);
        if (cancelled) return;
        if (!r.ok) {
          const status = (r.error && r.error.status) || 0;
          const message = (r.error && r.error.message) || 'Lien invalide.';
          setError({ status, message });
          setLoading(false);
          return;
        }
        setPayload(r.data);
        setLoading(false);
      }
      load();
      return () => { cancelled = true; };
    }, [shareToken]);

    const broker = payload && payload.broker ? payload.broker : null;
    const brandColor = useMPC(() => {
      const c = broker && broker.brand_color;
      return _isHexColor(c) ? c : '#0F172A';
    }, [broker]);

    async function submitFeedback(listing, action, comment) {
      const api = window.vestora && window.vestora.brokerApi;
      if (!api || typeof api.postPublicFeedback !== 'function') {
        return { ok: false, error: { message: 'API indisponible.' } };
      }
      const r = await api.postPublicFeedback(shareToken, {
        listingId: listing.id,
        action,
        comment: comment || null,
      });
      if (r.ok) {
        setSent((prev) => Object.assign({}, prev, { [listing.id]: action }));
      }
      return r;
    }

    function handleAction(listing, action) {
      if (action === 'question') {
        setQuestionFor(listing);
        return;
      }
      submitFeedback(listing, action, null);
    }

    async function handleQuestionSubmit(comment) {
      if (!questionFor) return { ok: false, error: { message: 'aucun listing' } };
      const r = await submitFeedback(questionFor, 'question', comment);
      if (r.ok) setQuestionFor(null);
      return r;
    }

    // ── Chargement ─────────────────────────────────────────────────────────
    if (loading) {
      return (
        <div style={{
          minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: '#64748b', fontSize: 15,
        }}>
          Chargement du portail…
        </div>
      );
    }

    // ── Lien expire / introuvable ──────────────────────────────────────────
    if (error) {
      const expired = error.status === 410;
      return (
        <div style={{
          minHeight: '100vh', background: '#f8fafc',
          display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24,
        }}>
          <div style={{
            background: '#fff', borderRadius: 14, padding: 36,
            maxWidth: 520, width: '100%', textAlign: 'center',
            boxShadow: '0 4px 20px rgba(0,0,0,0.06)',
          }}>
            <div style={{ fontSize: 48, marginBottom: 12 }}>
              {expired ? '⏰' : '🔗'}
            </div>
            <h1 style={{ margin: '0 0 12px', fontSize: 20, color: '#0f172a' }}>
              {expired ? 'Ce lien a expire' : 'Lien introuvable'}
            </h1>
            <p style={{ color: '#475569', fontSize: 14, lineHeight: 1.6 }}>
              Ce lien de partage n'est plus actif. Contactez votre courtier
              pour obtenir une nouvelle selection.
            </p>
            <a
              href="https://vestora.ca"
              style={{
                display: 'inline-block', marginTop: 16,
                color: '#3b82f6', textDecoration: 'none', fontSize: 13,
              }}
            >
              Genere par Vestora — vestora.ca
            </a>
          </div>
        </div>
      );
    }

    // ── Portail brand court ──────────────────────────────────────────────
    const listings = (payload && payload.listings) || [];

    return (
      <div style={{ minHeight: '100vh', background: '#f8fafc' }}>
        {/* Header brande courtier */}
        <header style={{
          background: brandColor, color: '#fff',
          padding: '24px 20px',
          boxShadow: '0 2px 6px rgba(15,23,42,0.08)',
        }}>
          <div style={{
            maxWidth: 1100, margin: '0 auto',
            display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap',
          }}>
            {broker && broker.logo_url && (
              <img
                src={broker.logo_url}
                alt={broker.display_name || 'Logo courtier'}
                style={{
                  width: 64, height: 64, objectFit: 'contain',
                  background: '#fff', borderRadius: 8, padding: 6,
                }}
                onError={(e) => { e.currentTarget.style.display = 'none'; }}
              />
            )}
            <div style={{ flex: 1, minWidth: 200 }}>
              <div style={{ fontSize: 20, fontWeight: 700, lineHeight: 1.2 }}>
                {broker && broker.display_name ? broker.display_name : 'Votre courtier'}
              </div>
              {broker && broker.agency && (
                <div style={{ fontSize: 13, opacity: 0.9, marginTop: 2 }}>{broker.agency}</div>
              )}
              {broker && broker.oaciq_number && (
                <div style={{ fontSize: 11, opacity: 0.75, marginTop: 2 }}>
                  OACIQ : {broker.oaciq_number}
                </div>
              )}
              {broker && broker.tagline && (
                <div style={{ fontSize: 12, opacity: 0.85, marginTop: 4, fontStyle: 'italic' }}>
                  {broker.tagline}
                </div>
              )}
            </div>
            <div style={{ fontSize: 12, opacity: 0.9, textAlign: 'right' }}>
              {broker && broker.phone && <div>📞 {broker.phone}</div>}
              {broker && broker.email_public && <div>✉ {broker.email_public}</div>}
            </div>
          </div>
        </header>

        {/* Titre + meta selection */}
        <section style={{
          maxWidth: 1100, margin: '0 auto', padding: '24px 20px 12px',
        }}>
          <h1 style={{ margin: 0, fontSize: 22, color: '#0f172a', fontWeight: 700 }}>
            Selection pour vous : {payload.title}
          </h1>
          <div style={{ fontSize: 13, color: '#64748b', marginTop: 6 }}>
            {listings.length} bien{listings.length > 1 ? 's' : ''}
            {' · '}Valide jusqu'au {_fmtDate(payload.expires_at)}
          </div>
        </section>

        {/* Grid listings */}
        <main style={{
          maxWidth: 1100, margin: '0 auto', padding: '12px 20px 40px',
        }}>
          {listings.length === 0 ? (
            <div style={{
              textAlign: 'center', padding: 40,
              color: '#64748b', fontSize: 14,
              background: '#fff', borderRadius: 12,
            }}>
              Aucun bien disponible pour le moment. Contactez votre courtier.
            </div>
          ) : (
            <div style={{
              display: 'grid',
              gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
              gap: 16,
            }}>
              {listings.map((l) => (
                <ListingPublicCard
                  key={l.id}
                  listing={l}
                  brandColor={brandColor}
                  sent={sent}
                  onAction={handleAction}
                />
              ))}
            </div>
          )}
        </main>

        {/* Footer disclaimer */}
        <footer style={{
          background: '#fff', borderTop: '1px solid #e2e8f0',
          padding: '20px 20px 28px', color: '#64748b', fontSize: 12,
          textAlign: 'center',
        }}>
          <div style={{ maxWidth: 800, margin: '0 auto' }}>
            {broker && broker.disclaimer_extra && (
              <p style={{ margin: '0 0 10px' }}>{broker.disclaimer_extra}</p>
            )}
            <p style={{ margin: 0, lineHeight: 1.6 }}>
              Les informations presentees sont fournies a titre indicatif et ne
              constituent pas un avis professionnel. Vestora et le courtier ne
              garantissent ni l'exactitude ni l'actualite des donnees. Pour toute
              decision, validez aupres de votre courtier OACIQ.
              {' '}
              <a
                href="https://lautorite.qc.ca"
                target="_blank"
                rel="noopener noreferrer"
                style={{ color: '#475569' }}
              >
                Information AMF
              </a>.
            </p>
            <p style={{ margin: '12px 0 0' }}>
              <a
                href="https://vestora.ca"
                target="_blank"
                rel="noopener noreferrer"
                style={{ color: '#3b82f6', textDecoration: 'none' }}
              >
                Genere par Vestora — vestora.ca
              </a>
            </p>
          </div>
        </footer>

        <QuestionModal
          open={!!questionFor}
          listing={questionFor}
          onClose={() => setQuestionFor(null)}
          onSubmit={handleQuestionSubmit}
          brandColor={brandColor}
        />
      </div>
    );
  }

  // Expose en global (pattern Vestora — pas d'export)
  window.PortailClient = PortailClient;
})();
