{% extends "dashboard_base.html" %}

{% block title %}Pulse — {{ config.APP_NAME }}{% endblock %}

{% block head %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<style>
/* ── Pulse page ── */
.pulse-masthead {
  margin-bottom: 1.5rem;
  padding-bottom: 1.25rem;
  border-bottom: 1.5px solid var(--color-parchment);
}
.pulse-masthead h1 {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 800;
  color: var(--color-espresso);
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 0 0 0.25rem;
}
.pulse-masthead p {
  font-size: 0.875rem;
  color: var(--color-stone);
}

/* Sparkline grid — auto-fit for 4 or 5 cards */
.spark-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}

.spark-card {
  background: white;
  border: 1px solid var(--color-parchment);
  border-radius: 1.25rem;
  padding: 1.125rem 1.25rem 0.875rem;
  box-shadow: 0 1px 3px rgba(44,24,16,0.05);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.spark-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
}
.spark-title {
  font-family: var(--font-display);
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--color-espresso);
  line-height: 1.2;
}
.spark-detail-link {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--color-copper);
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
}
.spark-detail-link:hover { color: var(--color-copper-hover); }
.spark-chart-wrap {
  position: relative;
  height: 100px;
}
.spark-chart-wrap canvas { max-height: 100px !important; }
.spark-meta {
  font-size: 0.6875rem;
  color: var(--color-stone);
}

@keyframes pulse-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.pulse-in   { animation: pulse-in 0.25s ease both; }
.pulse-in-1 { animation: pulse-in 0.25s 0.05s ease both; }
.pulse-in-2 { animation: pulse-in 0.25s 0.1s ease both; }
.pulse-in-3 { animation: pulse-in 0.25s 0.15s ease both; }
</style>
{% endblock %}

{% block content %}

<!-- Masthead -->
<div class="pulse-masthead pulse-in">
  <h1>Pulse</h1>
  <p>Global coffee market — full picture in 10 seconds{% if user.name %} · Welcome back, {{ user.name }}{% endif %}</p>
</div>

<!-- Metric cards -->
<div class="grid-4 mb-6 pulse-in">
  <div class="metric-card">
    <div class="metric-label">KC=F Close</div>
    <div class="metric-value">
      {% if price_latest %}{{ "{:.2f}".format(price_latest.close) }}{% else %}--{% endif %}
    </div>
    <div class="metric-sub">
      ¢/lb
      {% if price_latest and price_latest.daily_return_pct is not none %}
      · <span class="{% if price_latest.daily_return_pct > 0 %}text-bean-green{% elif price_latest.daily_return_pct < 0 %}text-danger{% endif %}">{{ "{:+.2f}%".format(price_latest.daily_return_pct) }}</span>
      {% endif %}
      {% if price_latest %} · {{ price_latest.trade_date }}{% endif %}
    </div>
  </div>

  <div class="metric-card">
    <div class="metric-label">MM Net Position</div>
    <div class="metric-value {% if cot_latest and cot_latest.managed_money_net > 0 %}text-bean-green{% elif cot_latest and cot_latest.managed_money_net < 0 %}text-danger{% endif %}">
      {% if cot_latest %}{{ "{:+,d}".format(cot_latest.managed_money_net | int) }}{% else %}--{% endif %}
    </div>
    <div class="metric-sub">contracts · {% if cot_latest %}COT Index {{ "{:.0f}".format(cot_latest.cot_index_26w) }}/100 · {{ cot_latest.report_date }}{% else %}CFTC COT{% endif %}</div>
  </div>

  <div class="metric-card">
    <div class="metric-label">Certified Stocks</div>
    <div class="metric-value">
      {% if ice_stocks_latest %}{{ "{:,.0f}".format(ice_stocks_latest.total_certified_bags) }}{% else %}--{% endif %}
    </div>
    <div class="metric-sub">
      60-kg bags
      {% if ice_stocks_latest and ice_stocks_latest.wow_change_bags is not none %}
      · <span class="{% if ice_stocks_latest.wow_change_bags > 0 %}text-bean-green{% elif ice_stocks_latest.wow_change_bags < 0 %}text-danger{% endif %}">{{ "{:+,d}".format(ice_stocks_latest.wow_change_bags | int) }} WoW</span>
      {% endif %}
      {% if ice_stocks_latest %} · {{ ice_stocks_latest.report_date }}{% endif %}
    </div>
  </div>

  <div class="metric-card">
    <div class="metric-label">Stock-to-Use Ratio</div>
    <div class="metric-value">
      {% if stu_latest %}{{ "{:.1f}".format(stu_latest.stock_to_use_ratio_pct) }}%{% else %}--{% endif %}
    </div>
    <div class="metric-sub">ending stocks / consumption{% if stu_latest %} · {{ stu_latest.market_year }}{% endif %}</div>
  </div>

  <div class="metric-card">
    <div class="metric-label">Crop Stress Index</div>
    <div class="metric-value {% if weather_stress_latest and weather_stress_latest.avg_crop_stress_index > 40 %}text-danger{% elif weather_stress_latest and weather_stress_latest.avg_crop_stress_index > 20 %}text-copper{% else %}text-bean-green{% endif %}">
      {% if weather_stress_latest %}{{ "{:.0f}".format(weather_stress_latest.avg_crop_stress_index) }}/100{% else %}--{% endif %}
    </div>
    <div class="metric-sub">
      avg · {% if weather_stress_latest %}{{ weather_stress_latest.locations_under_stress }} stressed{% endif %}
      {% if weather_stress_latest %} · {{ weather_stress_latest.observation_date }}{% endif %}
    </div>
  </div>
</div>

<!-- Freshness bar -->
<div class="freshness-bar pulse-in-1">
  <span style="font-size:0.75rem;font-weight:600;color:var(--color-stone);text-transform:uppercase;letter-spacing:0.06em;">Data as of:</span>
  <a href="{{ url_for('public.methodology') }}" class="freshness-badge">
    <strong>USDA PSD</strong> {% if stu_latest %}{{ stu_latest.market_year }}{% else %}—{% endif %}
  </a>
  <a href="{{ url_for('public.methodology') }}" class="freshness-badge">
    <strong>CFTC COT</strong> {% if cot_latest %}{{ cot_latest.report_date }}{% else %}—{% endif %}
  </a>
  <a href="{{ url_for('public.methodology') }}" class="freshness-badge">
    <strong>KC=F Price</strong> {% if price_latest %}{{ price_latest.trade_date }}{% else %}—{% endif %}
  </a>
  <a href="{{ url_for('public.methodology') }}" class="freshness-badge">
    <strong>ICE Stocks</strong> {% if ice_stocks_latest %}{{ ice_stocks_latest.report_date }}{% else %}—{% endif %}
  </a>
  <a href="{{ url_for('dashboard.weather') }}" class="freshness-badge">
    <strong>Weather</strong> {% if weather_stress_latest %}{{ weather_stress_latest.observation_date }}{% else %}—{% endif %}
  </a>
</div>

<!-- 2×2 sparkline grid -->
<div class="spark-grid pulse-in-2">

  <!-- Price 90d -->
  <div class="spark-card">
    <div class="spark-card-head">
      <div class="spark-title">KC=F Price — 90 days</div>
      <a href="{{ url_for('dashboard.positioning') }}" class="spark-detail-link">View details →</a>
    </div>
    <div class="spark-chart-wrap">
      <canvas id="sparkPrice"></canvas>
    </div>
    <div class="spark-meta">ICE Coffee C Arabica · ¢/lb daily close</div>
  </div>

  <!-- ICE Stocks 90d -->
  <div class="spark-card">
    <div class="spark-card-head">
      <div class="spark-title">ICE Certified Stocks — 90 days</div>
      <a href="{{ url_for('dashboard.warehouse') }}" class="spark-detail-link">View details →</a>
    </div>
    <div class="spark-chart-wrap">
      <canvas id="sparkStocks"></canvas>
    </div>
    <div class="spark-meta">Physical Arabica certified for delivery · 60-kg bags</div>
  </div>

  <!-- COT 26 weeks -->
  <div class="spark-card">
    <div class="spark-card-head">
      <div class="spark-title">COT Index — 26 weeks</div>
      <a href="{{ url_for('dashboard.positioning') }}" class="spark-detail-link">View details →</a>
    </div>
    <div class="spark-chart-wrap">
      <canvas id="sparkCot"></canvas>
    </div>
    <div class="spark-meta">CFTC Managed Money net position · 0 = max bearish · 100 = max bullish</div>
  </div>

  <!-- Supply/Demand 5yr -->
  <div class="spark-card">
    <div class="spark-card-head">
      <div class="spark-title">Global Supply &amp; Demand — 5 years</div>
      <a href="{{ url_for('dashboard.supply') }}" class="spark-detail-link">View details →</a>
    </div>
    <div class="spark-chart-wrap">
      <canvas id="sparkSupply"></canvas>
    </div>
    <div class="spark-meta">USDA WASDE · 1,000 60-kg bags · production vs distribution</div>
  </div>

  <!-- Weather Crop Stress 90d -->
  <div class="spark-card">
    <div class="spark-card-head">
      <div class="spark-title">Crop Stress Index — 90 days</div>
      <a href="{{ url_for('dashboard.weather') }}" class="spark-detail-link">View details →</a>
    </div>
    <div class="spark-chart-wrap">
      <canvas id="sparkWeather"></canvas>
    </div>
    <div class="spark-meta">Open-Meteo ERA5 · avg across 12 origins · 0 = no stress · 100 = severe</div>
  </div>

</div>

{% if plan == "free" %}
<div class="plan-gate mt-6 pulse-in-3">
  Free plan shows limited history. <a href="{{ url_for('billing.pricing') }}">Upgrade</a> for full historical depth on all pages.
</div>
{% endif %}

{% endblock %}

{% block scripts %}
<script>
(function () {
  const C = {
    copper: '#B45309', green: '#15803D', roast: '#4A2C1A', stone: '#78716C',
    parchment: '#E8DFD5', espresso: '#2C1810',
  };

  function sparkOpts(color, filled) {
    return {
      responsive: true,
      maintainAspectRatio: false,
      animation: { duration: 400 },
      interaction: { mode: 'index', intersect: false },
      plugins: { legend: { display: false }, tooltip: { enabled: false } },
      elements: { point: { radius: 0 } },
      scales: {
        x: { display: false },
        y: {
          display: false,
          grace: '10%',
        },
      },
    };
  }

  // Price sparkline (90d)
  var priceRaw = {{ price_series | tojson }};
  if (priceRaw && priceRaw.length > 0) {
    var priceAsc = priceRaw.slice().reverse();
    new Chart(document.getElementById('sparkPrice'), {
      type: 'line',
      data: {
        labels: priceAsc.map(function (r) { return r.trade_date; }),
        datasets: [{
          data: priceAsc.map(function (r) { return r.close; }),
          borderColor: C.copper,
          backgroundColor: C.copper + '22',
          fill: true,
          tension: 0.3,
          borderWidth: 2,
        }],
      },
      options: sparkOpts(C.copper, true),
    });
  }

  // ICE Stocks sparkline (90d)
  var stocksRaw = {{ ice_stocks_trend | tojson }};
  if (stocksRaw && stocksRaw.length > 0) {
    var stocksAsc = stocksRaw.slice().reverse();
    new Chart(document.getElementById('sparkStocks'), {
      type: 'line',
      data: {
        labels: stocksAsc.map(function (r) { return r.report_date; }),
        datasets: [{
          data: stocksAsc.map(function (r) { return r.total_certified_bags; }),
          borderColor: C.roast,
          backgroundColor: C.roast + '22',
          fill: true,
          tension: 0.3,
          borderWidth: 2,
        }],
      },
      options: sparkOpts(C.roast, true),
    });
  }

  // COT sparkline (26w)
  var cotRaw = {{ cot_trend | tojson }};
  if (cotRaw && cotRaw.length > 0) {
    var cotAsc = cotRaw.slice().reverse();
    new Chart(document.getElementById('sparkCot'), {
      type: 'line',
      data: {
        labels: cotAsc.map(function (r) { return r.report_date; }),
        datasets: [{
          data: cotAsc.map(function (r) { return r.managed_money_net; }),
          borderColor: C.green,
          backgroundColor: C.green + '22',
          fill: true,
          tension: 0.3,
          borderWidth: 2,
        }],
      },
      options: sparkOpts(C.green, true),
    });
  }

  // Supply/Demand sparkline (5yr)
  var supplyRaw = {{ time_series | tojson }};
  if (supplyRaw && supplyRaw.length > 0) {
    new Chart(document.getElementById('sparkSupply'), {
      type: 'line',
      data: {
        labels: supplyRaw.map(function (r) { return r.market_year; }),
        datasets: [
          {
            label: 'Production',
            data: supplyRaw.map(function (r) { return r.production; }),
            borderColor: C.copper,
            tension: 0.3,
            borderWidth: 2,
            fill: false,
          },
          {
            label: 'Distribution',
            data: supplyRaw.map(function (r) { return r.total_distribution; }),
            borderColor: C.roast,
            borderDash: [4, 3],
            tension: 0.3,
            borderWidth: 2,
            fill: false,
          },
        ],
      },
      options: sparkOpts(C.copper, false),
    });
  }

  // Weather crop stress sparkline (90d)
  var weatherRaw = {{ weather_stress_trend | tojson }};
  if (weatherRaw && weatherRaw.length > 0) {
    var weatherAsc = weatherRaw.slice().reverse();
    new Chart(document.getElementById('sparkWeather'), {
      type: 'line',
      data: {
        labels: weatherAsc.map(function (r) { return r.observation_date; }),
        datasets: [{
          data: weatherAsc.map(function (r) { return r.avg_crop_stress_index; }),
          borderColor: C.copper,
          backgroundColor: C.copper + '22',
          fill: true,
          tension: 0.3,
          borderWidth: 2,
        }],
      },
      options: sparkOpts(C.copper, true),
    });
  }
}());
</script>
{% endblock %}
