/* ============================================================
   BAN YARO — Playdate-Matching
   Spielkameraden in der Nähe finden, Inserate verwalten, Anfragen
   ============================================================ */

window.Page_playdate = (() => {

  let _container = null;
  let _appState  = null;
  let _activeTab = 'nearby';   // 'nearby' | 'listings' | 'requests'
  let _userPos   = null;
  let _radius    = 10;
  let _dogs      = [];

  // ------------------------------------------------------------------
  // Helpers
  // ------------------------------------------------------------------
  function _esc(s) {
    return String(s || '').replace(/&/g, '&amp;').replace(/</g, '&lt;')
                          .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  }

  function _fmtDate(iso) {
    if (!iso) return '';
    const d = new Date(iso.replace(' ', 'T'));
    return d.toLocaleDateString('de-DE');
  }

  function _dogAvatar(foto_url, name, size = 48) {
    const initials = _esc((name || '?').charAt(0).toUpperCase());
    if (foto_url) {
      return `<img src="${_esc(foto_url)}" alt="${initials}"
                   style="width:${size}px;height:${size}px;border-radius:50%;object-fit:cover;display:block;"
                   onerror="this.outerHTML='<div style=\'width:${size}px;height:${size}px;border-radius:50%;background:var(--c-primary-subtle);display:flex;align-items:center;justify-content:center;font-size:${Math.round(size*0.45)}px;font-weight:700;color:var(--c-primary);\'>${initials}</div>'">`;
    }
    return `<div style="width:${size}px;height:${size}px;border-radius:50%;
                background:var(--c-primary-subtle);display:flex;align-items:center;
                justify-content:center;font-size:${Math.round(size * 0.45)}px;
                font-weight:700;color:var(--c-primary);">${initials}</div>`;
  }

  function _statusBadge(status) {
    const map = {
      pending:  ['warning', 'Ausstehend'],
      accepted: ['success', 'Angenommen'],
      declined: ['danger',  'Abgelehnt'],
    };
    const [type, label] = map[status] || ['default', status];
    const colors = {
      warning: 'var(--c-warning, #f59e0b)',
      success: 'var(--c-success, #10b981)',
      danger:  'var(--c-danger,  #ef4444)',
      default: 'var(--c-text-muted)',
    };
    return `<span style="font-size:var(--text-xs);font-weight:600;
                color:${colors[type]};padding:2px 8px;border-radius:999px;
                background:${colors[type]}18">${label}</span>`;
  }

  // ------------------------------------------------------------------
  // INIT
  // ------------------------------------------------------------------
  async function init(container, appState) {
    _container = container;
    _appState  = appState;
    _dogs = appState.dogs?.filter(d => !d.is_guest) || [];
    _render();
    _switchTab(_activeTab);
  }

  function refresh() {
    _dogs = _appState?.dogs?.filter(d => !d.is_guest) || [];
    _switchTab(_activeTab);
  }

  function onDogChange() {
    _dogs = _appState?.dogs?.filter(d => !d.is_guest) || [];
    if (_activeTab === 'listings') _loadListings();
  }

  // ------------------------------------------------------------------
  // RENDER — Grundstruktur mit Tabs
  // ------------------------------------------------------------------
  function _render() {
    _container.innerHTML = `
      <div class="playdate-layout">

        <!-- Tabs -->
        <div class="by-tabs" id="playdate-tabs" style="margin-bottom:var(--space-4)">
          <button class="by-tab active" data-tab="nearby">In der Nähe</button>
          <button class="by-tab" data-tab="listings">Meine Inserate</button>
          <button class="by-tab" data-tab="requests">
            Anfragen
            <span id="playdate-req-badge" style="display:none;margin-left:4px;
              background:var(--c-primary);color:#fff;border-radius:999px;
              padding:1px 6px;font-size:var(--text-xs);font-weight:700">0</span>
          </button>
        </div>

        <!-- Tab-Inhalt -->
        <div id="playdate-content"></div>

      </div>
    `;

    document.getElementById('playdate-tabs').addEventListener('click', e => {
      const btn = e.target.closest('.by-tab');
      if (!btn) return;
      _switchTab(btn.dataset.tab);
    });
  }

  function _switchTab(tab) {
    _activeTab = tab;
    document.querySelectorAll('#playdate-tabs .by-tab').forEach(b => {
      b.classList.toggle('active', b.dataset.tab === tab);
    });
    const content = document.getElementById('playdate-content');
    if (!content) return;

    if (tab === 'nearby')   _renderNearby(content);
    if (tab === 'listings') _renderListings(content);
    if (tab === 'requests') _renderRequests(content);
  }

  // ------------------------------------------------------------------
  // TAB: IN DER NÄHE
  // ------------------------------------------------------------------
  async function _renderNearby(el) {
    el.innerHTML = `
      <div>
        <!-- Toolbar: Radius-Auswahl + Standort-Button -->
        <div style="display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-4);flex-wrap:wrap">
          <div style="display:flex;align-items:center;gap:var(--space-2)">
            ${UI.icon('map-pin')}
            <span style="font-size:var(--text-sm);color:var(--c-text-secondary)" id="nearby-location-label">
              ${_userPos ? 'Standort bekannt' : 'Kein Standort'}
            </span>
          </div>
          <select id="nearby-radius" class="form-select" style="width:auto;font-size:var(--text-sm)">
            <option value="5"  ${_radius===5  ? 'selected' : ''}>5 km</option>
            <option value="10" ${_radius===10 ? 'selected' : ''}>10 km</option>
            <option value="25" ${_radius===25 ? 'selected' : ''}>25 km</option>
            <option value="50" ${_radius===50 ? 'selected' : ''}>50 km</option>
          </select>
          <button class="btn btn-ghost btn-sm" id="nearby-locate-btn">
            ${UI.icon('crosshair')} Standort aktualisieren
          </button>
        </div>

        <!-- Info-Hinweis -->
        <div style="font-size:var(--text-xs);color:var(--c-text-muted);
                    margin-bottom:var(--space-4);padding:var(--space-2) var(--space-3);
                    background:var(--c-surface-2);border-radius:var(--radius-md)">
          ${UI.icon('info')} Nur Hunde von Nutzern die sich ebenfalls mit einem Inserat eingetragen haben.
          Dein genauer Standort bleibt privat — es wird nur der Ortsname und die ungefähre Entfernung angezeigt.
        </div>

        <!-- Ergebnisse -->
        <div id="nearby-results">
          <p style="text-align:center;color:var(--c-text-secondary);padding:var(--space-6)">
            Standort wird ermittelt…
          </p>
        </div>
      </div>
    `;

    document.getElementById('nearby-radius').addEventListener('change', e => {
      _radius = parseInt(e.target.value, 10);
      _loadNearby();
    });

    document.getElementById('nearby-locate-btn').addEventListener('click', async () => {
      const btn = document.getElementById('nearby-locate-btn');
      UI.setLoading(btn, true);
      try {
        _userPos = await API.getLocation();
        const label = document.getElementById('nearby-location-label');
        if (label) label.textContent = 'Standort aktualisiert';
        await _loadNearby();
      } catch {
        UI.toast.error('Standort konnte nicht ermittelt werden.');
      } finally {
        UI.setLoading(btn, false);
      }
    });

    if (!_userPos) {
      try {
        _userPos = await API.getLocation();
        const label = document.getElementById('nearby-location-label');
        if (label) label.textContent = 'Standort bekannt';
      } catch {
        document.getElementById('nearby-results').innerHTML = `
          <div style="text-align:center;padding:var(--space-8);color:var(--c-text-secondary)">
            ${UI.icon('map-pin')}
            <p style="margin:var(--space-3) 0 var(--space-4)">
              Standort konnte nicht automatisch ermittelt werden.<br>
              Klicke auf "Standort aktualisieren".
            </p>
          </div>
        `;
        return;
      }
    }
    await _loadNearby();
  }

  async function _loadNearby() {
    if (!_userPos) return;
    const resultsEl = document.getElementById('nearby-results');
    if (!resultsEl) return;
    resultsEl.innerHTML = `<p style="text-align:center;color:var(--c-text-secondary);padding:var(--space-6)">${UI.icon('spinner')} Suche…</p>`;

    try {
      const data = await API.get(`/playdate/nearby?lat=${_userPos.lat}&lon=${_userPos.lon}&radius=${_radius}`);

      if (!data || data.length === 0) {
        resultsEl.innerHTML = UI.emptyState({
          icon: UI.icon('paw-print'),
          title: 'Niemand in der Nähe',
          text: `Aktuell hat sich noch niemand in ${_radius} km Umkreis eingetragen. Trage deinen Hund unter "Meine Inserate" ein!`,
        });
        return;
      }

      resultsEl.innerHTML = `
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:var(--space-3)">
          ${data.map(d => _nearbyCard(d)).join('')}
        </div>
      `;

      resultsEl.querySelectorAll('.playdate-anfrage-btn').forEach(btn => {
        btn.addEventListener('click', () => {
          const toDogId = parseInt(btn.dataset.dogId, 10);
          const dogName = btn.dataset.dogName;
          _showRequestModal(toDogId, dogName);
        });
      });

    } catch (err) {
      resultsEl.innerHTML = `<p style="text-align:center;color:var(--c-danger);padding:var(--space-6)">${err.message}</p>`;
    }
  }

  function _nearbyCard(d) {
    return `
      <div class="card" style="padding:var(--space-4)">
        <div style="display:flex;gap:var(--space-3);align-items:flex-start;margin-bottom:var(--space-3)">
          ${_dogAvatar(d.foto_url, d.dog_name, 56)}
          <div style="flex:1;min-width:0">
            <div style="font-weight:var(--weight-semibold);font-size:var(--text-base);
                         color:var(--c-text)">${_esc(d.dog_name)}</div>
            ${d.rasse ? `<div style="font-size:var(--text-sm);color:var(--c-text-secondary)">${_esc(d.rasse)}</div>` : ''}
            ${d.alter ? `<div style="font-size:var(--text-xs);color:var(--c-text-muted)">${_esc(d.alter)}</div>` : ''}
          </div>
        </div>

        <div style="display:flex;gap:var(--space-3);margin-bottom:var(--space-3);flex-wrap:wrap">
          <span style="display:flex;align-items:center;gap:4px;font-size:var(--text-xs);color:var(--c-text-secondary)">
            ${UI.icon('map-pin')}
            ${d.ort_name ? _esc(d.ort_name) + ' · ' : ''}${d.entfernung_km} km entfernt
          </span>
          ${d.geschlecht ? `<span style="font-size:var(--text-xs);color:var(--c-text-muted)">${_esc(d.geschlecht)}</span>` : ''}
        </div>

        ${d.beschreibung ? `
          <p style="font-size:var(--text-sm);color:var(--c-text-secondary);
                    margin:0 0 var(--space-3);line-height:1.5">
            ${_esc(d.beschreibung)}
          </p>` : ''}

        <button class="btn btn-primary btn-sm playdate-anfrage-btn"
                data-dog-id="${d.dog_id}"
                data-dog-name="${_esc(d.dog_name)}">
          ${UI.icon('paw-print')} Spielkamerad anfragen
        </button>
      </div>
    `;
  }

  function _showRequestModal(toDogId, dogName) {
    const formId = 'playdate-req-form';
    UI.modal.open({
      title: `Anfrage an ${dogName}`,
      body: `
        <form id="${formId}">
          <div class="form-group">
            <label class="form-label">Nachricht (optional)</label>
            <textarea id="req-nachricht" class="form-control" rows="3" maxlength="500"
              placeholder="Hallo! Unsere Hunde könnten super zusammenpassen…"></textarea>
          </div>
        </form>
      `,
      footer: `
        <button class="btn btn-secondary" id="req-cancel-btn">Abbrechen</button>
        <button class="btn btn-primary" id="req-send-btn" form="${formId}">
          ${UI.icon('paper-plane-tilt')} Anfrage senden
        </button>
      `,
    });

    document.getElementById('req-cancel-btn').addEventListener('click', () => UI.modal.close());
    document.getElementById('req-send-btn').addEventListener('click', async () => {
      const btn = document.getElementById('req-send-btn');
      const nachricht = document.getElementById('req-nachricht').value.trim();
      await UI.asyncButton(btn, async () => {
        const result = await API.post('/playdate/request', {
          to_dog_id: toDogId,
          nachricht: nachricht || null,
        });
        UI.modal.close();
        UI.toast.success('Anfrage gesendet! Ein Chat wurde geöffnet.');
        // Zum Chat navigieren
        if (result.conversation_id) {
          setTimeout(() => {
            App.navigate('chat', true, { conversation_id: result.conversation_id });
          }, 800);
        }
      }, { errorMsg: null });
    });
  }

  // ------------------------------------------------------------------
  // TAB: MEINE INSERATE
  // ------------------------------------------------------------------
  async function _renderListings(el) {
    el.innerHTML = `<p style="text-align:center;color:var(--c-text-secondary);padding:var(--space-6)">${UI.icon('spinner')} Lädt…</p>`;
    await _loadListings(el);
  }

  async function _loadListings(el) {
    const target = el || document.getElementById('playdate-content');
    if (!target) return;

    if (_dogs.length === 0) {
      target.innerHTML = UI.emptyState({
        icon: UI.icon('paw-print'),
        title: 'Noch kein Hund',
        text: 'Lege zuerst einen Hund in deinem Profil an.',
        action: `<button class="btn btn-primary" onclick="App.navigate('dog-profile')">Hund anlegen</button>`,
      });
      return;
    }

    // Listings für alle eigenen Hunde laden
    const listings = {};
    await Promise.all(_dogs.map(async dog => {
      try {
        const data = await API.get(`/playdate/my-listing/${dog.id}`);
        listings[dog.id] = data;
      } catch {
        listings[dog.id] = null;
      }
    }));

    target.innerHTML = `
      <div style="display:flex;flex-direction:column;gap:var(--space-4)">
        ${_dogs.map(dog => _listingCard(dog, listings[dog.id])).join('')}
      </div>
    `;

    // Event-Delegation für alle Buttons
    target.addEventListener('click', async e => {
      const btn = e.target.closest('button[data-action]');
      if (!btn) return;
      const action = btn.dataset.action;
      const dogId  = parseInt(btn.dataset.dogId, 10);
      const dog    = _dogs.find(d => d.id === dogId);

      if (action === 'edit') {
        _showListingModal(dog, listings[dogId], async () => {
          await _loadListings();
        });
      }
      if (action === 'deactivate') {
        if (!window.confirm(`Inserat für ${dog?.name} deaktivieren?`)) return;
        try {
          await API.del(`/playdate/listing/${dogId}`);
          UI.toast.success('Inserat deaktiviert.');
          await _loadListings();
        } catch (err) {
          UI.toast.error(err.message);
        }
      }
    });
  }

  function _listingCard(dog, listing) {
    const isAktiv = listing && listing.aktiv;
    return `
      <div class="card" style="padding:var(--space-4)">
        <div style="display:flex;gap:var(--space-3);align-items:center;margin-bottom:var(--space-3)">
          ${_dogAvatar(dog.foto_url, dog.name, 44)}
          <div style="flex:1;min-width:0">
            <div style="font-weight:var(--weight-semibold);color:var(--c-text)">${_esc(dog.name)}</div>
            ${dog.rasse ? `<div style="font-size:var(--text-xs);color:var(--c-text-secondary)">${_esc(dog.rasse)}</div>` : ''}
          </div>
          <span style="font-size:var(--text-xs);font-weight:600;
                padding:2px 10px;border-radius:999px;
                background:${isAktiv ? 'var(--c-success-subtle,#d1fae5)' : 'var(--c-surface-2)'};
                color:${isAktiv ? 'var(--c-success,#10b981)' : 'var(--c-text-muted)'}">
            ${isAktiv ? 'Aktiv' : 'Inaktiv'}
          </span>
        </div>

        ${isAktiv ? `
          <div style="font-size:var(--text-sm);color:var(--c-text-secondary);margin-bottom:var(--space-3)">
            ${UI.icon('map-pin')}
            ${listing.ort_name ? _esc(listing.ort_name) + ' · ' : ''}
            Radius: ${listing.radius_km} km
          </div>
          ${listing.beschreibung ? `
            <p style="font-size:var(--text-sm);color:var(--c-text-secondary);
                      margin:0 0 var(--space-3);line-height:1.5">${_esc(listing.beschreibung)}</p>` : ''}
        ` : `
          <p style="font-size:var(--text-sm);color:var(--c-text-muted);margin:0 0 var(--space-3)">
            Noch kein Inserat — trage dich ein, damit andere dich finden können.
          </p>
        `}

        <div style="display:flex;gap:var(--space-2);flex-wrap:wrap">
          <button class="btn btn-primary btn-sm"
                  data-action="edit" data-dog-id="${dog.id}">
            ${UI.icon('pencil')} ${isAktiv ? 'Bearbeiten' : 'Inserat anlegen'}
          </button>
          ${isAktiv ? `
            <button class="btn btn-ghost btn-sm"
                    data-action="deactivate" data-dog-id="${dog.id}">
              ${UI.icon('x')} Deaktivieren
            </button>` : ''}
        </div>
      </div>
    `;
  }

  function _showListingModal(dog, existing, onSaved) {
    const formId = 'listing-form';
    UI.modal.open({
      title: `Inserat für ${dog.name}`,
      body: `
        <form id="${formId}">
          <div class="form-group">
            <label class="form-label">Ort / Standort</label>
            <div style="display:flex;gap:var(--space-2)">
              <input type="text" id="listing-ort" class="form-control"
                     placeholder="z.B. München"
                     value="${_esc(existing?.ort_name || '')}">
              <button type="button" class="btn btn-ghost btn-sm" id="listing-gps-btn"
                      title="GPS-Standort ermitteln">
                ${UI.icon('crosshair')}
              </button>
            </div>
            <input type="hidden" id="listing-lat" value="${existing?.lat || ''}">
            <input type="hidden" id="listing-lon" value="${existing?.lon || ''}">
            <div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-top:4px">
              Tipp: Klicke auf ${UI.icon('crosshair')} um deinen Ortsnamen automatisch zu ermitteln.
              Nur der Ortsname wird für andere sichtbar — nicht dein genauer Standort.
            </div>
          </div>

          <div class="form-group">
            <label class="form-label">Suchradius</label>
            <select id="listing-radius" class="form-control">
              <option value="5"  ${(existing?.radius_km||10)===5  ? 'selected' : ''}>5 km</option>
              <option value="10" ${(existing?.radius_km||10)===10 ? 'selected' : ''}>10 km</option>
              <option value="25" ${(existing?.radius_km||10)===25 ? 'selected' : ''}>25 km</option>
              <option value="50" ${(existing?.radius_km||10)===50 ? 'selected' : ''}>50 km</option>
            </select>
          </div>

          <div class="form-group">
            <label class="form-label">Beschreibung (optional)</label>
            <textarea id="listing-beschreibung" class="form-control" rows="3" maxlength="400"
              placeholder="Erzähl etwas über deinen Hund und was ihr sucht…">${_esc(existing?.beschreibung || '')}</textarea>
          </div>
        </form>
      `,
      footer: `
        <button class="btn btn-secondary" id="listing-cancel-btn">Abbrechen</button>
        <button class="btn btn-primary" id="listing-save-btn">
          ${UI.icon('floppy-disk')} Speichern
        </button>
      `,
    });

    // GPS-Button
    document.getElementById('listing-gps-btn').addEventListener('click', async () => {
      const gpsBtn = document.getElementById('listing-gps-btn');
      UI.setLoading(gpsBtn, true);
      try {
        const pos = await API.getLocation();
        document.getElementById('listing-lat').value = pos.lat;
        document.getElementById('listing-lon').value = pos.lon;

        // Reverse-Geocoding für Ortsname
        try {
          const rev = await fetch(
            `https://nominatim.openstreetmap.org/reverse?lat=${pos.lat}&lon=${pos.lon}&format=json&zoom=10&accept-language=de`,
            { cache: 'no-store' }
          );
          const geoData = await rev.json();
          const a = geoData.address || {};
          const ort = a.city || a.town || a.village || a.municipality || '';
          if (ort) document.getElementById('listing-ort').value = ort;
        } catch {}
        UI.toast.success('Standort ermittelt.');
      } catch {
        UI.toast.error('Standort konnte nicht ermittelt werden.');
      } finally {
        UI.setLoading(gpsBtn, false);
      }
    });

    document.getElementById('listing-cancel-btn').addEventListener('click', () => UI.modal.close());

    document.getElementById('listing-save-btn').addEventListener('click', async () => {
      const btn = document.getElementById('listing-save-btn');
      const lat  = parseFloat(document.getElementById('listing-lat').value);
      const lon  = parseFloat(document.getElementById('listing-lon').value);
      const ort  = document.getElementById('listing-ort').value.trim();
      const rad  = parseInt(document.getElementById('listing-radius').value, 10);
      const desc = document.getElementById('listing-beschreibung').value.trim();

      if (!lat || !lon) {
        UI.toast.error('Bitte ermittle zuerst deinen Standort über den GPS-Button.');
        return;
      }

      await UI.asyncButton(btn, async () => {
        await API.put('/playdate/listing', {
          dog_id:       dog.id,
          lat,
          lon,
          ort_name:     ort || null,
          radius_km:    rad,
          beschreibung: desc || null,
        });
        UI.modal.close();
        UI.toast.success('Inserat gespeichert!');
        onSaved?.();
      }, { errorMsg: null });
    });
  }

  // ------------------------------------------------------------------
  // TAB: ANFRAGEN
  // ------------------------------------------------------------------
  async function _renderRequests(el) {
    el.innerHTML = `<p style="text-align:center;color:var(--c-text-secondary);padding:var(--space-6)">${UI.icon('spinner')} Lädt…</p>`;
    try {
      const data = await API.get('/playdate/requests');
      const incoming = data.incoming || [];
      const outgoing = data.outgoing || [];

      // Badge aktualisieren
      const pendingCount = incoming.filter(r => r.status === 'pending').length;
      const badge = document.getElementById('playdate-req-badge');
      if (badge) {
        badge.textContent = pendingCount;
        badge.style.display = pendingCount > 0 ? '' : 'none';
      }

      if (incoming.length === 0 && outgoing.length === 0) {
        el.innerHTML = UI.emptyState({
          icon: UI.icon('paw-print'),
          title: 'Noch keine Anfragen',
          text: 'Wenn du oder jemand anderes eine Playdate-Anfrage schickt, erscheint sie hier.',
        });
        return;
      }

      el.innerHTML = `
        <div style="display:flex;flex-direction:column;gap:var(--space-5)">

          ${incoming.length > 0 ? `
            <div>
              <h3 style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
                          color:var(--c-text-muted);text-transform:uppercase;letter-spacing:0.05em;
                          margin:0 0 var(--space-3)">Eingehende Anfragen</h3>
              <div style="display:flex;flex-direction:column;gap:var(--space-3)">
                ${incoming.map(r => _incomingCard(r)).join('')}
              </div>
            </div>` : ''}

          ${outgoing.length > 0 ? `
            <div>
              <h3 style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
                          color:var(--c-text-muted);text-transform:uppercase;letter-spacing:0.05em;
                          margin:0 0 var(--space-3)">Ausgehende Anfragen</h3>
              <div style="display:flex;flex-direction:column;gap:var(--space-3)">
                ${outgoing.map(r => _outgoingCard(r)).join('')}
              </div>
            </div>` : ''}

        </div>
      `;

      // Button-Events (Accept/Decline)
      el.querySelectorAll('.req-accept-btn, .req-decline-btn').forEach(btn => {
        btn.addEventListener('click', async () => {
          const reqId = parseInt(btn.dataset.reqId, 10);
          const status = btn.dataset.status;
          await UI.asyncButton(btn, async () => {
            const result = await API.patch(`/playdate/requests/${reqId}`, { status });
            if (status === 'accepted' && result.conversation_id) {
              UI.toast.success('Anfrage angenommen! Chat wurde geöffnet.');
              setTimeout(() => {
                App.navigate('chat', true, { conversation_id: result.conversation_id });
              }, 800);
            } else {
              UI.toast.success(status === 'accepted' ? 'Anfrage angenommen.' : 'Anfrage abgelehnt.');
            }
            await _renderRequests(el);
          }, { errorMsg: null });
        });
      });

      // Chat-Buttons
      el.querySelectorAll('.req-chat-btn').forEach(btn => {
        btn.addEventListener('click', () => {
          App.navigate('chat', true);
        });
      });

    } catch (err) {
      el.innerHTML = `<p style="text-align:center;color:var(--c-danger);padding:var(--space-6)">${err.message}</p>`;
    }
  }

  function _incomingCard(r) {
    const isPending = r.status === 'pending';
    return `
      <div class="card" style="padding:var(--space-4)">
        <div style="display:flex;gap:var(--space-3);align-items:flex-start;margin-bottom:var(--space-3)">
          ${_dogAvatar(r.from_dog_foto, r.from_dog_name, 44)}
          <div style="flex:1;min-width:0">
            <div style="font-weight:var(--weight-semibold);color:var(--c-text)">${_esc(r.from_dog_name)}</div>
            <div style="font-size:var(--text-xs);color:var(--c-text-secondary)">
              ${r.from_dog_rasse ? _esc(r.from_dog_rasse) + ' · ' : ''}
              ${r.alter ? _esc(r.alter) + ' · ' : ''}
              von ${_esc(r.from_user_name)}
            </div>
            <div style="font-size:var(--text-xs);color:var(--c-text-muted)">${_fmtDate(r.created_at)}</div>
          </div>
          ${_statusBadge(r.status)}
        </div>

        ${r.nachricht ? `
          <div style="font-size:var(--text-sm);color:var(--c-text-secondary);
                      background:var(--c-surface-2);border-radius:var(--radius-md);
                      padding:var(--space-2) var(--space-3);margin-bottom:var(--space-3);
                      line-height:1.5">
            "${_esc(r.nachricht)}"
          </div>` : ''}

        ${isPending ? `
          <div style="display:flex;gap:var(--space-2)">
            <button class="btn btn-primary btn-sm req-accept-btn"
                    data-req-id="${r.id}" data-status="accepted">
              ${UI.icon('check')} Annehmen
            </button>
            <button class="btn btn-ghost btn-sm req-decline-btn"
                    data-req-id="${r.id}" data-status="declined">
              ${UI.icon('x')} Ablehnen
            </button>
          </div>` : `
          ${r.status === 'accepted' ? `
            <button class="btn btn-ghost btn-sm req-chat-btn">
              ${UI.icon('chat-circle-dots')} Zum Chat
            </button>` : ''}
          `}
      </div>
    `;
  }

  function _outgoingCard(r) {
    return `
      <div class="card" style="padding:var(--space-4)">
        <div style="display:flex;gap:var(--space-3);align-items:flex-start;margin-bottom:var(--space-3)">
          ${_dogAvatar(r.to_dog_foto, r.to_dog_name, 44)}
          <div style="flex:1;min-width:0">
            <div style="font-weight:var(--weight-semibold);color:var(--c-text)">${_esc(r.to_dog_name)}</div>
            <div style="font-size:var(--text-xs);color:var(--c-text-secondary)">
              ${r.to_dog_rasse ? _esc(r.to_dog_rasse) + ' · ' : ''}
              von ${_esc(r.to_user_name)}
            </div>
            <div style="font-size:var(--text-xs);color:var(--c-text-muted)">${_fmtDate(r.created_at)}</div>
          </div>
          ${_statusBadge(r.status)}
        </div>

        ${r.nachricht ? `
          <p style="font-size:var(--text-sm);color:var(--c-text-secondary);margin:0 0 var(--space-3)">
            "${_esc(r.nachricht)}"
          </p>` : ''}

        ${r.status === 'accepted' ? `
          <button class="btn btn-ghost btn-sm req-chat-btn">
            ${UI.icon('chat-circle-dots')} Chat öffnen
          </button>` : ''}
      </div>
    `;
  }

  // ------------------------------------------------------------------
  return { init, refresh, onDogChange };
})();
