// daygig-landlord.js — Landlord mode: Properties, Units, Tenants, Leases.
// Talks to /api/properties, /api/units, /api/tenants, /api/leases.

let _llProperties = [];
let _llTenants = [];

function _llEsc(s) {
  return String(s == null ? '' : s).replace(/[&<>"']/g, c => (
    { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]
  ));
}

async function _llGet(url) {
  const res = await fetch(url, { headers: { 'Accept': 'application/json' } });
  if (!res.ok) throw new Error('Request failed: ' + res.status);
  return res.json();
}

async function _llPost(url, body) {
  const res = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
    body: JSON.stringify(body || {}),
  });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || ('Request failed: ' + res.status));
  return data;
}

// ── Properties ────────────────────────────────────────────────────────────────

async function llLoadProperties() {
  const host = document.getElementById('ll-properties-list');
  if (!host) return;
  try {
    _llProperties = await _llGet('/api/properties');
    if (!_llProperties.length) {
      host.innerHTML = '<div style="color:var(--text-dim);padding:24px;text-align:center;">No properties yet. Click “Add Property” to start.</div>';
      return;
    }
    host.innerHTML = _llProperties.map(_llPropertyCard).join('');
  } catch (e) {
    host.innerHTML = '<div style="color:var(--err);padding:16px;">Could not load properties: ' + _llEsc(e.message) + '</div>';
  }
}

function _llPropertyCard(p) {
  const addr = [p.address_line1, p.city, p.state, p.zip].filter(Boolean).join(', ');
  const units = (p.units || []).map(u =>
    `<div style="display:flex;justify-content:space-between;padding:4px 0;border-top:1px solid var(--border);font-size:13px;">
       <span>${_llEsc(u.label)}${u.bedrooms ? ' · ' + _llEsc(u.bedrooms) + 'bd' : ''}${u.bathrooms ? '/' + _llEsc(u.bathrooms) + 'ba' : ''}</span>
       <span style="color:var(--text-dim);">Market rent: ${money(u.market_rent)}</span>
     </div>`).join('') || '<div style="color:var(--text-dim);font-size:13px;padding-top:4px;">No units yet.</div>';
  const typeLabel = String(p.property_type || '').replace(/_/g, ' ');
  return `
    <div class="card" style="padding:16px;margin-bottom:12px;">
      <div style="display:flex;justify-content:space-between;align-items:flex-start;">
        <div>
          <strong style="font-size:15px;">${_llEsc(p.name)}</strong>
          <div style="color:var(--text-dim);font-size:13px;">${_llEsc(typeLabel)}${addr ? ' · ' + _llEsc(addr) : ''}</div>
        </div>
        <div style="display:flex;gap:6px;">
          <button class="btn btn-ghost btn-sm" onclick="llEditProperty(${p.id})">Edit</button>
          <button class="btn btn-ghost btn-sm" onclick="llAddUnit(${p.id})">＋ Unit</button>
          <button class="btn btn-ghost btn-sm" onclick="llDeleteProperty(${p.id})">Delete</button>
        </div>
      </div>
      <div style="display:flex;gap:20px;margin:8px 0;font-size:12px;color:var(--text-dim);">
        <span>Purchase: ${money(p.purchase_price)}</span>
        <span>Land: ${money(p.land_value)}</span>
        <span>Depreciable basis: ${money(p.depreciable_basis)}</span>
        <span>Owner: ${p.ownership_pct}%</span>
      </div>
      <div style="margin-top:6px;">${units}</div>
    </div>`;
}

function llShowPropertyForm() {
  document.getElementById('ll-prop-id').value = '';
  ['ll-prop-name','ll-prop-addr','ll-prop-city','ll-prop-state','ll-prop-zip','ll-prop-price','ll-prop-land','ll-prop-inservice','ll-prop-lender','ll-prop-notes'].forEach(id => { const el = document.getElementById(id); if (el) el.value = ''; });
  document.getElementById('ll-prop-type').value = 'single_family';
  document.getElementById('ll-property-form').style.display = '';
}

function llHidePropertyForm() {
  document.getElementById('ll-property-form').style.display = 'none';
}

function llEditProperty(id) {
  const p = _llProperties.find(x => x.id === id);
  if (!p) return;
  document.getElementById('ll-prop-id').value = p.id;
  document.getElementById('ll-prop-name').value = p.name || '';
  document.getElementById('ll-prop-type').value = p.property_type || 'single_family';
  document.getElementById('ll-prop-addr').value = p.address_line1 || '';
  document.getElementById('ll-prop-city').value = p.city || '';
  document.getElementById('ll-prop-state').value = p.state || '';
  document.getElementById('ll-prop-zip').value = p.zip || '';
  document.getElementById('ll-prop-price').value = p.purchase_price || '';
  document.getElementById('ll-prop-land').value = p.land_value || '';
  document.getElementById('ll-prop-inservice').value = p.in_service_date || '';
  document.getElementById('ll-prop-lender').value = p.mortgage_lender || '';
  document.getElementById('ll-prop-notes').value = p.notes || '';
  document.getElementById('ll-property-form').style.display = '';
  document.getElementById('ll-property-form').scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}

async function llSaveProperty() {
  const id = document.getElementById('ll-prop-id').value;
  const body = {
    name: document.getElementById('ll-prop-name').value.trim(),
    property_type: document.getElementById('ll-prop-type').value,
    address_line1: document.getElementById('ll-prop-addr').value.trim(),
    city: document.getElementById('ll-prop-city').value.trim(),
    state: document.getElementById('ll-prop-state').value.trim(),
    zip: document.getElementById('ll-prop-zip').value.trim(),
    purchase_price: document.getElementById('ll-prop-price').value || 0,
    land_value: document.getElementById('ll-prop-land').value || 0,
    in_service_date: document.getElementById('ll-prop-inservice').value,
    mortgage_lender: document.getElementById('ll-prop-lender').value.trim(),
    notes: document.getElementById('ll-prop-notes').value.trim(),
  };
  if (!body.name) { alert('Property name is required.'); return; }
  try {
    if (id) await _llPost('/api/properties/' + id, body);
    else await _llPost('/api/properties', body);
    llHidePropertyForm();
    await llLoadProperties();
  } catch (e) {
    alert('Could not save property: ' + e.message);
  }
}

async function llDeleteProperty(id) {
  if (!confirm('Delete this property and its units and leases? This cannot be undone.')) return;
  try {
    await _llPost('/api/properties/delete/' + id, {});
    await llLoadProperties();
  } catch (e) {
    alert('Could not delete: ' + e.message);
  }
}

async function llAddUnit(propertyId) {
  const label = prompt('Unit label (e.g. "Unit B", "Upstairs"):', 'Unit');
  if (label === null) return;
  const rent = prompt('Market rent for this unit ($/month):', '0');
  if (rent === null) return;
  try {
    await _llPost('/api/properties/' + propertyId + '/units', { label: label.trim() || 'Unit', market_rent: rent || 0 });
    await llLoadProperties();
  } catch (e) {
    alert('Could not add unit: ' + e.message);
  }
}

// ── Tenants ─────────────────────────────────────────────────────────────────

async function llLoadTenants() {
  const host = document.getElementById('ll-tenants-list');
  if (!host) return;
  try {
    _llTenants = await _llGet('/api/tenants');
    if (!_llTenants.length) {
      host.innerHTML = '<div style="color:var(--text-dim);font-size:13px;">No tenants yet.</div>';
    } else {
      host.innerHTML = _llTenants.map(t =>
        `<div style="display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-top:1px solid var(--border);">
           <div><div>${_llEsc(t.name)}</div><div style="color:var(--text-dim);font-size:12px;">${_llEsc(t.email || t.phone || '')}</div></div>
           <button class="btn btn-ghost btn-sm" onclick="llDeleteTenant(${t.id})">✕</button>
         </div>`).join('');
    }
  } catch (e) {
    host.innerHTML = '<div style="color:var(--err);font-size:13px;">' + _llEsc(e.message) + '</div>';
  }
}

function llShowTenantForm() {
  ['ll-tenant-id','ll-tenant-name','ll-tenant-email','ll-tenant-phone'].forEach(id => { const el = document.getElementById(id); if (el) el.value = ''; });
  document.getElementById('ll-tenant-form').style.display = '';
}

function llHideTenantForm() {
  document.getElementById('ll-tenant-form').style.display = 'none';
}

async function llSaveTenant() {
  const body = {
    name: document.getElementById('ll-tenant-name').value.trim(),
    email: document.getElementById('ll-tenant-email').value.trim(),
    phone: document.getElementById('ll-tenant-phone').value.trim(),
  };
  if (!body.name) { alert('Tenant name is required.'); return; }
  try {
    await _llPost('/api/tenants', body);
    llHideTenantForm();
    await llLoadTenants();
    _llPopulateLeaseSelects();
  } catch (e) {
    alert('Could not save tenant: ' + e.message);
  }
}

async function llDeleteTenant(id) {
  if (!confirm('Delete this tenant? Their leases stay but lose the tenant link.')) return;
  try {
    await _llPost('/api/tenants/delete/' + id, {});
    await llLoadTenants();
    _llPopulateLeaseSelects();
  } catch (e) {
    alert('Could not delete tenant: ' + e.message);
  }
}

// ── Leases ──────────────────────────────────────────────────────────────────

async function llLoadLeases() {
  const host = document.getElementById('ll-leases-list');
  if (!host) return;
  try {
    const leases = await _llGet('/api/leases');
    if (!leases.length) {
      host.innerHTML = '<div style="color:var(--text-dim);padding:18px;">No leases yet. Add a property and a tenant, then create a lease.</div>';
      return;
    }
    host.innerHTML = leases.map(l => {
      const statusColor = l.status === 'active' ? 'var(--accent)' : 'var(--text-dim)';
      return `<div class="card" style="padding:12px;margin-bottom:10px;display:flex;justify-content:space-between;align-items:center;">
        <div>
          <strong>${_llEsc(l.property_name || 'Unit')} · ${_llEsc(l.unit_label || '')}</strong>
          <div style="color:var(--text-dim);font-size:13px;">${_llEsc(l.tenant_name || 'No tenant')} · ${money(l.monthly_rent)}/mo · due day ${l.due_day} · deposit ${money(l.deposit)}</div>
          <div style="font-size:12px;color:${statusColor};">${_llEsc(String(l.status).replace(/_/g,' '))}${l.start_date ? ' · from ' + _llEsc(l.start_date) : ''}</div>
        </div>
        <div style="display:flex;gap:6px;">
          <button class="btn btn-ghost btn-sm" onclick="llRecordDeposit(${l.id}, ${l.deposit_cents || 0})">Deposit</button>
          <button class="btn btn-ghost btn-sm" onclick="llEditLease(${l.id})">Edit</button>
          <button class="btn btn-ghost btn-sm" onclick="llDeleteLease(${l.id})">Delete</button>
        </div>
      </div>`;
    }).join('');
  } catch (e) {
    host.innerHTML = '<div style="color:var(--err);padding:16px;">' + _llEsc(e.message) + '</div>';
  }
}

function _llPopulateLeaseSelects(currentUnitId, currentTenantId) {
  const unitSel = document.getElementById('ll-lease-unit');
  const tenantSel = document.getElementById('ll-lease-tenant');
  if (unitSel) {
    const opts = [];
    _llProperties.forEach(p => (p.units || []).forEach(u => {
      opts.push(`<option value="${u.id}" ${String(u.id) === String(currentUnitId) ? 'selected' : ''}>${_llEsc(p.name)} — ${_llEsc(u.label)}</option>`);
    }));
    unitSel.innerHTML = opts.length ? opts.join('') : '<option value="">No units — add a property first</option>';
  }
  if (tenantSel) {
    tenantSel.innerHTML = '<option value="">— none —</option>' + _llTenants.map(t =>
      `<option value="${t.id}" ${String(t.id) === String(currentTenantId) ? 'selected' : ''}>${_llEsc(t.name)}</option>`).join('');
  }
}

async function llShowLeaseForm() {
  // Make sure property/tenant lists are fresh for the dropdowns.
  if (!_llProperties.length) { try { _llProperties = await _llGet('/api/properties'); } catch (e) {} }
  if (!_llTenants.length) { try { _llTenants = await _llGet('/api/tenants'); } catch (e) {} }
  document.getElementById('ll-lease-id').value = '';
  document.getElementById('ll-lease-rent').value = '';
  document.getElementById('ll-lease-dueday').value = '1';
  document.getElementById('ll-lease-deposit').value = '';
  document.getElementById('ll-lease-status').value = 'active';
  document.getElementById('ll-lease-start').value = '';
  document.getElementById('ll-lease-end').value = '';
  _llPopulateLeaseSelects();
  document.getElementById('ll-lease-form').style.display = '';
}

function llHideLeaseForm() {
  document.getElementById('ll-lease-form').style.display = 'none';
}

async function llEditLease(id) {
  try {
    const l = await _llGet('/api/leases/' + id);
    if (!_llProperties.length) _llProperties = await _llGet('/api/properties');
    if (!_llTenants.length) _llTenants = await _llGet('/api/tenants');
    document.getElementById('ll-lease-id').value = l.id;
    document.getElementById('ll-lease-rent').value = l.monthly_rent || '';
    document.getElementById('ll-lease-dueday').value = l.due_day || 1;
    document.getElementById('ll-lease-deposit').value = l.deposit || '';
    document.getElementById('ll-lease-status').value = l.status || 'active';
    document.getElementById('ll-lease-start').value = l.start_date || '';
    document.getElementById('ll-lease-end').value = l.end_date || '';
    _llPopulateLeaseSelects(l.unit_id, l.tenant_id);
    document.getElementById('ll-lease-form').style.display = '';
    document.getElementById('ll-lease-form').scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  } catch (e) {
    alert('Could not load lease: ' + e.message);
  }
}

async function llSaveLease() {
  const id = document.getElementById('ll-lease-id').value;
  const unitId = document.getElementById('ll-lease-unit').value;
  if (!unitId) { alert('Pick a unit. Add a property first if the list is empty.'); return; }
  const body = {
    unit_id: unitId,
    tenant_id: document.getElementById('ll-lease-tenant').value || null,
    monthly_rent: document.getElementById('ll-lease-rent').value || 0,
    due_day: document.getElementById('ll-lease-dueday').value || 1,
    deposit: document.getElementById('ll-lease-deposit').value || 0,
    status: document.getElementById('ll-lease-status').value,
    start_date: document.getElementById('ll-lease-start').value,
    end_date: document.getElementById('ll-lease-end').value,
  };
  try {
    if (id) await _llPost('/api/leases/' + id, body);
    else await _llPost('/api/leases', body);
    llHideLeaseForm();
    await llLoadLeases();
  } catch (e) {
    alert('Could not save lease: ' + e.message);
  }
}

async function llDeleteLease(id) {
  if (!confirm('Delete this lease?')) return;
  try {
    await _llPost('/api/leases/delete/' + id, {});
    await llLoadLeases();
  } catch (e) {
    alert('Could not delete lease: ' + e.message);
  }
}

// Called when the Tenants & Leases tab opens: load everything it needs.
async function llLoadLeasesPanel() {
  try { _llProperties = await _llGet('/api/properties'); } catch (e) {}
  await llLoadTenants();
  await llLoadLeases();
}

// ── Deposits ──────────────────────────────────────────────────────────────────

async function llRecordDeposit(leaseId, depositCents) {
  const suggested = depositCents ? (depositCents / 100).toFixed(2) : '';
  const amount = prompt('Security deposit amount received ($):', suggested);
  if (amount === null) return;
  try {
    const r = await _llPost('/api/rent/deposit', { lease_id: leaseId, amount: amount, payment_method: 'bank' });
    alert('Deposit of ' + money(r.amount) + ' recorded as a liability (held for the tenant).');
  } catch (e) {
    alert('Could not record deposit: ' + e.message);
  }
}

// ── Rent Roll ─────────────────────────────────────────────────────────────────

function _llCurrentMonth() {
  const d = new Date();
  return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0');
}

async function llLoadRentRoll() {
  const periodEl = document.getElementById('ll-rr-period');
  if (periodEl && !periodEl.value) periodEl.value = _llCurrentMonth();
  const period = periodEl ? periodEl.value : _llCurrentMonth();
  const tbody = document.getElementById('ll-rr-tbody');
  const summary = document.getElementById('ll-rr-summary');
  if (tbody) tbody.innerHTML = '<tr><td colspan="8" style="padding:24px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
  try {
    const data = await _llGet('/api/rent-roll?period=' + encodeURIComponent(period));
    if (summary) {
      summary.innerHTML = [
        ['Billed', data.total_due],
        ['Collected', data.total_collected],
        ['Outstanding', data.total_outstanding],
      ].map(([k, v]) =>
        `<div class="card" style="padding:10px 16px;"><div style="font-size:11px;color:var(--text-dim);">${k}</div><div style="font-size:18px;font-weight:700;">${money(v)}</div></div>`
      ).join('');
    }
    if (!data.charges.length) {
      if (tbody) tbody.innerHTML = '<tr><td colspan="8" style="padding:24px;text-align:center;color:var(--text-dim);">No active leases for this month. Add a lease to start the rent roll.</td></tr>';
      return;
    }
    const statusColors = { paid: 'var(--accent)', partial: '#e6a23c', late: 'var(--err)', due: 'var(--text-dim)' };
    if (tbody) tbody.innerHTML = data.charges.map(c => {
      const color = statusColors[c.status] || 'var(--text-dim)';
      const action = c.status === 'paid'
        ? '<span style="color:var(--text-dim);font-size:12px;">—</span>'
        : `<button class="btn btn-primary btn-sm" onclick="llShowPaymentForm(${c.id}, ${c.balance_cents}, '${_llEsc(c.property_name)} / ${_llEsc(c.unit_label)}')">Record</button>`;
      return `<tr style="border-top:1px solid var(--border);">
        <td style="padding:10px 12px;">${_llEsc(c.property_name)} <span style="color:var(--text-dim);">/ ${_llEsc(c.unit_label)}</span></td>
        <td style="padding:10px 12px;">${_llEsc(c.tenant_name || '—')}</td>
        <td style="padding:10px 12px;color:var(--text-dim);">${_llEsc(c.due_date || '')}</td>
        <td style="padding:10px 12px;">${money(c.amount_due)}</td>
        <td style="padding:10px 12px;">${money(c.amount_paid)}</td>
        <td style="padding:10px 12px;">${money(c.balance)}</td>
        <td style="padding:10px 12px;color:${color};text-transform:capitalize;">${_llEsc(c.status)}</td>
        <td style="padding:10px 12px;text-align:right;">${action}</td>
      </tr>`;
    }).join('');
  } catch (e) {
    if (tbody) tbody.innerHTML = '<tr><td colspan="8" style="padding:16px;color:var(--err);">' + _llEsc(e.message) + '</td></tr>';
  }
}

function llShowPaymentForm(chargeId, balanceCents, label) {
  document.getElementById('ll-pay-charge').value = chargeId;
  document.getElementById('ll-pay-amount').value = balanceCents ? (balanceCents / 100).toFixed(2) : '';
  document.getElementById('ll-pay-late').value = '';
  document.getElementById('ll-pay-method').value = 'bank';
  document.getElementById('ll-pay-date').value = todayIso();
  document.getElementById('ll-pay-title').textContent = 'Record payment — ' + (label || '');
  const form = document.getElementById('ll-pay-form');
  form.style.display = '';
  form.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}

function llHidePaymentForm() {
  document.getElementById('ll-pay-form').style.display = 'none';
}

async function llSubmitPayment() {
  const body = {
    charge_id: document.getElementById('ll-pay-charge').value,
    amount: document.getElementById('ll-pay-amount').value || 0,
    late_fee: document.getElementById('ll-pay-late').value || 0,
    payment_method: document.getElementById('ll-pay-method').value,
    date: document.getElementById('ll-pay-date').value,
  };
  if (!(Number(body.amount) > 0)) { alert('Enter a payment amount.'); return; }
  try {
    await _llPost('/api/rent/payment', body);
    llHidePaymentForm();
    await llLoadRentRoll();
  } catch (e) {
    alert('Could not record payment: ' + e.message);
  }
}

// ── Schedule E / Taxes ────────────────────────────────────────────────────────

function _llEnsureYearOptions() {
  const sel = document.getElementById('ll-se-year');
  if (!sel || sel.options.length) return;
  const now = new Date().getFullYear();
  let html = '';
  for (let y = now; y >= now - 6; y--) html += `<option value="${y}">${y}</option>`;
  sel.innerHTML = html;
}

async function llLoadScheduleE() {
  _llEnsureYearOptions();
  const yearSel = document.getElementById('ll-se-year');
  const year = yearSel ? yearSel.value : new Date().getFullYear();
  const summary = document.getElementById('ll-se-summary');
  const ws = document.getElementById('ll-se-worksheet');
  const dep = document.getElementById('ll-se-depreciation');
  if (ws) ws.innerHTML = '<div style="color:var(--text-dim);">Loading…</div>';
  try {
    const data = await _llGet('/api/landlord/schedule-e?year=' + encodeURIComponent(year));
    if (summary) {
      const netColor = data.is_loss ? 'var(--err)' : 'var(--accent)';
      summary.innerHTML = [
        ['Rents received', data.total_income, 'var(--text)'],
        ['Total expenses', data.total_expenses, 'var(--text)'],
        [data.is_loss ? 'Net loss' : 'Net income', data.net_income, netColor],
      ].map(([k, v, c]) =>
        `<div class="card" style="padding:10px 16px;"><div style="font-size:11px;color:var(--text-dim);">${k}</div><div style="font-size:18px;font-weight:700;color:${c};">${money(v)}</div></div>`
      ).join('');
    }
    if (ws) {
      let rows = '';
      rows += '<div style="font-size:12px;color:var(--text-dim);margin:6px 0 2px;">Income</div>';
      (data.income_lines.length ? data.income_lines : [{ label: 'No rental income recorded', amount: 0 }]).forEach(l => {
        rows += _llSeRow(l.label, l.amount);
      });
      rows += _llSeRow('<strong>Total income</strong>', data.total_income, true);
      rows += '<div style="font-size:12px;color:var(--text-dim);margin:10px 0 2px;">Expenses</div>';
      (data.expense_lines.length ? data.expense_lines : [{ line: '', label: 'No expenses recorded', amount: 0 }]).forEach(l => {
        rows += _llSeRow((l.line ? 'Line ' + l.line + ' · ' : '') + l.label, l.amount);
      });
      rows += _llSeRow('<strong>Total expenses</strong>', data.total_expenses, true);
      rows += _llSeRow('<strong>' + (data.is_loss ? 'Net loss' : 'Net income') + '</strong>', data.net_income, true);
      ws.innerHTML = rows;
    }
    if (dep) {
      const props = data.depreciation.properties || [];
      if (!props.length) {
        dep.innerHTML = '<div style="color:var(--text-dim);font-size:13px;">No properties yet.</div>';
      } else {
        dep.innerHTML = props.map(p =>
          `<div style="padding:6px 0;border-top:1px solid var(--border);">
             <div style="display:flex;justify-content:space-between;"><span>${_llEsc(p.property_name)}</span><strong>${money(p.this_year)}</strong></div>
             <div style="font-size:11px;color:var(--text-dim);">Basis ${money(p.basis)} · ${_llEsc(p.note || '')}</div>
           </div>`
        ).join('') + _llSeRow('<strong>Total depreciation</strong>', data.depreciation.total_depreciation, true);
      }
    }
  } catch (e) {
    if (ws) ws.innerHTML = '<div style="color:var(--err);">' + _llEsc(e.message) + '</div>';
  }
}

function _llSeRow(label, amount, strong) {
  const border = strong ? 'border-top:1px solid var(--border-hi);margin-top:4px;padding-top:6px;' : '';
  return `<div style="display:flex;justify-content:space-between;padding:3px 0;${border}">
            <span>${label}</span><span style="font-family:var(--mono);">${money(amount)}</span>
          </div>`;
}

function llDownloadYearEnd() {
  const yearSel = document.getElementById('ll-se-year');
  const year = yearSel ? yearSel.value : new Date().getFullYear();
  window.location = '/api/landlord/year-end.zip?year=' + encodeURIComponent(year);
}

// ── Property P&L ──────────────────────────────────────────────────────────────

async function llLoadPropertyPnl() {
  const periodEl = document.getElementById('ll-pnl-period');
  if (periodEl && !periodEl.value) periodEl.value = _llCurrentMonth();
  const period = periodEl ? periodEl.value : _llCurrentMonth();
  const list = document.getElementById('ll-pnl-list');
  if (list) list.innerHTML = '<div style="color:var(--text-dim);padding:24px;text-align:center;">Loading…</div>';
  try {
    // Need the property list for the assignment dropdown.
    if (!_llProperties.length) { try { _llProperties = await _llGet('/api/properties'); } catch (e) {} }
    const data = await _llGet('/api/landlord/property-pnl?period=' + encodeURIComponent(period));
    if (list) {
      if (!data.properties.length) {
        list.innerHTML = '<div style="color:var(--text-dim);padding:24px;text-align:center;">No properties yet.</div>';
      } else {
        const portfolioColor = data.portfolio_net_cents >= 0 ? 'var(--accent)' : 'var(--err)';
        let html = `<div class="card" style="padding:12px 16px;margin-bottom:12px;display:flex;justify-content:space-between;align-items:center;">
          <strong>Portfolio net — ${_llEsc(period)}</strong>
          <span style="font-size:20px;font-weight:700;color:${portfolioColor};">${money(data.portfolio_net)}</span></div>`;
        html += data.properties.map(p => {
          const color = p.is_profit ? 'var(--accent)' : 'var(--err)';
          const lines = (p.expense_lines || []).map(l =>
            `<div style="display:flex;justify-content:space-between;font-size:12px;color:var(--text-dim);"><span>${_llEsc(l.name.replace('Expenses:', ''))}</span><span>${money(l.amount)}</span></div>`).join('');
          return `<div class="card" style="padding:16px;margin-bottom:10px;">
            <div style="display:flex;justify-content:space-between;align-items:flex-start;">
              <strong style="font-size:15px;">${_llEsc(p.property_name)}</strong>
              <div style="text-align:right;"><div style="font-size:18px;font-weight:700;color:${color};">${money(p.net)}</div><div style="font-size:11px;color:var(--text-dim);">${p.is_profit ? 'profit' : 'loss'} this period</div></div>
            </div>
            <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:10px;font-size:13px;">
              <div><div style="color:var(--text-dim);font-size:11px;">Income</div>${money(p.income)}</div>
              <div><div style="color:var(--text-dim);font-size:11px;">Cash expenses</div>${money(p.cash_expense)}</div>
              <div><div style="color:var(--text-dim);font-size:11px;">Depreciation</div>${money(p.depreciation)}</div>
              <div><div style="color:var(--text-dim);font-size:11px;">Total expenses</div>${money(p.total_expense)}</div>
            </div>
            ${lines ? '<div style="margin-top:8px;border-top:1px solid var(--border);padding-top:6px;">' + lines + '</div>' : ''}
          </div>`;
        }).join('');
        list.innerHTML = html;
      }
    }
    // Assignment section
    await llLoadUntaggedExpenses(data.unassigned);
  } catch (e) {
    if (list) list.innerHTML = '<div style="color:var(--err);padding:16px;">' + _llEsc(e.message) + '</div>';
  }
}

async function llLoadUntaggedExpenses(unassigned) {
  const wrap = document.getElementById('ll-pnl-assign');
  const host = document.getElementById('ll-pnl-untagged');
  if (!wrap || !host) return;
  try {
    const data = await _llGet('/api/landlord/untagged-expenses');
    const items = data.expenses || [];
    if (!items.length) {
      wrap.style.display = 'none';
      return;
    }
    wrap.style.display = '';
    const opts = '<option value="">— pick property —</option>' + _llProperties.map(p => `<option value="${p.id}">${_llEsc(p.name)}</option>`).join('');
    host.innerHTML = items.map(it =>
      `<div style="display:flex;justify-content:space-between;align-items:center;gap:10px;padding:6px 0;border-top:1px solid var(--border);">
         <div><div>${_llEsc(it.description)}</div><div style="font-size:12px;color:var(--text-dim);">${_llEsc(it.date)} · ${money(it.amount)}</div></div>
         <div style="display:flex;gap:6px;align-items:center;">
           <select id="ll-assign-${it.transaction_id}">${opts}</select>
           <button class="btn btn-ghost btn-sm" onclick="llAssignExpense(${it.transaction_id})">Assign</button>
         </div>
       </div>`).join('');
  } catch (e) {
    host.innerHTML = '<div style="color:var(--err);font-size:13px;">' + _llEsc(e.message) + '</div>';
  }
}

async function llAssignExpense(transactionId) {
  const sel = document.getElementById('ll-assign-' + transactionId);
  const propertyId = sel ? sel.value : '';
  if (!propertyId) { alert('Pick a property first.'); return; }
  try {
    await _llPost('/api/transactions/' + transactionId + '/property', { property_id: propertyId });
    await llLoadPropertyPnl();
  } catch (e) {
    alert('Could not assign: ' + e.message);
  }
}

// ── CapEx Reserves ──────────────────────────────────────────────────────────

function _llStatusColor(status) {
  return status === 'funded' ? 'var(--accent)'
    : status === 'behind' ? 'var(--warn, #e8b339)'
    : status === 'critical' ? 'var(--err)' : 'var(--text-dim)';
}

async function llLoadReserves() {
  const host = document.getElementById('ll-reserve-list');
  if (host) host.innerHTML = '<div style="color:var(--text-dim);padding:24px;text-align:center;">Loading…</div>';
  try {
    const data = await _llGet('/api/landlord/reserves');
    if (host) {
      if (!data.properties.length) {
        host.innerHTML = '<div style="color:var(--text-dim);padding:24px;text-align:center;">No properties yet — add one under Properties.</div>';
      } else {
        host.innerHTML = data.properties.map(p => {
          const color = _llStatusColor(p.status);
          const pct = Math.max(0, Math.min(100, p.funded_pct));
          const statusLabel = p.status === 'no_target' ? 'No target set'
            : p.status === 'funded' ? 'Fully funded'
            : `${money(p.shortfall)} short — set aside ${money(p.monthly_needed)}/mo to fund in ${p.months_to_target} months`;
          return `<div class="card" style="padding:16px;margin-bottom:10px;">
            <div style="display:flex;justify-content:space-between;align-items:center;">
              <strong>CapEx Reserve — ${_llEsc(p.property_name)}</strong>
              <span style="color:${color};font-weight:700;">${money(p.balance)} of ${money(p.target)}</span>
            </div>
            <div style="background:var(--border);border-radius:4px;height:8px;margin:10px 0 6px;overflow:hidden;">
              <div style="width:${pct}%;height:100%;background:${color};"></div>
            </div>
            <div style="font-size:12px;color:${color};">${p.status === 'funded' ? '✓' : dgIcon('warning', 12)} ${_llEsc(statusLabel)}</div>
            <div style="display:flex;gap:8px;margin-top:10px;flex-wrap:wrap;align-items:center;">
              <input id="ll-res-target-${p.property_id}" inputmode="decimal" placeholder="Target $" style="width:110px;">
              <button class="btn btn-ghost" onclick="llSetReserveTarget(${p.property_id})">Set target</button>
              <input id="ll-res-amt-${p.property_id}" inputmode="decimal" placeholder="Amount $" style="width:110px;">
              <button class="btn btn-ghost" onclick="llReserveEntry(${p.property_id}, 'deposit')">Deposit</button>
              <button class="btn btn-ghost" onclick="llReserveEntry(${p.property_id}, 'withdrawal')">Withdraw</button>
            </div>
          </div>`;
        }).join('');
      }
    }
  } catch (e) {
    if (host) host.innerHTML = '<div style="color:var(--err);padding:16px;">' + _llEsc(e.message) + '</div>';
  }
  llLoadOwnerDraw();
  llLoadFeeLeak();
}

async function llSetReserveTarget(propertyId) {
  const input = document.getElementById('ll-res-target-' + propertyId);
  const val = input ? input.value.trim() : '';
  if (!val) { alert('Enter a target amount.'); return; }
  try {
    await _llPost(`/api/landlord/reserves/${propertyId}/target`, { target: val });
    await llLoadReserves();
  } catch (e) { alert('Could not set target: ' + e.message); }
}

async function llReserveEntry(propertyId, entryType) {
  const input = document.getElementById('ll-res-amt-' + propertyId);
  const val = input ? input.value.trim() : '';
  if (!val) { alert('Enter an amount.'); return; }
  try {
    await _llPost(`/api/landlord/reserves/${propertyId}/entry`, { amount: val, entry_type: entryType });
    await llLoadReserves();
  } catch (e) { alert('Could not record entry: ' + e.message); }
}

// ── Owner Draw Calculator ───────────────────────────────────────────────────

async function llLoadOwnerDraw() {
  const host = document.getElementById('ll-draw-body');
  if (!host) return;
  try {
    const d = await _llGet('/api/reports/owner-draw');
    const rows = [];
    rows.push(`<div style="display:flex;justify-content:space-between;"><span>Cash on hand (total draw)</span><strong>${money(d.total_draw)}</strong></div>`);
    if (d.upcoming_total_cents) rows.push(`<div style="display:flex;justify-content:space-between;color:var(--text-dim);"><span>− Recurring bills due in ${d.lookahead_days} days</span><span>${money(d.upcoming_total)}</span></div>`);
    if (d.reserve_shortfall_cents) rows.push(`<div style="display:flex;justify-content:space-between;color:var(--text-dim);"><span>− Unfunded CapEx reserves</span><span>${money(d.reserve_shortfall)}</span></div>`);
    if (d.held_total_cents) rows.push(`<div style="display:flex;justify-content:space-between;color:var(--text-dim);"><span>− Sales tax / deposits held</span><span>${money(d.held_total)}</span></div>`);
    const color = d.safe_draw_cents > 0 ? 'var(--accent)' : 'var(--err)';
    rows.push(`<div style="display:flex;justify-content:space-between;border-top:1px solid var(--border);margin-top:6px;padding-top:6px;font-size:16px;"><strong>Safe draw</strong><strong style="color:${color};">${money(d.safe_draw)}</strong></div>`);
    host.innerHTML = rows.join('');
  } catch (e) {
    host.innerHTML = '<div style="color:var(--err);">' + _llEsc(e.message) + '</div>';
  }
}

// ── Fee Leak Report ─────────────────────────────────────────────────────────

async function llLoadFeeLeak() {
  const host = document.getElementById('ll-feeleak-body');
  if (!host) return;
  const sel = document.getElementById('ll-feeleak-year');
  if (sel && !sel.options.length) {
    const y = new Date().getFullYear();
    for (let i = 0; i < 4; i++) sel.add(new Option(String(y - i), String(y - i)));
  }
  const year = sel ? sel.value : String(new Date().getFullYear());
  try {
    const d = await _llGet('/api/reports/fee-leak?period=' + encodeURIComponent(year));
    if (!d.categories.length) {
      host.innerHTML = '<div style="color:var(--text-dim);">No fees found for ' + _llEsc(year) + '. Either you are winning, or nothing is categorized yet.</div>';
      return;
    }
    const cats = d.categories.map(c =>
      `<div style="display:flex;justify-content:space-between;font-size:13px;"><span>${_llEsc(c.name.replace('Expenses:', ''))}</span><span>${money(c.amount)}</span></div>`).join('');
    const pct = d.pct_of_income != null ? ` — <strong>${d.pct_of_income}%</strong> of income` : '';
    host.innerHTML = cats +
      `<div style="display:flex;justify-content:space-between;border-top:1px solid var(--border);margin-top:6px;padding-top:6px;"><strong>Total leak (${_llEsc(year)})</strong><strong style="color:var(--err);">${money(d.total)}</strong></div>` +
      `<div style="font-size:12px;color:var(--text-dim);margin-top:4px;">${money(d.total)} left the building in fees${pct}.</div>`;
  } catch (e) {
    host.innerHTML = '<div style="color:var(--err);">' + _llEsc(e.message) + '</div>';
  }
}

// ── STR Bookings ────────────────────────────────────────────────────────────

async function llLoadStrBookings() {
  const list = document.getElementById('ll-str-list');
  const summary = document.getElementById('ll-str-summary');
  if (list) list.innerHTML = '<div style="color:var(--text-dim);padding:24px;text-align:center;">Loading…</div>';
  try {
    if (!_llProperties.length) { try { _llProperties = await _llGet('/api/properties'); } catch (e) {} }
    const sel = document.getElementById('ll-str-property');
    if (sel) {
      sel.innerHTML = _llProperties.map(p => `<option value="${p.id}">${_llEsc(p.name)}</option>`).join('');
    }
    const [data, sum] = await Promise.all([
      _llGet('/api/landlord/str-bookings'),
      _llGet('/api/landlord/str-summary'),
    ]);
    if (summary) {
      summary.innerHTML = (sum.properties || []).map(p => `
        <div class="card" style="padding:12px 16px;margin-bottom:10px;display:flex;justify-content:space-between;align-items:center;">
          <span><strong>${_llEsc(p.property_name)}</strong> — ${p.bookings} stay${p.bookings === 1 ? '' : 's'}, ${p.nights} night${p.nights === 1 ? '' : 's'} (${sum.year})</span>
          <span style="font-weight:700;color:${p.net_cents >= 0 ? 'var(--accent)' : 'var(--err)'};">${money(p.net)} net · ${money(p.net_per_night)}/night</span>
        </div>`).join('');
    }
    if (list) {
      if (!data.bookings.length) {
        list.innerHTML = '<div style="color:var(--text-dim);padding:24px;text-align:center;">No bookings yet. Add your first stay.</div>';
      } else {
        list.innerHTML = data.bookings.map(b => {
          const color = b.is_profit ? 'var(--accent)' : 'var(--err)';
          return `<div class="card" style="padding:14px 16px;margin-bottom:10px;">
            <div style="display:flex;justify-content:space-between;align-items:flex-start;">
              <div>
                <strong>${_llEsc(b.platform.toUpperCase())}</strong> · ${_llEsc(b.checkin_date || '?')} → ${_llEsc(b.checkout_date || '?')} (${b.nights} nights)
                ${b.guest_name ? '<span style="color:var(--text-dim);"> · ' + _llEsc(b.guest_name) + '</span>' : ''}
              </div>
              <div style="text-align:right;">
                <div style="font-weight:700;color:${color};">${money(b.net_profit)} <span style="font-size:11px;">(${money(b.profit_per_night)}/night)</span></div>
                <button class="btn btn-ghost" style="font-size:11px;padding:2px 8px;margin-top:4px;" onclick="llDeleteBooking(${b.id})">Delete</button>
              </div>
            </div>
            <div style="display:grid;grid-template-columns:repeat(6,1fr);gap:8px;margin-top:8px;font-size:12px;color:var(--text-dim);">
              <div>Gross<br><span style="color:var(--text);">${money(b.gross_payout)}</span></div>
              <div>Fees<br><span style="color:var(--text);">−${money(b.platform_fee)}</span></div>
              <div>Cleaning<br><span style="color:var(--text);">−${money(b.cleaning_cost)}</span></div>
              <div>Supplies<br><span style="color:var(--text);">−${money(b.supplies_cost)}</span></div>
              <div>Utilities<br><span style="color:var(--text);">−${money(b.utilities_est)}</span></div>
              <div>Reserve<br><span style="color:var(--text);">−${money(b.reserve_allocation)}</span></div>
            </div>
          </div>`;
        }).join('');
      }
    }
  } catch (e) {
    if (list) list.innerHTML = '<div style="color:var(--err);padding:16px;">' + _llEsc(e.message) + '</div>';
  }
}

function llShowBookingForm() {
  const f = document.getElementById('ll-str-form');
  if (f) f.style.display = '';
}

function llHideBookingForm() {
  const f = document.getElementById('ll-str-form');
  if (f) f.style.display = 'none';
}

async function llSaveBooking() {
  const val = id => { const el = document.getElementById(id); return el ? el.value.trim() : ''; };
  try {
    await _llPost('/api/landlord/str-bookings', {
      property_id: parseInt(val('ll-str-property'), 10),
      platform: val('ll-str-platform'),
      guest_name: val('ll-str-guest'),
      checkin_date: val('ll-str-checkin'),
      checkout_date: val('ll-str-checkout'),
      gross_payout: val('ll-str-gross') || '0',
      platform_fee: val('ll-str-fee') || '0',
      cleaning_cost: val('ll-str-cleaning') || '0',
      supplies_cost: val('ll-str-supplies') || '0',
      utilities_est: val('ll-str-utilities') || '0',
      reserve_allocation: val('ll-str-reserve') || '0',
    });
    llHideBookingForm();
    ['ll-str-guest','ll-str-checkin','ll-str-checkout','ll-str-gross','ll-str-fee',
     'll-str-cleaning','ll-str-supplies','ll-str-utilities','ll-str-reserve'].forEach(id => {
      const el = document.getElementById(id); if (el) el.value = '';
    });
    await llLoadStrBookings();
  } catch (e) { alert('Could not save booking: ' + e.message); }
}

async function llDeleteBooking(id) {
  if (!confirm('Delete this booking? Its reserve set-aside entry is removed too.')) return;
  try {
    await _llPost('/api/landlord/str-bookings/delete/' + id, {});
    await llLoadStrBookings();
  } catch (e) { alert('Could not delete: ' + e.message); }
}

Object.assign(window, {
  llLoadProperties, llShowPropertyForm, llHidePropertyForm, llEditProperty,
  llSaveProperty, llDeleteProperty, llAddUnit,
  llShowTenantForm, llHideTenantForm, llSaveTenant, llDeleteTenant,
  llShowLeaseForm, llHideLeaseForm, llEditLease, llSaveLease, llDeleteLease,
  llLoadLeasesPanel, llRecordDeposit,
  llLoadRentRoll, llShowPaymentForm, llHidePaymentForm, llSubmitPayment,
  llLoadScheduleE, llDownloadYearEnd,
  llLoadPropertyPnl, llAssignExpense,
  llLoadReserves, llSetReserveTarget, llReserveEntry,
  llLoadOwnerDraw, llLoadFeeLeak,
  llLoadStrBookings, llShowBookingForm, llHideBookingForm, llSaveBooking, llDeleteBooking,
});
