<template>
  <!-- Inhalt für DialogManager: Rahmen, Minimieren und Schließen liefert der Manager -->
  <div v-if="!clubId" class="internal-tournament-stats internal-tournament-stats--embed stats-no-club">
    <p class="stats-empty">{{ $t('club.selectPlaceholder') }}</p>
  </div>
  <div v-else class="internal-tournament-stats internal-tournament-stats--embed">
      <div class="stats-toolbar">
        <button
          type="button"
          class="pdf-button"
          :disabled="pdfDisabled"
          @click="exportPdf"
        >
          {{ $t('tournaments.internalStatsExportPdf') }}
        </button>
        <label class="period-label">
          <span>{{ $t('tournaments.internalStatsPeriod') }}</span>
          <select v-model="months" @change="onMonthsChange" :disabled="loading">
            <option :value="12">{{ $t('tournaments.internalStatsLast12Months') }}</option>
            <option :value="6">{{ $t('tournaments.internalStatsLast6Months') }}</option>
            <option :value="3">{{ $t('tournaments.internalStatsLast3Months') }}</option>
          </select>
        </label>
      </div>
      <p class="stats-meta">
        {{ $t('tournaments.internalStatsTournamentsInPeriod', { count: stats.tournamentCount || 0 }) }}
      </p>
      <p class="stats-explain">{{ $t('tournaments.internalStatsPointsExplain') }}</p>

      <fieldset v-if="bandOptions.length" class="age-filter">
        <legend class="age-filter-legend">{{ $t('tournaments.internalStatsAgeFilter') }}</legend>
        <div class="age-filter-actions">
          <button type="button" class="age-filter-link" @click="selectAllAgeKeys" :disabled="loading">
            {{ $t('tournaments.internalStatsAgeSelectAll') }}
          </button>
          <button type="button" class="age-filter-link" @click="selectNoAgeKeys" :disabled="loading">
            {{ $t('tournaments.internalStatsAgeSelectNone') }}
          </button>
        </div>
        <div class="age-filter-columns">
          <div class="age-filter-column">
            <div class="age-filter-column-title">{{ $t('tournaments.internalStatsFilterAgeBands') }}</div>
            <div class="age-filter-checkboxes">
              <label v-for="b in bandOptions" :key="'b-' + b.bandKey" class="age-filter-item">
                <input
                  type="checkbox"
                  :checked="selectedBandKeys.includes(b.bandKey)"
                  :disabled="loading"
                  @change="onBandCheckboxChange(b.bandKey, $event.target.checked)"
                />
                <span>{{ formatBandOnly(b) }}</span>
              </label>
            </div>
          </div>
          <div class="age-filter-column">
            <div class="age-filter-column-title">{{ $t('tournaments.internalStatsFilterGenderColumn') }}</div>
            <label class="gender-select-label">
              <select
                v-model="genderScope"
                class="gender-scope-select"
                :disabled="loading"
                @change="onGenderScopeChange"
              >
                <option value="all">{{ $t('tournaments.internalStatsGenderScopeAll') }}</option>
                <option value="female">{{ $t('tournaments.internalStatsGenderScopeGirls') }}</option>
              </select>
            </label>
          </div>
        </div>
      </fieldset>

      <div v-if="loading" class="stats-loading">{{ $t('common.loading') }}</div>
      <div v-else-if="error" class="stats-error">{{ error }}</div>
      <div v-else class="stats-grid">
        <div class="stats-column">
          <h4>{{ $t('tournaments.internalStatsAbsoluteRank') }}</h4>
          <table class="stats-table">
            <thead>
              <tr>
                <th class="col-rank">#</th>
                <th>{{ $t('tournaments.player') }}</th>
                <th>{{ $t('tournaments.internalStatsPoints') }}</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(row, i) in stats.absoluteRanking" :key="'a-' + row.memberId">
                <td class="col-rank">{{ i + 1 }}</td>
                <td>{{ row.firstName }} {{ row.lastName }}</td>
                <td>{{ formatTotal(row.totalPoints) }}</td>
              </tr>
            </tbody>
          </table>
          <p v-if="!stats.absoluteRanking?.length" class="stats-empty">{{ $t('tournaments.internalStatsEmpty') }}</p>
        </div>
        <div class="stats-column">
          <h4>{{ $t('tournaments.internalStatsAverageRank') }}</h4>
          <table class="stats-table">
            <thead>
              <tr>
                <th class="col-rank">#</th>
                <th>{{ $t('tournaments.player') }}</th>
                <th>{{ $t('tournaments.internalStatsAvgPoints') }}</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(row, i) in stats.averageRanking" :key="'v-' + row.memberId">
                <td class="col-rank">{{ i + 1 }}</td>
                <td>{{ row.firstName }} {{ row.lastName }}</td>
                <td>{{ formatAvg(row.averagePoints) }}</td>
              </tr>
            </tbody>
          </table>
          <p v-if="!stats.averageRanking?.length" class="stats-empty">{{ $t('tournaments.internalStatsEmpty') }}</p>
        </div>
      </div>
    </div>
</template>

<script>
import { mapState } from 'vuex';
import jsPDF from 'jspdf';
import autoTable from 'jspdf-autotable';
import apiClient from '../../apiClient.js';

export default {
  name: 'InternalTournamentStats',
  data() {
    return {
      months: 12,
      loading: false,
      error: null,
      stats: {
        tournamentCount: 0,
        ageClassOptions: [],
        absoluteRanking: [],
        averageRanking: [],
      },
      /** '9'|'11'|…|'19'|'adult' */
      selectedBandKeys: [],
      /** 'all' = weiblich + offen; 'female' = nur Mädchen/Weiblich-Kanal */
      genderScope: 'all',
      ageFilterInitialized: false,
      pendingResetAgeSelection: false,
    };
  },
  computed: {
    ...mapState({
      clubId: (state) => state.currentClub,
    }),
    pdfDisabled() {
      return (
        this.loading ||
        !!this.error ||
        (!this.stats.absoluteRanking?.length && !this.stats.averageRanking?.length)
      );
    },
    /** Eine Zeile pro Altersband (ohne Geschlecht), sortiert J9 … Erwachsene */
    bandOptions() {
      const opts = this.stats.ageClassOptions || [];
      const byKey = new Map();
      for (const o of opts) {
        if (!o || o.isNoClass) continue;
        const bandKey = o.band === 'adult' ? 'adult' : String(o.bandNum);
        if (!byKey.has(bandKey)) {
          byKey.set(bandKey, {
            bandKey,
            band: o.band,
            bandNum: o.bandNum,
            sortKey: o.band === 'adult' ? 1000 : Number(o.bandNum) || 0,
          });
        }
      }
      return [...byKey.values()].sort((a, b) => a.sortKey - b.sortKey);
    },
    effectiveGenderModes() {
      return this.genderScope === 'female' ? ['female'] : ['female', 'open'];
    },
    effectiveAgeClassKeys() {
      const opts = this.stats.ageClassOptions || [];
      const valid = new Set(opts.map((o) => o.key));
      const keys = [];
      for (const bk of this.selectedBandKeys) {
        for (const g of this.effectiveGenderModes) {
          const key = bk === 'adult' ? `tt|adult|${g}` : `tt|${bk}|${g}`;
          if (valid.has(key)) keys.push(key);
        }
      }
      return keys;
    },
  },
  watch: {
    clubId() {
      this.ageFilterInitialized = false;
      this.selectedBandKeys = [];
      this.genderScope = 'all';
      this.pendingResetAgeSelection = false;
      if (this.clubId) this.load();
    },
  },
  mounted() {
    if (this.clubId) this.load();
  },
  methods: {
    periodLabel() {
      const key =
        this.months === 12
          ? 'internalStatsLast12Months'
          : this.months === 6
            ? 'internalStatsLast6Months'
            : 'internalStatsLast3Months';
      return this.$t(`tournaments.${key}`);
    },
    buildStatsParams() {
      const params = { months: this.months };
      if (this.pendingResetAgeSelection) return params;
      const opts = this.stats.ageClassOptions || [];
      const allKeys = opts.map((o) => o.key);
      if (allKeys.length === 0) return params;
      const sel = this.effectiveAgeClassKeys;
      if (sel.length === 0) {
        params.ageClassKeys = '';
      } else if (sel.length < allKeys.length) {
        params.ageClassKeys = sel.join(',');
      }
      return params;
    },
    onMonthsChange() {
      this.pendingResetAgeSelection = true;
      this.load();
    },
    allBandKeysFromOptions(opts) {
      const seen = new Set();
      const out = [];
      for (const o of opts || []) {
        if (!o || o.isNoClass) continue;
        const bk = o.band === 'adult' ? 'adult' : String(o.bandNum);
        if (!seen.has(bk)) {
          seen.add(bk);
          out.push(bk);
        }
      }
      out.sort((a, b) => {
        if (a === 'adult') return 1;
        if (b === 'adult') return -1;
        return Number(a) - Number(b);
      });
      return out;
    },
    onBandCheckboxChange(bandKey, checked) {
      if (checked) {
        if (!this.selectedBandKeys.includes(bandKey)) {
          this.selectedBandKeys = [...this.selectedBandKeys, bandKey];
        }
      } else {
        this.selectedBandKeys = this.selectedBandKeys.filter((k) => k !== bandKey);
      }
      this.load();
    },
    onGenderScopeChange() {
      this.load();
    },
    selectAllAgeKeys() {
      const opts = this.stats.ageClassOptions || [];
      this.selectedBandKeys = this.allBandKeysFromOptions(opts);
      this.genderScope = 'all';
      this.load();
    },
    selectNoAgeKeys() {
      this.selectedBandKeys = [];
      this.load();
    },
    formatBandOnly(b) {
      if (!b) return '';
      if (b.band === 'youth' && b.bandNum != null) return `J${b.bandNum}`;
      if (b.band === 'adult') return this.$t('tournaments.internalStatsTtAdult');
      return b.bandKey || '';
    },
    ageFilterPdfLine() {
      const opts = this.stats.ageClassOptions || [];
      if (opts.length === 0) return '';
      const allKeys = opts.map((o) => o.key);
      const sel = this.effectiveAgeClassKeys;
      if (sel.length === allKeys.length) {
        return this.$t('tournaments.internalStatsAgeFilterAll');
      }
      if (sel.length === 0) {
        return this.$t('tournaments.internalStatsAgeFilterNone');
      }
      const bandLabels = this.bandOptions
        .filter((b) => this.selectedBandKeys.includes(b.bandKey))
        .map((b) => this.formatBandOnly(b));
      const genderLabel =
        this.genderScope === 'female'
          ? this.$t('tournaments.internalStatsGenderScopeGirls')
          : this.$t('tournaments.internalStatsGenderScopeAll');
      const parts = [];
      if (bandLabels.length) {
        parts.push(`${this.$t('tournaments.internalStatsFilterAgeBands')}: ${bandLabels.join(', ')}`);
      }
      parts.push(`${this.$t('tournaments.internalStatsFilterGenderColumn')}: ${genderLabel}`);
      return parts.length ? `${this.$t('tournaments.internalStatsAgeFilter')}: ${parts.join(' · ')}` : '';
    },
    exportPdf() {
      const t = this.$t;
      const margin = 14;
      const pdf = new jsPDF('p', 'mm', 'a4');
      const pageW = pdf.internal.pageSize.getWidth();

      pdf.setFontSize(14);
      pdf.setFont('helvetica', 'bold');
      pdf.text(t('tournaments.internalStatsTitle'), margin, 18);

      pdf.setFontSize(9);
      pdf.setFont('helvetica', 'normal');
      let y = 24;
      pdf.text(`${t('tournaments.internalStatsPeriod')}: ${this.periodLabel()}`, margin, y);
      y += 5;
      pdf.text(
        t('tournaments.internalStatsTournamentsInPeriod', {
          count: this.stats.tournamentCount || 0,
        }),
        margin,
        y,
      );
      y += 6;

      const ageLine = this.ageFilterPdfLine();
      if (ageLine) {
        pdf.text(ageLine, margin, y);
        y += 5;
      }

      const explain = t('tournaments.internalStatsPointsExplain');
      const explainLines = pdf.splitTextToSize(explain, pageW - margin * 2);
      pdf.setFontSize(8);
      pdf.setTextColor(60);
      pdf.text(explainLines, margin, y);
      y += explainLines.length * 3.6 + 4;
      pdf.setTextColor(0);

      pdf.setFontSize(11);
      pdf.setFont('helvetica', 'bold');
      pdf.text(t('tournaments.internalStatsAbsoluteRank'), margin, y);
      y += 6;
      pdf.setFont('helvetica', 'normal');
      pdf.setFontSize(9);

      const absRows =
        this.stats.absoluteRanking?.map((row, i) => [
          String(i + 1),
          `${row.firstName || ''} ${row.lastName || ''}`.trim(),
          this.formatTotal(row.totalPoints),
        ]) || [];

      autoTable(pdf, {
        startY: y,
        margin: { left: margin, right: margin },
        head: [
          [
            '#',
            t('tournaments.player'),
            t('tournaments.internalStatsPoints'),
          ],
        ],
        body: absRows.length ? absRows : [['–', t('tournaments.internalStatsEmpty'), '']],
        styles: { fontSize: 9, cellPadding: 2 },
        headStyles: { fillColor: [55, 120, 180], textColor: 255, fontStyle: 'bold' },
        theme: 'striped',
      });

      let nextY = pdf.lastAutoTable?.finalY != null ? pdf.lastAutoTable.finalY + 10 : y + 40;

      pdf.setFontSize(11);
      pdf.setFont('helvetica', 'bold');
      pdf.text(t('tournaments.internalStatsAverageRank'), margin, nextY);
      nextY += 6;
      pdf.setFont('helvetica', 'normal');
      pdf.setFontSize(9);

      const avgRows =
        this.stats.averageRanking?.map((row, i) => [
          String(i + 1),
          `${row.firstName || ''} ${row.lastName || ''}`.trim(),
          this.formatAvg(row.averagePoints),
        ]) || [];

      autoTable(pdf, {
        startY: nextY,
        margin: { left: margin, right: margin },
        head: [
          [
            '#',
            t('tournaments.player'),
            t('tournaments.internalStatsAvgPoints'),
          ],
        ],
        body: avgRows.length ? avgRows : [['–', t('tournaments.internalStatsEmpty'), '']],
        styles: { fontSize: 9, cellPadding: 2 },
        headStyles: { fillColor: [55, 120, 180], textColor: 255, fontStyle: 'bold' },
        theme: 'striped',
      });

      const ts = new Date();
      const stamp = `${ts.getFullYear()}-${String(ts.getMonth() + 1).padStart(2, '0')}-${String(ts.getDate()).padStart(2, '0')}_${String(ts.getHours()).padStart(2, '0')}${String(ts.getMinutes()).padStart(2, '0')}`;
      const pageCount = pdf.internal.getNumberOfPages();
      for (let i = 1; i <= pageCount; i++) {
        pdf.setPage(i);
        pdf.setFontSize(8);
        pdf.setTextColor(120);
        pdf.text(
          `${t('pdfGenerator.generatedAt')} ${ts.toLocaleString()}`,
          margin,
          pdf.internal.pageSize.getHeight() - 8,
        );
        pdf.setTextColor(0);
      }

      pdf.save(`turnier-statistik-einzel_${stamp}.pdf`);
    },
    formatTotal(v) {
      if (v == null || Number.isNaN(Number(v))) return '–';
      const n = Number(v);
      return n.toLocaleString(undefined, {
        maximumFractionDigits: 2,
        minimumFractionDigits: 0,
      });
    },
    formatAvg(v) {
      if (v == null || Number.isNaN(v)) return '–';
      return String(v);
    },
    async load() {
      if (!this.clubId) return;
      this.loading = true;
      this.error = null;
      try {
        const res = await apiClient.get(`/tournament/internal-stats/${this.clubId}`, {
          params: this.buildStatsParams(),
        });
        this.stats = res.data || {};
        const opts = this.stats.ageClassOptions || [];
        if (this.pendingResetAgeSelection) {
          this.selectedBandKeys = this.allBandKeysFromOptions(opts);
          this.genderScope = 'all';
          this.pendingResetAgeSelection = false;
          this.ageFilterInitialized = true;
        } else if (!this.ageFilterInitialized && opts.length) {
          this.selectedBandKeys = this.allBandKeysFromOptions(opts);
          this.genderScope = 'all';
          this.ageFilterInitialized = true;
        }
      } catch (e) {
        this.error = e?.response?.data?.error || e.message || 'Error';
        this.stats = {
          tournamentCount: 0,
          ageClassOptions: [],
          absoluteRanking: [],
          averageRanking: [],
        };
      } finally {
        this.loading = false;
      }
    },
  },
};
</script>

<style scoped>
.internal-tournament-stats {
  min-width: 0;
}

.internal-tournament-stats--embed {
  padding: 1rem 1.25rem 1.25rem;
  box-sizing: border-box;
  height: 100%;
  overflow: auto;
}

.stats-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

.pdf-button {
  margin-right: auto;
  background: #f3f4f6;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  padding: 0.4rem 0.75rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: #374151;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.pdf-button:hover:not(:disabled) {
  background: #e5e7eb;
  border-color: #9ca3af;
}

.pdf-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.period-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
}

.period-label select {
  padding: 0.35rem 0.6rem;
  border-radius: 6px;
  border: 1px solid var(--border-color, #d1d5db);
}

.stats-meta {
  margin: 0 0 0.35rem;
  font-size: 0.85rem;
  color: var(--text-muted, #6b7280);
}

.stats-explain {
  margin: 0 0 1rem;
  font-size: 0.85rem;
  color: #4b5563;
  line-height: 1.45;
}

.age-filter {
  margin: 0 0 1rem;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--border-color, #e5e7eb);
  border-radius: 8px;
  background: #fafafa;
}

.age-filter-legend {
  padding: 0 0.35rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: #374151;
}

.age-filter-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem 1.5rem;
  align-items: start;
}

@media (max-width: 520px) {
  .age-filter-columns {
    grid-template-columns: 1fr;
  }
}

.age-filter-column-title {
  font-size: 0.82rem;
  font-weight: 600;
  color: #6b7280;
  margin-bottom: 0.4rem;
}

.gender-select-label {
  display: block;
  margin: 0;
}

.gender-scope-select {
  width: 100%;
  max-width: 14rem;
  padding: 0.4rem 0.55rem;
  border-radius: 6px;
  border: 1px solid var(--border-color, #d1d5db);
  font-size: 0.88rem;
  background: #fff;
  color: inherit;
}

.age-filter-actions {
  display: flex;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

.age-filter-link {
  background: none;
  border: none;
  padding: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--primary-color, #2563eb);
  cursor: pointer;
  text-decoration: underline;
}

.age-filter-link:hover:not(:disabled) {
  color: var(--primary-hover, #1d4ed8);
}

.age-filter-link:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.age-filter-checkboxes {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  max-height: 14rem;
  overflow-y: auto;
}

.age-filter-item {
  display: flex;
  align-items: flex-start;
  gap: 0.45rem;
  font-size: 0.88rem;
  line-height: 1.35;
  cursor: pointer;
}

.age-filter-item input {
  margin-top: 0.2rem;
  flex-shrink: 0;
}

.stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
}

@media (max-width: 900px) {
  .stats-grid {
    grid-template-columns: 1fr;
  }
}

.stats-column h4 {
  margin: 0 0 0.5rem;
  font-size: 1rem;
}

.stats-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  background: #fff;
  border: 1px solid var(--border-color, #e5e7eb);
  border-radius: 6px;
  overflow: hidden;
}

.stats-table th,
.stats-table td {
  padding: 0.45rem 0.6rem;
  text-align: left;
  border-bottom: 1px solid #f3f4f6;
}

.stats-table th {
  background: #f9fafb;
  font-weight: 600;
}

.col-rank {
  width: 2.5rem;
  color: #6b7280;
}

.stats-loading,
.stats-error,
.stats-empty {
  font-size: 0.9rem;
  color: #6b7280;
}

.stats-error {
  color: #b91c1c;
}
</style>
