import type { CommandBus } from '@application/handlers/CommandBus';
import type { QueryBus } from '@application/handlers/QueryBus';
import type { StatisticsResult, KpiDelta } from '@application/queries/GetStatistics';
import { TOTAL_RACES } from '@application/queries/GetStatistics';
import { GEN_COLORS, raceColor } from '@domain/value-objects/Race';
import { getDDImage } from '@presentation/helpers/dd-image';
import { esc } from '@presentation/helpers/format';

const PERIOD_OPTIONS = [
  { days: 7,  label: '7 jours' },
  { days: 14, label: '14 jours' },
  { days: 30, label: '30 jours' },
  { days: 90, label: '3 mois' },
  { days: 0,  label: 'Tout' },
];

export class StatistiquesView {
  private el: HTMLElement | null = null;
  private selectedDays = 30;

  constructor(
    private commandBus: CommandBus,
    private queryBus: QueryBus,
  ) {}

  render(container: HTMLElement): void {
    this.el = document.createElement('div');
    this.el.className = 'stats-view';
    container.appendChild(this.el);
    this.renderAll();
  }

  update(): void {}

  destroy(): void {
    this.el?.remove();
    this.el = null;
  }

  private getData(): StatisticsResult {
    return this.queryBus.execute<StatisticsResult>({ type: 'get-statistics', days: this.selectedDays });
  }

  private renderAll(): void {
    if (!this.el) return;
    const data = this.getData();

    let html = '';

    // ── Hero + Filtres ──────────────────────────────────────────
    html += `<div class="stats-hero">
      <div>
        <h2 class="stats-hero-title">Statistiques d'\u00c9levage</h2>
        <p class="stats-hero-sub">Aperçu analytique des performances de votre archive.</p>
      </div>
      <div class="stats-period-chips">`;
    for (const opt of PERIOD_OPTIONS) {
      const active = this.selectedDays === opt.days ? ' active' : '';
      html += `<button class="stats-period-chip${active}" data-days="${opt.days}">${esc(opt.label)}</button>`;
    }
    html += `</div></div>`;

    // ── KPIs ────────────────────────────────────────────────────
    html += `<div class="stats-kpi-grid">`;
    html += this.renderKpi('Total Naissances', data.totalBabies, 'egg_alt');
    html += this.renderKpi('Taux de R\u00e9ussite', data.successRate, 'trending_up', '%');
    html += this.renderKpi('Couples Form\u00e9s', data.totalCouples, 'favorite');
    html += this.renderKpiRaces(data.racesCount);
    html += `</div>`;

    // ── Graphique naissances + Donut ─────────────────────────────
    html += `<div class="stats-two-col">`;
    html += this.renderBarChart(data);
    html += this.renderRaceDistribution(data);
    html += `</div>`;

    // ── Répartition par génération + Activité semaine ────────────
    html += `<div class="stats-two-col">`;
    html += this.renderGenBreakdown(data);
    html += this.renderWeekdayActivity(data);
    html += `</div>`;

    // ── Détail par race ──────────────────────────────────────────
    html += this.renderRaceDetail(data);

    // ── Taux de réussite par race ────────────────────────────────
    html += this.renderRaceSuccessRates(data);

    // ── Meilleurs couples ────────────────────────────────────────
    html += this.renderBestCouples(data);

    // ── Races manquantes (toujours en dernier) ───────────────────
    html += this.renderMissingRaces(data);

    this.el.innerHTML = html;
    this.bindEvents();
  }

  // ── KPIs ──────────────────────────────────────────────────────

  private renderKpi(label: string, kpi: KpiDelta, icon: string, suffix = ''): string {
    return `<div class="stats-kpi-card">
      <div class="stats-kpi-icon-wrap">
        <span class="material-symbols-outlined stats-kpi-icon">${icon}</span>
      </div>
      <p class="stats-kpi-label">${label}</p>
      <div class="stats-kpi-row">
        <span class="stats-kpi-value">${kpi.value}${suffix}</span>
        ${this.deltaTag(kpi.delta, suffix)}
      </div>
    </div>`;
  }

  private renderKpiRaces(kpi: KpiDelta): string {
    return `<div class="stats-kpi-card">
      <div class="stats-kpi-icon-wrap">
        <span class="material-symbols-outlined stats-kpi-icon">pets</span>
      </div>
      <p class="stats-kpi-label">Races Obtenues</p>
      <div class="stats-kpi-row">
        <span class="stats-kpi-value">${kpi.value}<span class="stats-kpi-total">/${TOTAL_RACES}</span></span>
        ${this.deltaTag(kpi.delta)}
      </div>
    </div>`;
  }

  private deltaTag(delta: number | null, suffix = ''): string {
    if (delta === null) return '';
    if (delta === 0) return `<span class="stats-delta stats-delta-neutral">= 0${suffix}</span>`;
    const sign = delta > 0 ? '+' : '';
    const cls = delta > 0 ? 'stats-delta-up' : 'stats-delta-down';
    return `<span class="stats-delta ${cls}">${sign}${delta}${suffix}</span>`;
  }

  // ── Graphique barres ──────────────────────────────────────────

  private renderBarChart(data: StatisticsResult): string {
    const maxCount = Math.max(...data.dailyBirths.map(d => d.count), 1);
    const hasData = data.dailyBirths.some(d => d.count > 0);
    const periodLabel = this.selectedDays === 0 ? '30 DERNIERS JOURS' : `${this.selectedDays} DERNIERS JOURS`;

    let html = `<div class="stats-chart-panel">
      <div class="stats-chart-header">
        <h3 class="stats-chart-title">\u00c9volution des Naissances</h3>
        <span class="stats-chart-badge">${periodLabel}</span>
      </div>`;

    if (!hasData) {
      html += `<div class="stats-chart-empty">
        <span class="material-symbols-outlined" style="font-size:40px;color:var(--md-outline-variant)">bar_chart</span>
        <p>Aucune naissance sur cette p\u00e9riode</p>
      </div>`;
    } else {
      html += `<div class="stats-chart-area">`;
      html += `<div class="stats-chart-y-axis">
        <span>${maxCount}</span>
        <span>${Math.round(maxCount / 2)}</span>
        <span>0</span>
      </div>`;
      html += `<div class="stats-chart-bars">`;
      for (const day of data.dailyBirths) {
        const pct = (day.count / maxCount) * 100;
        const isToday = day === data.dailyBirths[data.dailyBirths.length - 1];
        html += `<div class="stats-bar-col">
          <div class="stats-tooltip">${day.label}<br><strong>${day.count}</strong> naissance${day.count !== 1 ? 's' : ''}</div>
          <div class="stats-bar${isToday ? ' stats-bar-today' : ''}" style="height:${Math.max(pct, day.count > 0 ? 4 : 0)}%"></div>
        </div>`;
      }
      html += `</div>`;
      const step = Math.max(1, Math.floor(data.dailyBirths.length / 6));
      html += `<div class="stats-chart-x-axis">`;
      for (let i = 0; i < data.dailyBirths.length; i++) {
        if (i % step === 0 || i === data.dailyBirths.length - 1) {
          html += `<span>${data.dailyBirths[i].label}</span>`;
        }
      }
      html += `</div></div>`;
    }

    html += `</div>`;
    return html;
  }

  // ── Donut races ───────────────────────────────────────────────

  private renderRaceDistribution(data: StatisticsResult): string {
    const top = data.raceShares.slice(0, 8);

    let html = `<div class="stats-race-panel">
      <h3 class="stats-chart-title">R\u00e9partition des Races</h3>`;

    if (top.length === 0) {
      html += `<div class="stats-chart-empty">
        <span class="material-symbols-outlined" style="font-size:40px;color:var(--md-outline-variant)">donut_large</span>
        <p>Aucune race enregistr\u00e9e</p>
      </div>`;
    } else {
      html += `<div class="stats-donut-wrap">
        <div class="stats-donut-center">
          <span class="stats-donut-num">${data.racesCount.value}</span>
          <span class="stats-donut-label">RACES</span>
        </div>
        ${this.renderDonutSVG(top)}
      </div>`;
      html += `<div class="stats-race-legend">`;
      for (const r of top) {
        const col = raceColor(r.race);
        html += `<div class="stats-race-legend-row">
          <div class="stats-race-legend-left">
            <span class="stats-race-dot" style="background:${esc(col)}"></span>
            <span class="stats-race-name">${esc(r.race)}</span>
          </div>
          <div class="stats-race-legend-right">
            <span class="stats-race-count">${r.count}</span>
            <span class="stats-race-pct">${r.pct}%</span>
          </div>
        </div>`;
      }
      if (data.raceShares.length > 8) {
        const otherCount = data.raceShares.slice(8).reduce((s, r) => s + r.count, 0);
        const otherPct = data.totalBabies.value > 0 ? Math.round((otherCount / data.totalBabies.value) * 100) : 0;
        html += `<div class="stats-race-legend-row">
          <div class="stats-race-legend-left">
            <span class="stats-race-dot" style="background:var(--md-outline-variant)"></span>
            <span class="stats-race-name">Autres (${data.raceShares.length - 8})</span>
          </div>
          <div class="stats-race-legend-right">
            <span class="stats-race-count">${otherCount}</span>
            <span class="stats-race-pct">${otherPct}%</span>
          </div>
        </div>`;
      }
      html += `</div>`;
    }

    html += `</div>`;
    return html;
  }

  private renderDonutSVG(shares: { race: string; pct: number; count: number }[]): string {
    const r = 60, circ = 2 * Math.PI * r, gap = 2;
    let offset = 0;
    let arcs = '';
    for (const s of shares) {
      const col = raceColor(s.race);
      const len = Math.max((s.pct / 100) * circ - gap, 0);
      arcs += `<circle class="stats-donut-arc" cx="75" cy="75" r="${r}" fill="none"
        stroke="${col}" stroke-width="14"
        stroke-dasharray="${len} ${circ - len}" stroke-dashoffset="${-offset}"
        stroke-linecap="round" transform="rotate(-90 75 75)">
        <title>${esc(s.race)} — ${s.count} (${s.pct}%)</title>
      </circle>`;
      offset += len + gap;
    }
    return `<svg class="stats-donut-svg" viewBox="0 0 150 150" width="150" height="150">${arcs}</svg>`;
  }

  // ── Répartition par génération ─────────────────────────────────

  private renderGenBreakdown(data: StatisticsResult): string {
    let html = `<div class="stats-chart-panel">
      <div class="stats-chart-header">
        <h3 class="stats-chart-title">Naissances par G\u00e9n\u00e9ration</h3>
      </div>`;

    if (data.genBreakdown.length === 0) {
      html += `<div class="stats-chart-empty">
        <span class="material-symbols-outlined" style="font-size:40px;color:var(--md-outline-variant)">genetics</span>
        <p>Aucune donn\u00e9e</p>
      </div>`;
    } else {
      const maxBabies = Math.max(...data.genBreakdown.map(g => g.babies), 1);
      html += `<div class="stats-gen-bars">`;
      for (const g of data.genBreakdown) {
        const col = GEN_COLORS[g.gen] ?? '#888';
        const pct = (g.babies / maxBabies) * 100;
        const rate = g.couples > 0 ? Math.round((g.babies / g.couples) * 100) : 0;
        html += `<div class="stats-gen-row">
          <span class="stats-gen-label" style="color:${esc(col)}">Gen ${g.gen}</span>
          <div class="stats-gen-bar-wrap">
            <div class="stats-gen-bar" style="width:${pct}%;background:${esc(col)}"></div>
          </div>
          <div class="stats-gen-info">
            <span class="stats-gen-count">${g.babies}</span>
            <span class="stats-gen-rate">${rate}%</span>
            <span class="stats-gen-races">${g.races} race${g.races > 1 ? 's' : ''}</span>
          </div>
        </div>`;
      }
      html += `</div>`;
    }

    html += `</div>`;
    return html;
  }

  // ── Activité par jour de la semaine ────────────────────────────

  private renderWeekdayActivity(data: StatisticsResult): string {
    const maxCount = Math.max(...data.weekdayActivity.map(d => d.count), 1);
    const hasData = data.weekdayActivity.some(d => d.count > 0);

    let html = `<div class="stats-race-panel">
      <h3 class="stats-chart-title">Activit\u00e9 par Jour</h3>`;

    if (!hasData) {
      html += `<div class="stats-chart-empty">
        <span class="material-symbols-outlined" style="font-size:40px;color:var(--md-outline-variant)">calendar_month</span>
        <p>Aucune activit\u00e9</p>
      </div>`;
    } else {
      html += `<div class="stats-weekday-grid">`;
      for (const w of data.weekdayActivity) {
        const pct = (w.count / maxCount) * 100;
        const intensity = Math.min(pct / 100, 1);
        const bg = `rgba(157, 120, 255, ${0.1 + intensity * 0.6})`;
        html += `<div class="stats-weekday-item">
          <span class="stats-weekday-name">${w.day.slice(0, 3)}</span>
          <div class="stats-weekday-block" style="background:${bg}" title="${w.day} : ${w.count} naissance${w.count !== 1 ? 's' : ''}">
            <span class="stats-weekday-count">${w.count}</span>
          </div>
        </div>`;
      }
      html += `</div>`;
    }

    html += `</div>`;
    return html;
  }

  // ── Taux de réussite par race ──────────────────────────────────

  private renderRaceSuccessRates(data: StatisticsResult): string {
    if (data.raceSuccessRates.length === 0) return '';

    let html = `<div class="stats-history-panel">
      <div class="stats-chart-header">
        <h3 class="stats-chart-title">Taux de R\u00e9ussite par Race</h3>
        <span class="stats-chart-badge">${data.raceSuccessRates.length} RACES</span>
      </div>
      <div class="stats-success-grid">`;

    for (const r of data.raceSuccessRates) {
      const col = raceColor(r.race);
      const rateClass = r.rate >= 80 ? 'stats-rate-high' : r.rate >= 50 ? 'stats-rate-mid' : 'stats-rate-low';
      html += `<div class="stats-success-row">
        <div class="stats-success-race">
          <div class="stats-success-avatar">${getDDImage(r.race)}</div>
          <span class="stats-success-name" style="color:${esc(col)}">${esc(r.race)}</span>
        </div>
        <div class="stats-success-bar-wrap">
          <div class="stats-success-bar" style="width:${r.rate}%;background:${esc(col)}"></div>
        </div>
        <span class="stats-success-rate ${rateClass}">${r.rate}%</span>
        <span class="stats-success-detail">${r.babies}/${r.couples}</span>
      </div>`;
    }

    html += `</div></div>`;
    return html;
  }

  // ── Meilleurs couples ──────────────────────────────────────────

  private renderBestCouples(data: StatisticsResult): string {
    if (data.bestCouples.length === 0) return '';

    let html = `<div class="stats-history-panel">
      <div class="stats-chart-header">
        <h3 class="stats-chart-title">Meilleurs Couples</h3>
        <span class="stats-chart-badge">TOP ${data.bestCouples.length}</span>
      </div>
      <div class="stats-couples-grid">`;

    for (let i = 0; i < data.bestCouples.length; i++) {
      const c = data.bestCouples[i];
      const babyCol = raceColor(c.baby);
      const rateClass = c.rate >= 80 ? 'stats-rate-high' : c.rate >= 50 ? 'stats-rate-mid' : 'stats-rate-low';
      html += `<div class="stats-couple-row">
        <span class="stats-couple-rank">#${i + 1}</span>
        <div class="stats-couple-parents">
          <div class="stats-couple-av">${getDDImage(c.parentA)}</div>
          <span class="material-symbols-outlined" style="font-size:14px;color:var(--md-outline-variant)">add</span>
          <div class="stats-couple-av">${getDDImage(c.parentB)}</div>
        </div>
        <span class="material-symbols-outlined" style="font-size:20px;color:var(--md-primary)">arrow_forward</span>
        <div class="stats-couple-baby">
          <div class="stats-couple-baby-av">${getDDImage(c.baby)}</div>
          <span style="color:${esc(babyCol)};font-weight:600;font-size:13px">${esc(c.baby)}</span>
        </div>
        <span class="stats-couple-rate ${rateClass}">${c.rate}%</span>
        <span class="stats-couple-detail">${c.babies}/${c.couples}</span>
      </div>`;
    }

    html += `</div></div>`;
    return html;
  }

  // ── Races manquantes ───────────────────────────────────────────

  private renderMissingRaces(data: StatisticsResult): string {
    if (data.missingRaces.length === 0) {
      return `<div class="stats-history-panel">
        <div class="stats-chart-header">
          <h3 class="stats-chart-title">Races Manquantes</h3>
          <span class="stats-chart-badge stats-badge-success">COMPLET !</span>
        </div>
        <div class="stats-chart-empty">
          <span class="material-symbols-outlined" style="font-size:48px;color:#22c55e">check_circle</span>
          <p style="color:#22c55e;font-weight:600">Toutes les ${TOTAL_RACES} races ont \u00e9t\u00e9 obtenues !</p>
        </div>
      </div>`;
    }

    // Grouper par génération
    const byGen = new Map<number, typeof data.missingRaces>();
    for (const r of data.missingRaces) {
      if (!byGen.has(r.gen)) byGen.set(r.gen, []);
      byGen.get(r.gen)!.push(r);
    }

    let html = `<div class="stats-history-panel">
      <div class="stats-chart-header">
        <h3 class="stats-chart-title">Races Manquantes</h3>
        <span class="stats-chart-badge">${data.missingRaces.length} / ${TOTAL_RACES} RESTANTES</span>
      </div>
      <div class="stats-missing-list">`;

    for (const [gen, races] of Array.from(byGen.entries()).sort((a, b) => a[0] - b[0])) {
      const genCol = GEN_COLORS[gen] ?? '#888';
      html += `<div class="stats-missing-gen">
        <span class="stats-missing-gen-badge" style="background:${esc(genCol)}">Gen ${gen}</span>
        <div class="stats-missing-races">`;
      for (const r of races) {
        const col = raceColor(r.name);
        html += `<div class="stats-missing-card">
          <div class="stats-missing-av">${getDDImage(r.name)}</div>
          <span class="stats-missing-name" style="color:${esc(col)}">${esc(r.name)}</span>
        </div>`;
      }
      html += `</div></div>`;
    }

    html += `</div></div>`;
    return html;
  }

  // ── Détail par race (barres horizontales) ──────────────────────

  private renderRaceDetail(data: StatisticsResult): string {
    if (data.raceShares.length === 0) return '';

    const maxCount = data.raceShares[0].count;

    let html = `<div class="stats-history-panel">
      <div class="stats-chart-header">
        <h3 class="stats-chart-title">D\u00e9tail par Race</h3>
        <span class="stats-chart-badge">${data.raceShares.length} / ${TOTAL_RACES} RACES</span>
      </div>
      <div class="stats-race-bars">`;

    for (const r of data.raceShares) {
      const col = raceColor(r.race);
      const pct = maxCount > 0 ? (r.count / maxCount) * 100 : 0;
      html += `<div class="stats-race-bar-row">
        <span class="stats-race-bar-name" style="color:${esc(col)}">${esc(r.race)}</span>
        <div class="stats-race-bar-track">
          <div class="stats-race-bar-fill" style="width:${pct}%;background:${esc(col)}"></div>
        </div>
        <span class="stats-race-bar-count">${r.count}</span>
      </div>`;
    }

    html += `</div></div>`;
    return html;
  }

  // ── Events ────────────────────────────────────────────────────

  private bindEvents(): void {
    if (!this.el) return;
    this.el.querySelectorAll<HTMLElement>('.stats-period-chip').forEach(chip => {
      chip.addEventListener('click', () => {
        this.selectedDays = Number(chip.dataset['days']);
        this.renderAll();
      });
    });
  }
}
