// SoumissionVendeurModal — Soumission vendeur PDF brandée (PR-4.2 Vague 4)
//
// S'ouvre depuis :
//   - l'écran résultat de BrokerTab_Rapide
//   - le drawer listing, à côté de « Fiche brandée PDF »
//
// Le courtier saisit ce que Vestora ne peut pas connaître : sa rétribution, le
// solde hypothécaire du vendeur, la pénalité de remboursement anticipé. Le
// reste vient de l'annonce.
//
// L'aperçu net-vendeur est recalculé à la frappe avec la MÊME arithmétique que
// soumission_renderer.compute_net_vendeur — un écart entre l'écran et le PDF
// sur le chiffre que le vendeur retient serait le pire bug possible ici.
//
// Convention : IIFE, React global, expose window.SoumissionVendeurModal.

(function () {
  'use strict';

  const { useState, useEffect, useMemo } = React;

  // Taux légaux — identiques à soumission_renderer.py. Pas des hypothèses.
  const TPS_RATE = 0.05;
  const TVQ_RATE = 0.09975;
  const DEFAULT_NOTARY_FEES = 1500;

  function _fmtMoney(v, lang) {
    if (v == null || !Number.isFinite(Number(v))) return '—';
    return Number(v).toLocaleString(lang === 'en' ? 'en-CA' : 'fr-CA', {
      style: 'currency', currency: 'CAD', maximumFractionDigits: 0,
    });
  }

  // Port exact de compute_net_vendeur (soumission_renderer.py).
  // Les taxes portent sur la RÉTRIBUTION, jamais sur le prix de vente.
  function _computeNet(v) {
    const price = Math.max(0, Number(v.price) || 0);
    const pct = Math.max(0, Number(v.commissionPct) || 0);
    const mortgage = Math.max(0, Number(v.mortgageBalance) || 0);
    const penalty = Math.max(0, Number(v.penalty) || 0);
    const notaryRaw = (v.notaryFees === '' || v.notaryFees == null)
      ? DEFAULT_NOTARY_FEES : Number(v.notaryFees);
    const notary = Math.max(0, Number.isFinite(notaryRaw) ? notaryRaw : DEFAULT_NOTARY_FEES);

    const commission = price * pct;
    const tps = commission * TPS_RATE;
    const tvq = commission * TVQ_RATE;
    const deductions = commission + tps + tvq + mortgage + penalty + notary;
    const net = price - deductions;

    return {
      price, commission, tps, tvq, mortgage, penalty, notary,
      deductions, net,
      netPct: price > 0 ? net / price : 0,
      notaryIsDefault: (v.notaryFees === '' || v.notaryFees == null),
    };
  }

  function SoumissionVendeurModal({ open, onClose, listing, currentUser, lang }) {
    const FR = lang !== 'en';

    const T = {
      title:        FR ? 'Soumission vendeur' : 'Seller net sheet',
      subtitle:     FR ? "Ce qu'il restera au propriétaire, avec l'analyse du bien et sa concurrence active."
                       : 'What the owner walks away with, plus the property analysis and its active competition.',
      sectionInputs: FR ? 'Vos paramètres' : 'Your inputs',
      price:        FR ? 'Prix de vente envisagé ($)' : 'Target sale price ($)',
      priceHint:    FR ? "Laissez tel quel pour utiliser le prix affiché." : 'Leave as is to use the listed price.',
      commission:   FR ? 'Rétribution du courtier (%)' : 'Broker compensation (%)',
      mortgage:     FR ? 'Solde hypothécaire ($)' : 'Mortgage balance ($)',
      penalty:      FR ? 'Pénalité de remboursement anticipé ($)' : 'Prepayment penalty ($)',
      notary:       FR ? 'Honoraires de notaire ($)' : 'Notary fees ($)',
      notaryHint:   FR ? 'Vide = estimation de 1 500 $, signalée comme telle dans le PDF.'
                       : 'Empty = $1,500 estimate, flagged as such in the PDF.',
      preview:      FR ? 'Aperçu du net vendeur' : 'Seller net preview',
      rowPrice:     FR ? 'Prix de vente' : 'Sale price',
      rowCommission: FR ? 'Rétribution' : 'Compensation',
      rowTps:       FR ? 'TPS (5 %) sur la rétribution' : 'GST (5%) on compensation',
      rowTvq:       FR ? 'TVQ (9,975 %) sur la rétribution' : 'QST (9.975%) on compensation',
      rowMortgage:  FR ? 'Solde hypothécaire' : 'Mortgage balance',
      rowPenalty:   FR ? 'Pénalité' : 'Penalty',
      rowNotary:    FR ? 'Notaire' : 'Notary',
      rowNotaryEst: FR ? 'Notaire (estimation)' : 'Notary (estimate)',
      netLabel:     FR ? 'Produit net estimé' : 'Estimated net proceeds',
      ofPrice:      FR ? 'du prix de vente' : 'of the sale price',
      negative:     FR ? "Le net est négatif : les sommes à rembourser dépassent le prix envisagé. Une vente à ce prix exigerait un apport du vendeur."
                       : 'Net proceeds are negative: amounts owing exceed the target price. A sale at this price would require the seller to bring money.',
      generate:     FR ? 'Générer la soumission PDF' : 'Generate PDF net sheet',
      generating:   FR ? 'Génération en cours (5-10 s)…' : 'Generating (5-10s)…',
      cancel:       FR ? 'Annuler' : 'Cancel',
      openPdf:      FR ? 'Ouvrir le PDF' : 'Open PDF',
      copyLink:     FR ? 'Copier le lien (7 j)' : 'Copy link (7 days)',
      copied:       FR ? 'Lien copié ✓' : 'Link copied ✓',
      done:         FR ? 'Soumission générée.' : 'Net sheet generated.',
      noCma:        FR ? "Générée sans la section concurrence : aucun comparable actif trouvé pour ce bien."
                       : 'Generated without the competition section: no active comparable found.',
      errProfile:   FR ? "Configurez d'abord votre profil courtier (Profil > Mon profil)."
                       : 'Set up your broker profile first (Profile > My profile).',
      errUpgrade:   FR ? 'La soumission vendeur nécessite un abonnement Pro Courtier.'
                       : 'The seller net sheet requires a Pro Courtier subscription.',
      errAuth:      FR ? 'Session expirée — reconnectez-vous puis réessayez.'
                       : 'Session expired — sign in again and retry.',
      errGeneric:   FR ? 'Erreur lors de la génération du PDF.' : 'Error generating the PDF.',
      disclaimer:   FR ? "Estimation à titre indicatif : elle ne remplace pas le décompte du notaire, et exclut l'impôt sur le gain en capital et les ajustements de taxes."
                       : 'Indicative estimate only: it does not replace the notary statement, and excludes capital gains tax and tax adjustments.',
    };

    const listedPrice = Number(listing?.price) || 0;

    const defaults = useMemo(function () {
      return {
        price: listedPrice,
        commissionPct: 0.04,
        mortgageBalance: '',
        penalty: '',
        notaryFees: '',
      };
    }, [listedPrice]);

    const [values, setValues] = useState(defaults);
    const [status, setStatus] = useState('idle'); // idle | loading | done | error
    const [result, setResult] = useState(null);
    const [error, setError] = useState('');
    const [copied, setCopied] = useState(false);

    useEffect(function () {
      if (open) {
        setValues(defaults);
        setStatus('idle');
        setResult(null);
        setError('');
        setCopied(false);
      }
    }, [open, defaults]);

    if (!open) return null;

    const net = _computeNet(values);

    const setNum = function (key) {
      return function (e) {
        const raw = e.target.value;
        setValues(function (prev) {
          const next = Object.assign({}, prev);
          next[key] = raw === '' ? '' : Number(raw);
          return next;
        });
      };
    };
    const setPct = function (key) {
      return function (e) {
        const raw = e.target.value;
        setValues(function (prev) {
          const next = Object.assign({}, prev);
          next[key] = raw === '' ? '' : Number(raw) / 100;
          return next;
        });
      };
    };

    async function handleSubmit() {
      if (!currentUser) {
        if (window.vestora?.auth?.openModal) window.vestora.auth.openModal();
        onClose();
        return;
      }
      const api = window.vestora && window.vestora.brokerApi;
      if (!api || typeof api.generateSoumission !== 'function') {
        setStatus('error');
        setError(T.errGeneric);
        return;
      }

      setStatus('loading');
      setError('');
      let res;
      try {
        res = await api.generateSoumission(String(listing.id), {
          commissionPct: values.commissionPct,
          mortgageBalance: values.mortgageBalance,
          penalty: values.penalty,
          notaryFees: values.notaryFees,
          // N'envoyer un override que s'il diffère vraiment du prix affiché.
          priceOverride: (Number(values.price) !== listedPrice) ? values.price : null,
        });
      } catch (e) {
        res = { ok: false, error: { message: String((e && e.message) || e) } };
      }

      if (res && res.ok && res.data && res.data.pdfUrl) {
        setStatus('done');
        setResult(res.data);
        return;
      }
      const st = res && res.error && res.error.status;
      setStatus('error');
      if (st === 400) setError(T.errProfile);
      else if (st === 402 || st === 403) setError(T.errUpgrade);
      else if (st === 401) setError(T.errAuth);
      else setError((res && res.error && res.error.message) || T.errGeneric);
    }

    function handleCopy() {
      if (!result || !result.pdfUrl) return;
      try {
        navigator.clipboard.writeText(result.pdfUrl).then(function () {
          setCopied(true);
          setTimeout(function () { setCopied(false); }, 2000);
        }).catch(function () {});
      } catch (_) {}
    }

    // ---- Styles (mêmes jetons que FicheBrandeeModal) ----------------------
    const overlay = {
      position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.55)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      zIndex: 9999, padding: 16,
    };
    const card = {
      background: '#fff', borderRadius: 12, maxWidth: 680, width: '100%',
      maxHeight: '90vh', overflow: 'auto',
      boxShadow: '0 20px 60px rgba(15,23,42,0.30)',
      fontFamily: 'Inter, -apple-system, sans-serif',
    };
    const header = {
      padding: '18px 24px', borderBottom: '1px solid #e5e7eb',
      display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between',
    };
    const body = { padding: '18px 24px' };
    const grid2 = { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 6 };
    const label = { fontSize: 12, color: '#475569', marginBottom: 4, display: 'block', fontWeight: 500 };
    const input = {
      width: '100%', padding: '8px 10px', border: '1px solid #d1d5db',
      borderRadius: 6, fontSize: 14, fontFamily: 'inherit',
    };
    const hint = { fontSize: 11, color: '#94a3b8', marginTop: 3 };
    const sectionTitle = {
      fontSize: 12, fontWeight: 600, color: '#0F172A',
      textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: 10,
    };
    const rowStyle = {
      display: 'flex', justifyContent: 'space-between',
      padding: '5px 0', fontSize: 13, borderBottom: '1px solid #f1f5f9',
    };
    const btnPrimary = {
      background: 'oklch(0.30 0.07 155)', color: '#fff', border: 'none',
      padding: '10px 20px', borderRadius: 6, fontWeight: 600, fontSize: 14,
      cursor: status === 'loading' ? 'not-allowed' : 'pointer',
      opacity: status === 'loading' ? 0.6 : 1,
    };
    const btnSecondary = {
      background: '#fff', color: '#475569', border: '1px solid #d1d5db',
      padding: '10px 20px', borderRadius: 6, fontWeight: 500, fontSize: 14,
      cursor: 'pointer', marginRight: 8,
    };

    const row = function (lbl, value, negative) {
      return (
        <div style={rowStyle}>
          <span style={{ color: '#64748b' }}>{lbl}</span>
          <span style={{ fontWeight: 500, color: negative ? '#9a3412' : '#0f172a' }}>
            {negative ? '−' : ''}{_fmtMoney(Math.abs(value), lang)}
          </span>
        </div>
      );
    };

    return (
      <div style={overlay} onClick={function (e) { if (e.target === e.currentTarget) onClose(); }}>
        <div style={card} role="dialog" aria-modal="true" aria-label={T.title}>
          <div style={header}>
            <div>
              <div style={{ fontSize: 18, fontWeight: 600, color: '#0F172A' }}>{T.title}</div>
              <div style={{ fontSize: 12, color: '#64748b', marginTop: 2, maxWidth: 480 }}>
                {T.subtitle}
              </div>
            </div>
            <button onClick={onClose} aria-label={T.cancel}
              style={{ background: 'transparent', border: 'none', fontSize: 22, cursor: 'pointer', color: '#64748b' }}>×</button>
          </div>

          <div style={body}>
            <div style={{ fontSize: 13, color: '#0F172A', marginBottom: 14 }}>
              <strong>{listing?.address || listing?.address_full || ('#' + (listing?.id || ''))}</strong>
            </div>

            <div style={sectionTitle}>{T.sectionInputs}</div>
            <div style={grid2}>
              <div>
                <label style={label}>{T.price}</label>
                <input type="number" min="0" step="1000" style={input}
                  value={values.price === '' ? '' : values.price}
                  onChange={setNum('price')} />
                <div style={hint}>{T.priceHint}</div>
              </div>
              <div>
                <label style={label}>{T.commission}</label>
                <input type="number" min="0" max="20" step="0.25" style={input}
                  value={values.commissionPct === '' ? '' : (Number(values.commissionPct) * 100).toFixed(2).replace(/\.?0+$/, '')}
                  onChange={setPct('commissionPct')} />
              </div>
              <div>
                <label style={label}>{T.mortgage}</label>
                <input type="number" min="0" step="1000" style={input}
                  value={values.mortgageBalance} onChange={setNum('mortgageBalance')} />
              </div>
              <div>
                <label style={label}>{T.penalty}</label>
                <input type="number" min="0" step="100" style={input}
                  value={values.penalty} onChange={setNum('penalty')} />
              </div>
              <div>
                <label style={label}>{T.notary}</label>
                <input type="number" min="0" step="100" style={input}
                  placeholder={String(DEFAULT_NOTARY_FEES)}
                  value={values.notaryFees} onChange={setNum('notaryFees')} />
                <div style={hint}>{T.notaryHint}</div>
              </div>
            </div>

            <div style={{
              background: '#faf7f2', border: '1px solid #e5e0d6', borderRadius: 8,
              padding: 14, marginTop: 16, marginBottom: 14,
            }}>
              <div style={sectionTitle}>{T.preview}</div>
              {row(T.rowPrice, net.price, false)}
              {row(T.rowCommission, net.commission, true)}
              {row(T.rowTps, net.tps, true)}
              {row(T.rowTvq, net.tvq, true)}
              {net.mortgage > 0 && row(T.rowMortgage, net.mortgage, true)}
              {net.penalty > 0 && row(T.rowPenalty, net.penalty, true)}
              {row(net.notaryIsDefault ? T.rowNotaryEst : T.rowNotary, net.notary, true)}

              <div style={{
                display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
                marginTop: 10, paddingTop: 10, borderTop: '2px solid #e5e0d6',
              }}>
                <span style={{ fontSize: 13, color: '#475569' }}>{T.netLabel}</span>
                <span>
                  <strong style={{ fontSize: 22, color: net.net < 0 ? '#b91c1c' : 'oklch(0.30 0.07 155)' }}>
                    {_fmtMoney(net.net, lang)}
                  </strong>
                  <span style={{ fontSize: 11, color: '#94a3b8', marginLeft: 8 }}>
                    {(net.netPct * 100).toFixed(1).replace('.', FR ? ',' : '.')} % {T.ofPrice}
                  </span>
                </span>
              </div>

              {net.net < 0 && (
                <div style={{
                  marginTop: 10, padding: '8px 10px', background: '#fef2f2',
                  borderLeft: '3px solid #b91c1c', borderRadius: 3,
                  fontSize: 12, color: '#7f1d1d',
                }}>{T.negative}</div>
              )}
            </div>

            {status === 'error' && (
              <div style={{
                background: '#fef2f2', color: '#991b1b', border: '1px solid #fecaca',
                padding: '10px 12px', borderRadius: 6, fontSize: 13, marginBottom: 12,
              }}>{error}</div>
            )}

            {status === 'done' && result && (
              <div style={{
                background: '#ecfdf5', border: '1px solid #a7f3d0', borderRadius: 6,
                padding: '12px', marginBottom: 12,
              }}>
                <div style={{ fontSize: 13, color: '#065f46', fontWeight: 600, marginBottom: 8 }}>
                  {T.done}
                </div>
                {!result.cmaAvailable && (
                  <div style={{ fontSize: 12, color: '#92400e', marginBottom: 8 }}>{T.noCma}</div>
                )}
                <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                  <a href={result.pdfUrl} target="_blank" rel="noopener noreferrer"
                     style={{
                       background: '#059669', color: '#fff', padding: '8px 16px',
                       borderRadius: 6, fontSize: 13, fontWeight: 600, textDecoration: 'none',
                     }}>{T.openPdf}</a>
                  <button style={btnSecondary} onClick={handleCopy}>
                    {copied ? T.copied : T.copyLink}
                  </button>
                </div>
              </div>
            )}

            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 8 }}>
              <button style={btnSecondary} onClick={onClose} disabled={status === 'loading'}>
                {T.cancel}
              </button>
              {status !== 'done' && (
                <button style={btnPrimary} onClick={handleSubmit} disabled={status === 'loading'}>
                  {status === 'loading' ? T.generating : T.generate}
                </button>
              )}
            </div>

            <div style={{ fontSize: 11, color: '#94a3b8', marginTop: 12, lineHeight: 1.5 }}>
              {T.disclaimer}
            </div>
          </div>
        </div>
      </div>
    );
  }

  window.SoumissionVendeurModal = SoumissionVendeurModal;
})();
