<template>
  <div class="club-invoices-page">
    <header class="page-header card">
      <div>
        <p class="page-eyebrow">TT-Verein</p>
        <h2>Rechnungen</h2>
        <p class="page-subtitle">
          Ausgangsrechnungen an Sponsoren, Kurse und sonstige Empfänger sowie eingehende Belege in einer gemeinsamen Arbeitsfläche.
        </p>
      </div>
      <button type="button" class="btn-primary" :disabled="!canEdit" @click="resetInvoiceForm">Neue Rechnung</button>
    </header>

    <div v-if="!canEdit && currentClub" class="state-banner">
      Lesemodus aktiv. Rechnungen und Parteien können angezeigt, aber nicht bearbeitet werden.
    </div>

    <section v-if="!currentClub" class="card empty-state">
      <h3>Kein Verein ausgewählt</h3>
      <p>Bitte zuerst einen Verein auswählen, um Rechnungen zu verwalten.</p>
    </section>

    <template v-else>
      <section class="invoice-stats-grid">
        <article class="card stat-card">
          <span class="stat-label">Ausgehend</span>
          <strong class="stat-value">{{ outgoingInvoices.length }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Eingehend</span>
          <strong class="stat-value">{{ incomingInvoices.length }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Offen</span>
          <strong class="stat-value">{{ openInvoices.length }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Volumen</span>
          <strong class="stat-value">{{ formatCurrency(totalVisibleGrossCents) }}</strong>
        </article>
      </section>

      <section class="invoice-layout">
        <div class="invoice-main">
          <section class="card invoice-filter-card">
            <div class="invoice-filter-grid">
              <label>
                <span>Richtung</span>
                <select v-model="filters.direction">
                  <option value="">Alle</option>
                  <option value="outgoing">Ausgehend</option>
                  <option value="incoming">Eingehend</option>
                </select>
              </label>
              <label>
                <span>Status</span>
                <select v-model="filters.status">
                  <option value="">Alle</option>
                  <option value="draft">Entwurf</option>
                  <option value="issued">Gestellt</option>
                  <option value="partially_paid">Teilweise bezahlt</option>
                  <option value="paid">Bezahlt</option>
                  <option value="cancelled">Storniert</option>
                  <option value="archived">Archiviert</option>
                </select>
              </label>
              <label class="filter-search">
                <span>Suche</span>
                <input v-model.trim="filters.search" type="text" placeholder="Nummer, Partei oder Beschreibung" />
              </label>
            </div>
          </section>

          <section class="card invoice-party-card">
            <div class="section-header">
              <h3>Rechnungsparteien</h3>
              <button type="button" class="btn-secondary" :disabled="!canEdit" @click="startCreateParty">Neue Partei</button>
            </div>
            <p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Parteien können eingesehen, aber nicht bearbeitet werden.</p>
            <div class="party-list">
              <button
                v-for="party in parties"
                :key="party.id"
                type="button"
                class="party-chip"
                :class="{ active: selectedParty?.id === party.id }"
                @click="selectParty(party)"
              >
                {{ party.name }}
              </button>
            </div>
            <form class="party-form" @submit.prevent="submitParty">
              <div class="invoice-form-grid">
                <label>
                  <span>Name</span>
                  <input v-model.trim="partyForm.name" type="text" :disabled="!canEdit" required />
                </label>
                <label>
                  <span>Typ</span>
                  <select v-model="partyForm.partyType" :disabled="!canEdit">
                    <option value="customer">Kunde</option>
                    <option value="supplier">Lieferant</option>
                    <option value="sponsor">Sponsor</option>
                    <option value="other">Sonstige</option>
                  </select>
                </label>
              </div>
              <div class="invoice-form-grid">
                <label>
                  <span>Ansprechpartner</span>
                  <input v-model.trim="partyForm.contactName" type="text" :disabled="!canEdit" />
                </label>
                <label>
                  <span>E-Mail</span>
                  <input v-model.trim="partyForm.email" type="email" :disabled="!canEdit" />
                </label>
              </div>
              <div class="invoice-form-grid">
                <label>
                  <span>Status</span>
                  <select v-model="partyForm.status" :disabled="!canEdit">
                    <option value="active">Aktiv</option>
                    <option value="prospect">Interessent</option>
                    <option value="paused">Pausiert</option>
                    <option value="ended">Beendet</option>
                  </select>
                </label>
                <label>
                  <span>Vertragsreferenz</span>
                  <input v-model.trim="partyForm.contractReference" type="text" :disabled="!canEdit" />
                </label>
              </div>
              <div class="invoice-form-grid">
                <label>
                  <span>Vertragsbeginn</span>
                  <input v-model="partyForm.validFrom" type="date" :disabled="!canEdit" />
                </label>
                <label>
                  <span>Vertragsende</span>
                  <input v-model="partyForm.validTo" type="date" :disabled="!canEdit" />
                </label>
              </div>
              <div class="invoice-form-grid">
                <label>
                  <span>Straße</span>
                  <input v-model.trim="partyForm.street" type="text" :disabled="!canEdit" />
                </label>
                <label>
                  <span>Ort</span>
                  <input v-model.trim="partyForm.city" type="text" :disabled="!canEdit" />
                </label>
              </div>
              <div class="invoice-form-grid">
                <label>
                  <span>PLZ</span>
                  <input v-model.trim="partyForm.postalCode" type="text" :disabled="!canEdit" />
                </label>
                <label>
                  <span>Notizen</span>
                  <input v-model.trim="partyForm.notes" type="text" :disabled="!canEdit" />
                </label>
              </div>
              <div class="invoice-form-actions">
                <button type="submit" class="btn-primary" :disabled="!canEdit || partySaving">{{ partySaving ? 'Speichert…' : 'Partei speichern' }}</button>
                <button type="button" class="btn-secondary" @click="resetPartyForm">Zurücksetzen</button>
                <button type="button" class="btn-danger" :disabled="!canEdit || !partyForm.id" @click="deleteParty">Löschen</button>
              </div>
            </form>
          </section>

          <section class="card invoice-list-card">
            <div class="section-header invoice-list-header">
              <h3>Rechnungen</h3>
              <button type="button" class="btn-secondary" @click="loadInvoices" :disabled="loading">
                {{ loading ? 'Lädt…' : 'Neu laden' }}
              </button>
            </div>

            <p v-if="loadError" class="state-banner state-banner-error">{{ loadError }}</p>
            <p v-else-if="loading" class="state-banner">Rechnungen werden geladen…</p>
            <p v-else-if="filteredInvoices.length === 0" class="state-banner">Keine Rechnungen im aktuellen Filter.</p>

            <div v-else class="invoice-list">
              <div
                v-for="invoice in filteredInvoices"
                :key="invoice.id"
                class="invoice-row"
                :class="{ active: selectedInvoice?.id === invoice.id }"
              >
                <div class="invoice-row-main">
                  <div class="invoice-row-topline">
                    <strong>{{ invoice.invoiceNumber || `Rechnung #${invoice.id}` }}</strong>
                    <div class="invoice-badge-row">
                      <span class="invoice-badge" :class="`direction-${invoice.invoiceDirection}`">{{ displayDirection(invoice.invoiceDirection) }}</span>
                      <span class="invoice-badge" :class="`status-${invoice.status}`">{{ displayStatus(invoice.status) }}</span>
                    </div>
                  </div>
                  <p class="invoice-row-meta">
                    <span>{{ invoice.party?.name || 'Ohne Partei' }}</span>
                    <span>{{ displayInvoiceType(invoice.invoiceType) }}</span>
                    <span>{{ invoice.dueOn || 'Kein Fälligkeitsdatum' }}</span>
                    <span>{{ formatCurrency(invoice.grossAmountCents, invoice.currencyCode) }}</span>
                  </p>
                  <p class="invoice-row-description">{{ invoice.description || 'Keine Beschreibung hinterlegt.' }}</p>
                </div>
                <div class="invoice-row-actions">
                  <button type="button" class="btn-secondary" @click="selectInvoice(invoice)">Bearbeiten</button>
                  <button type="button" class="btn-secondary" :disabled="!canEdit || invoice.status === 'archived'" @click="archiveInvoice(invoice)">Archivieren</button>
                  <button type="button" class="btn-danger" :disabled="!canEdit" @click="deleteInvoice(invoice)">Löschen</button>
                </div>
              </div>
            </div>
          </section>
        </div>

        <aside class="invoice-side">
          <section class="card invoice-form-card">
            <div class="section-header">
              <h3>{{ invoiceForm.id ? 'Rechnung bearbeiten' : 'Neue Rechnung' }}</h3>
            </div>
            <p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Rechnungen lassen sich prüfen, aber nicht ändern.</p>
            <form class="invoice-form" @submit.prevent="submitInvoice">
              <div class="invoice-form-grid">
                <label>
                  <span>Richtung</span>
                  <select v-model="invoiceForm.invoiceDirection" :disabled="!canEdit">
                    <option value="outgoing">Ausgehend</option>
                    <option value="incoming">Eingehend</option>
                  </select>
                </label>
                <label>
                  <span>Typ</span>
                  <select v-model="invoiceForm.invoiceType" :disabled="!canEdit">
                    <option value="sponsoring">Sponsoring</option>
                    <option value="course_fee">Kurs</option>
                    <option value="service">Leistung</option>
                    <option value="material">Material</option>
                    <option value="expense">Ausgabe</option>
                    <option value="other">Sonstige</option>
                  </select>
                </label>
              </div>

              <div class="invoice-form-grid">
                <label>
                  <span>Status</span>
                  <select v-model="invoiceForm.status" :disabled="!canEdit">
                    <option value="draft">Entwurf</option>
                    <option value="issued">Gestellt</option>
                    <option value="partially_paid">Teilweise bezahlt</option>
                    <option value="paid">Bezahlt</option>
                    <option value="cancelled">Storniert</option>
                    <option value="archived">Archiviert</option>
                  </select>
                </label>
                <label>
                  <span>Währung</span>
                  <input v-model.trim="invoiceForm.currencyCode" maxlength="3" :disabled="!canEdit" />
                </label>
              </div>

              <div class="invoice-form-grid">
                <label>
                  <span>Rechnungsnummer</span>
                  <input :value="displayInvoiceNumber" type="text" disabled />
                </label>
                <label>
                  <span>Externe Referenz</span>
                  <input v-model.trim="invoiceForm.externalReference" type="text" :disabled="!canEdit" />
                </label>
              </div>

              <p class="invoice-number-hint">
                {{ invoiceForm.id ? 'Rechnungsnummer wird automatisch vergeben und bleibt danach fest.' : `Wird beim Speichern automatisch als ${displayInvoiceNumber} vergeben.` }}
              </p>

              <div class="invoice-form-grid">
                <label>
                  <span>Partei</span>
                  <select v-model="invoiceForm.partyId" :disabled="!canEdit">
                    <option value="">Bitte wählen</option>
                    <option v-for="party in parties" :key="party.id" :value="String(party.id)">
                      {{ party.name }}
                    </option>
                  </select>
                </label>
                <label>
                  <span>Konto</span>
                  <select v-model="invoiceForm.accountId" :disabled="!canEdit">
                    <option value="">Kein Konto</option>
                    <option v-for="account in accounts" :key="account.id" :value="String(account.id)">
                      {{ account.name }}
                    </option>
                  </select>
                </label>
              </div>

              <div class="invoice-form-grid">
                <label>
                  <span>Ausgestellt am</span>
                  <input v-model="invoiceForm.issuedOn" type="date" :disabled="!canEdit" />
                </label>
                <label>
                  <span>Fällig am</span>
                  <input v-model="invoiceForm.dueOn" type="date" :disabled="!canEdit" />
                </label>
              </div>

              <label>
                <span>Beschreibung</span>
                <textarea v-model.trim="invoiceForm.description" rows="3" :disabled="!canEdit"></textarea>
              </label>

              <div class="invoice-item-header">
                <h4>Positionen</h4>
                <button type="button" class="btn-secondary" :disabled="!canEdit" @click="addInvoiceItem">Position hinzufügen</button>
              </div>
              <div class="invoice-items">
                <div v-for="(item, index) in invoiceForm.items" :key="`item-${index}`" class="invoice-item-row">
                  <label class="item-description">
                    <span>Beschreibung</span>
                    <input v-model.trim="item.description" type="text" :disabled="!canEdit" />
                  </label>
                  <label>
                    <span>Menge</span>
                    <input v-model.number="item.quantity" type="number" min="0" step="0.01" :disabled="!canEdit" />
                  </label>
                  <label>
                    <span>Einzelpreis (EUR)</span>
                    <input v-model.number="item.unitPriceEuro" type="number" min="0" step="0.01" :disabled="!canEdit" />
                  </label>
                  <label>
                    <span>Steuer %</span>
                    <input v-model.number="item.taxRate" type="number" min="0" step="0.01" :disabled="!canEdit" />
                  </label>
                  <button type="button" class="btn-danger" :disabled="!canEdit" @click="removeInvoiceItem(index)">Entfernen</button>
                </div>
              </div>

              <div class="invoice-totals card">
                <div><span>Netto</span><strong>{{ formatCurrency(invoiceTotals.netAmountCents, invoiceForm.currencyCode) }}</strong></div>
                <div><span>Steuer</span><strong>{{ formatCurrency(invoiceTotals.taxAmountCents, invoiceForm.currencyCode) }}</strong></div>
                <div><span>Brutto</span><strong>{{ formatCurrency(invoiceTotals.grossAmountCents, invoiceForm.currencyCode) }}</strong></div>
              </div>

              <div class="invoice-form-actions">
                <button type="submit" class="btn-primary" :disabled="!canEdit || saving">{{ saving ? 'Speichert…' : 'Rechnung speichern' }}</button>
                <button type="button" class="btn-secondary" @click="resetInvoiceForm">Zurücksetzen</button>
              </div>
            </form>
          </section>
        </aside>
      </section>
    </template>

    <InfoDialog
      v-model="infoDialog.isOpen"
      :title="infoDialog.title"
      :message="infoDialog.message"
      :details="infoDialog.details"
      :type="infoDialog.type"
    />

    <ConfirmDialog
      v-model="confirmDialog.isOpen"
      :title="confirmDialog.title"
      :message="confirmDialog.message"
      :details="confirmDialog.details"
      :type="confirmDialog.type"
      :confirm-text="confirmDialog.confirmText"
      :cancel-text="confirmDialog.cancelText"
      @confirm="handleConfirmResult(true)"
      @cancel="handleConfirmResult(false)"
    />
  </div>
</template>

<script>
import { mapGetters } from 'vuex';
import apiClient from '../apiClient.js';
import ConfirmDialog from '../components/ConfirmDialog.vue';
import InfoDialog from '../components/InfoDialog.vue';
import { buildConfirmConfig, buildInfoConfig, safeErrorMessage } from '../utils/dialogUtils.js';

function normalizeParty(payload = {}) {
  return {
    id: payload.id,
    name: payload.name || '',
    partyType: payload.partyType || payload.party_type || 'customer',
    status: payload.status || 'active',
    contractReference: payload.contractReference || payload.contract_reference || '',
    validFrom: payload.validFrom || payload.valid_from || '',
    validTo: payload.validTo || payload.valid_to || '',
    contactName: payload.contactName || payload.contact_name || '',
    email: payload.email || '',
    phone: payload.phone || '',
    street: payload.street || '',
    postalCode: payload.postalCode || payload.postal_code || '',
    city: payload.city || '',
    notes: payload.notes || '',
  };
}

function normalizeInvoiceItem(payload = {}) {
  return {
    id: payload.id,
    description: payload.description || '',
    quantity: Number(payload.quantity || 1),
    unitPriceCents: Number(payload.unitPriceCents || payload.unit_price_cents || 0),
    unitPriceEuro: Number(payload.unitPriceCents || payload.unit_price_cents || 0) / 100,
    taxRate: Number(payload.taxRate || payload.tax_rate || 0),
    totalCents: Number(payload.totalCents || payload.total_cents || 0),
  };
}

function normalizeInvoice(payload = {}) {
  return {
    id: payload.id,
    invoiceDirection: payload.invoiceDirection || payload.invoice_direction || 'outgoing',
    invoiceType: payload.invoiceType || payload.invoice_type || 'other',
    status: payload.status || 'draft',
    invoiceNumber: payload.invoiceNumber || payload.invoice_number || '',
    externalReference: payload.externalReference || payload.external_reference || '',
    partyId: payload.partyId || payload.party_id || null,
    accountId: payload.accountId || payload.account_id || null,
    issuedOn: payload.issuedOn || payload.issued_on || '',
    dueOn: payload.dueOn || payload.due_on || '',
    paidOn: payload.paidOn || payload.paid_on || '',
    netAmountCents: Number(payload.netAmountCents || payload.net_amount_cents || 0),
    taxAmountCents: Number(payload.taxAmountCents || payload.tax_amount_cents || 0),
    grossAmountCents: Number(payload.grossAmountCents || payload.gross_amount_cents || 0),
    currencyCode: payload.currencyCode || payload.currency_code || 'EUR',
    description: payload.description || '',
    party: payload.party ? normalizeParty(payload.party) : null,
    account: payload.account || null,
    items: Array.isArray(payload.items) ? payload.items.map(normalizeInvoiceItem) : [],
  };
}

function createEmptyInvoiceItem() {
  return {
    description: '',
    quantity: 1,
    unitPriceEuro: 0,
    taxRate: 19,
  };
}

function addDaysIso(baseDate, days) {
  const date = new Date(baseDate);
  date.setDate(date.getDate() + days);
  return date.toISOString().slice(0, 10);
}

function buildInvoiceNumber(prefix, nextNumber, referenceDate = new Date()) {
  const parsedReferenceDate = referenceDate instanceof Date ? referenceDate : new Date(referenceDate || new Date());
  const year = Number.isNaN(parsedReferenceDate.getTime()) ? new Date().getFullYear() : parsedReferenceDate.getFullYear();
  const normalizedPrefix = String(prefix || '').trim().toUpperCase();
  const paddedCounter = String(Math.max(1, Number.parseInt(nextNumber, 10) || 1)).padStart(4, '0');
  return normalizedPrefix ? `${normalizedPrefix}-${year}-${paddedCounter}` : `${year}-${paddedCounter}`;
}

function createEmptyInvoiceForm() {
  const issuedOn = new Date().toISOString().slice(0, 10);
  return {
    id: null,
    invoiceDirection: 'outgoing',
    invoiceType: 'sponsoring',
    status: 'draft',
    invoiceNumber: '',
    externalReference: '',
    partyId: '',
    accountId: '',
    issuedOn,
    dueOn: addDaysIso(issuedOn, 14),
    paidOn: '',
    currencyCode: 'EUR',
    description: '',
    items: [createEmptyInvoiceItem()],
  };
}

function createEmptyPartyForm() {
  return {
    id: null,
    name: '',
    partyType: 'customer',
    status: 'active',
    contractReference: '',
    validFrom: '',
    validTo: '',
    contactName: '',
    email: '',
    phone: '',
    street: '',
    postalCode: '',
    city: '',
    notes: '',
  };
}

export default {
  name: 'ClubInvoicesView',
  components: {
    ConfirmDialog,
    InfoDialog,
  },
  data() {
    return {
      loading: false,
      saving: false,
      partySaving: false,
      loadError: '',
      invoices: [],
      parties: [],
      accounts: [],
      invoiceSettings: {
        outgoingInvoicePrefix: 'RE',
        outgoingInvoiceNextNumber: 1,
        incomingInvoicePrefix: 'EI',
        incomingInvoiceNextNumber: 1,
      },
      selectedInvoiceId: null,
      selectedPartyId: null,
      filters: {
        direction: 'outgoing',
        status: '',
        search: '',
      },
      invoiceForm: createEmptyInvoiceForm(),
      partyForm: createEmptyPartyForm(),
      infoDialog: {
        isOpen: false,
        title: '',
        message: '',
        details: '',
        type: 'info',
      },
      confirmDialog: {
        isOpen: false,
        title: '',
        message: '',
        details: '',
        type: 'warning',
        confirmText: '',
        cancelText: '',
        resolveCallback: null,
      },
    };
  },
  computed: {
    ...mapGetters(['currentClub', 'hasPermission']),
    canEdit() {
      return this.hasPermission('finance_invoices', 'write');
    },
    filteredInvoices() {
      const needle = this.filters.search.trim().toLowerCase();
      return this.invoices.filter((invoice) => {
        if (this.filters.direction && invoice.invoiceDirection !== this.filters.direction) return false;
        if (this.filters.status && invoice.status !== this.filters.status) return false;
        if (!needle) return true;
        return [
          invoice.invoiceNumber,
          invoice.externalReference,
          invoice.description,
          invoice.party?.name,
        ].join(' ').toLowerCase().includes(needle);
      });
    },
    selectedInvoice() {
      return this.invoices.find((invoice) => String(invoice.id) === String(this.selectedInvoiceId)) || null;
    },
    selectedParty() {
      return this.parties.find((party) => String(party.id) === String(this.selectedPartyId)) || null;
    },
    outgoingInvoices() {
      return this.invoices.filter((invoice) => invoice.invoiceDirection === 'outgoing');
    },
    incomingInvoices() {
      return this.invoices.filter((invoice) => invoice.invoiceDirection === 'incoming');
    },
    openInvoices() {
      return this.invoices.filter((invoice) => ['draft', 'issued', 'partially_paid'].includes(invoice.status));
    },
    totalVisibleGrossCents() {
      return this.filteredInvoices.reduce((sum, invoice) => sum + Number(invoice.grossAmountCents || 0), 0);
    },
    invoiceTotals() {
      return this.invoiceForm.items.reduce((acc, item) => {
        const quantity = Number(item.quantity || 0);
        const unitPriceCents = Math.round(Number(item.unitPriceEuro || 0) * 100);
        const taxRate = Number(item.taxRate || 0);
        const net = Math.round(quantity * unitPriceCents);
        const tax = Math.round(net * (taxRate / 100));
        acc.netAmountCents += net;
        acc.taxAmountCents += tax;
        acc.grossAmountCents += net + tax;
        return acc;
      }, { netAmountCents: 0, taxAmountCents: 0, grossAmountCents: 0 });
    },
    displayInvoiceNumber() {
      if (this.invoiceForm.id) {
        return this.invoiceForm.invoiceNumber || '';
      }
      const isIncoming = this.invoiceForm.invoiceDirection === 'incoming';
      const referenceDate = this.invoiceForm.issuedOn || new Date();
      return buildInvoiceNumber(
        isIncoming ? this.invoiceSettings.incomingInvoicePrefix : this.invoiceSettings.outgoingInvoicePrefix,
        isIncoming ? this.invoiceSettings.incomingInvoiceNextNumber : this.invoiceSettings.outgoingInvoiceNextNumber,
        referenceDate
      );
    },
  },
  watch: {
    currentClub: {
      immediate: true,
      async handler(newClub) {
        if (!newClub) {
          this.clearInvoiceState();
          return;
        }
        await this.loadInvoices();
      },
    },
    '$route.query': {
      immediate: true,
      handler() {
        this.applyWorkflowQueryPrefill();
      },
    },
    selectedInvoice(invoice) {
      if (!invoice) {
        this.resetInvoiceForm();
        return;
      }
      this.invoiceForm = {
        id: invoice.id,
        invoiceDirection: invoice.invoiceDirection,
        invoiceType: invoice.invoiceType,
        status: invoice.status,
        invoiceNumber: invoice.invoiceNumber,
        externalReference: invoice.externalReference,
        partyId: invoice.partyId ? String(invoice.partyId) : '',
        accountId: invoice.accountId ? String(invoice.accountId) : '',
        issuedOn: invoice.issuedOn || '',
        dueOn: invoice.dueOn || '',
        paidOn: invoice.paidOn || '',
        currencyCode: invoice.currencyCode || 'EUR',
        description: invoice.description || '',
        items: invoice.items.length
          ? invoice.items.map((item) => ({
            description: item.description,
            quantity: item.quantity,
            unitPriceEuro: item.unitPriceCents / 100,
            taxRate: item.taxRate,
          }))
          : [createEmptyInvoiceItem()],
      };
    },
    selectedParty(party) {
      if (!party) {
        this.resetPartyForm();
        return;
      }
      this.partyForm = {
        id: party.id,
        name: party.name,
        partyType: party.partyType,
        status: party.status || 'active',
        contractReference: party.contractReference || '',
        validFrom: party.validFrom || '',
        validTo: party.validTo || '',
        contactName: party.contactName,
        email: party.email,
        phone: party.phone,
        street: party.street || '',
        postalCode: party.postalCode || '',
        city: party.city || '',
        notes: party.notes || '',
      };
    },
  },
  methods: {
    clearInvoiceState() {
      this.invoices = [];
      this.parties = [];
      this.accounts = [];
      this.invoiceSettings = {
        outgoingInvoicePrefix: 'RE',
        outgoingInvoiceNextNumber: 1,
        incomingInvoicePrefix: 'EI',
        incomingInvoiceNextNumber: 1,
      };
      this.selectedInvoiceId = null;
      this.selectedPartyId = null;
      this.invoiceForm = createEmptyInvoiceForm();
      this.partyForm = createEmptyPartyForm();
      this.loadError = '';
    },
    showInfo(title, message, details = '', type = 'info') {
      this.infoDialog = buildInfoConfig({ title, message, details, type });
    },
    async showConfirm(title, message, details = '', type = 'warning', options = {}) {
      return new Promise((resolve) => {
        this.confirmDialog = buildConfirmConfig({
          title,
          message,
          details,
          type,
          resolveCallback: resolve,
          ...options,
        });
      });
    },
    handleConfirmResult(confirmed) {
      if (this.confirmDialog.resolveCallback) {
        this.confirmDialog.resolveCallback(confirmed);
        this.confirmDialog.resolveCallback = null;
      }
      this.confirmDialog.isOpen = false;
    },
    displayDirection(direction) {
      return direction === 'incoming' ? 'Eingehend' : 'Ausgehend';
    },
    displayStatus(status) {
      return {
        draft: 'Entwurf',
        issued: 'Gestellt',
        partially_paid: 'Teilweise bezahlt',
        paid: 'Bezahlt',
        cancelled: 'Storniert',
        archived: 'Archiviert',
      }[status] || status;
    },
    displayInvoiceType(type) {
      return {
        membership_fee: 'Mitgliedsbeitrag',
        course_fee: 'Kurs',
        sponsoring: 'Sponsoring',
        material: 'Material',
        service: 'Leistung',
        expense: 'Ausgabe',
        other: 'Sonstige',
      }[type] || type;
    },
    formatCurrency(value, currencyCode = 'EUR') {
      const amount = Number(value || 0) / 100;
      return new Intl.NumberFormat('de-DE', {
        style: 'currency',
        currency: currencyCode || 'EUR',
      }).format(amount);
    },
    async loadInvoices() {
      if (!this.currentClub) return;
      this.loading = true;
      this.loadError = '';
      try {
        const response = await apiClient.get(`/club-invoices/${this.currentClub}`);
        this.invoices = Array.isArray(response.data?.invoices) ? response.data.invoices.map(normalizeInvoice) : [];
        this.parties = Array.isArray(response.data?.parties) ? response.data.parties.map(normalizeParty) : [];
        this.accounts = Array.isArray(response.data?.accounts) ? response.data.accounts : [];
        this.invoiceSettings = {
          outgoingInvoicePrefix: response.data?.settings?.outgoingInvoicePrefix || 'RE',
          outgoingInvoiceNextNumber: Number(response.data?.settings?.outgoingInvoiceNextNumber || 1) || 1,
          incomingInvoicePrefix: response.data?.settings?.incomingInvoicePrefix || 'EI',
          incomingInvoiceNextNumber: Number(response.data?.settings?.incomingInvoiceNextNumber || 1) || 1,
        };
        if (this.selectedInvoiceId && !this.selectedInvoice) {
          this.selectedInvoiceId = null;
          this.resetInvoiceForm();
        }
        if (this.selectedPartyId && !this.selectedParty) {
          this.selectedPartyId = null;
          this.resetPartyForm();
        }
        if (!this.selectedInvoiceId && this.invoices.length > 0) {
          this.selectedInvoiceId = this.invoices[0].id;
        }
        if (this.invoices.length === 0) {
          this.resetInvoiceForm();
        }
        if (this.parties.length === 0) {
          this.resetPartyForm();
        }
        this.applyWorkflowQueryPrefill();
      } catch (error) {
        this.loadError = safeErrorMessage(error, 'Rechnungen konnten nicht geladen werden.');
      } finally {
        this.loading = false;
      }
    },
    selectInvoice(invoice) {
      this.selectedInvoiceId = invoice.id;
    },
    selectParty(party) {
      this.selectedPartyId = party.id;
    },
    applyWorkflowQueryPrefill() {
      if (!this.currentClub || !Array.isArray(this.parties)) return;
      if (this.selectedInvoiceId || this.invoiceForm.id) return;
      const partyId = String(this.$route?.query?.partyId || this.$route?.query?.selectedPartyId || '').trim();
      if (!partyId) return;
      const matchingParty = this.parties.find((party) => String(party.id) === partyId);
      if (!matchingParty) return;

      this.selectedPartyId = matchingParty.id;
      this.selectedInvoiceId = null;
      this.invoiceForm = {
        id: null,
        invoiceDirection: this.$route?.query?.invoiceDirection || 'outgoing',
        invoiceType: this.$route?.query?.invoiceType || 'sponsoring',
        status: 'draft',
        invoiceNumber: '',
        externalReference: this.$route?.query?.externalReference || '',
        partyId: String(matchingParty.id),
        accountId: '',
        issuedOn: new Date().toISOString().slice(0, 10),
        dueOn: addDaysIso(new Date(), 14),
        paidOn: '',
        currencyCode: 'EUR',
        description: this.$route?.query?.invoiceDescription || `Sponsoringrechnung für ${matchingParty.name}`,
        items: [createEmptyInvoiceItem()],
      };
      if (!this.invoiceForm.items[0].description) {
        this.invoiceForm.items[0].description = `Sponsoring ${matchingParty.name}`;
        this.invoiceForm.items[0].unitPriceEuro = 0;
        this.invoiceForm.items[0].taxRate = 0;
      }
    },
    resetInvoiceForm() {
      this.selectedInvoiceId = null;
      this.invoiceForm = createEmptyInvoiceForm();
    },
    startCreateParty() {
      this.selectedPartyId = null;
      this.partyForm = createEmptyPartyForm();
    },
    resetPartyForm() {
      this.startCreateParty();
    },
    addInvoiceItem() {
      this.invoiceForm.items.push(createEmptyInvoiceItem());
    },
    removeInvoiceItem(index) {
      this.invoiceForm.items.splice(index, 1);
      if (this.invoiceForm.items.length === 0) {
        this.invoiceForm.items.push(createEmptyInvoiceItem());
      }
    },
    async submitParty() {
      if (!this.currentClub || !this.canEdit) return;
      this.partySaving = true;
      try {
        const payload = { ...this.partyForm };
        let savedPartyId = this.partyForm.id;
        if (this.partyForm.id) {
          const response = await apiClient.put(`/club-invoices/${this.currentClub}/parties/${this.partyForm.id}`, payload);
          savedPartyId = response.data?.party?.id || savedPartyId;
        } else {
          const response = await apiClient.post(`/club-invoices/${this.currentClub}/parties`, payload);
          savedPartyId = response.data?.party?.id || savedPartyId;
        }
        this.selectedPartyId = savedPartyId ? String(savedPartyId) : null;
        await this.loadInvoices();
        this.showInfo('Erfolg', 'Rechnungspartei gespeichert.', '', 'success');
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Rechnungspartei konnte nicht gespeichert werden.'), '', 'error');
      } finally {
        this.partySaving = false;
      }
    },
    async deleteParty() {
      if (!this.currentClub || !this.canEdit || !this.partyForm.id) return;
      const confirmed = await this.showConfirm(
        'Rechnungspartei löschen',
        `Soll "${this.partyForm.name}" gelöscht werden?`,
        'Verknüpfte Parteien können nicht gelöscht werden.',
        'danger',
        { confirmText: 'Löschen', cancelText: 'Abbrechen' }
      );
      if (!confirmed) return;
      try {
        await apiClient.delete(`/club-invoices/${this.currentClub}/parties/${this.partyForm.id}`);
        this.resetPartyForm();
        await this.loadInvoices();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Rechnungspartei konnte nicht gelöscht werden.'), '', 'error');
      }
    },
    async submitInvoice() {
      if (!this.currentClub || !this.canEdit) return;
      this.saving = true;
      try {
        const payload = {
          ...this.invoiceForm,
          partyId: this.invoiceForm.partyId || null,
          accountId: this.invoiceForm.accountId || null,
          items: this.invoiceForm.items.map((item) => ({
            description: item.description,
            quantity: item.quantity,
            unitPriceCents: Math.round(Number(item.unitPriceEuro || 0) * 100),
            taxRate: item.taxRate,
          })),
        };
        let savedInvoiceId = this.invoiceForm.id;
        if (this.invoiceForm.id) {
          const response = await apiClient.put(`/club-invoices/${this.currentClub}/${this.invoiceForm.id}`, payload);
          savedInvoiceId = response.data?.invoice?.id || savedInvoiceId;
        } else {
          const response = await apiClient.post(`/club-invoices/${this.currentClub}`, payload);
          savedInvoiceId = response.data?.invoice?.id || savedInvoiceId;
        }
        this.selectedInvoiceId = savedInvoiceId ? String(savedInvoiceId) : null;
        await this.loadInvoices();
        this.showInfo('Erfolg', 'Rechnung gespeichert.', '', 'success');
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Rechnung konnte nicht gespeichert werden.'), '', 'error');
      } finally {
        this.saving = false;
      }
    },
    async archiveInvoice(invoice) {
      if (!this.currentClub || !this.canEdit || !invoice?.id) return;
      const confirmed = await this.showConfirm(
        'Rechnung archivieren',
        `Soll ${invoice.invoiceNumber || `Rechnung #${invoice.id}`} archiviert werden?`,
        '',
        'warning',
        { confirmText: 'Archivieren', cancelText: 'Abbrechen' }
      );
      if (!confirmed) return;
      try {
        await apiClient.patch(`/club-invoices/${this.currentClub}/${invoice.id}/status`, { status: 'archived' });
        await this.loadInvoices();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Rechnung konnte nicht archiviert werden.'), '', 'error');
      }
    },
    async deleteInvoice(invoice) {
      if (!this.currentClub || !this.canEdit || !invoice?.id) return;
      const confirmed = await this.showConfirm(
        'Rechnung löschen',
        `Soll ${invoice.invoiceNumber || `Rechnung #${invoice.id}`} endgültig gelöscht werden?`,
        '',
        'danger',
        { confirmText: 'Löschen', cancelText: 'Abbrechen' }
      );
      if (!confirmed) return;
      try {
        await apiClient.delete(`/club-invoices/${this.currentClub}/${invoice.id}`);
        if (this.selectedInvoiceId === invoice.id) {
          this.resetInvoiceForm();
        }
        await this.loadInvoices();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Rechnung konnte nicht gelöscht werden.'), '', 'error');
      }
    },
  },
};
</script>

<style scoped>
.club-invoices-page {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.page-header,
.empty-state,
.invoice-filter-card,
.invoice-party-card,
.invoice-list-card,
.invoice-form-card {
  padding: 1.25rem;
}

.page-header {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  align-items: flex-start;
}

.page-eyebrow {
  margin: 0 0 0.35rem;
  color: var(--text-light);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.8rem;
}

.page-subtitle {
  margin: 0.35rem 0 0;
  color: var(--text-secondary);
}

.invoice-stats-grid,
.invoice-filter-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
}

.invoice-form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.invoice-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(320px, 0.9fr);
  gap: 1rem;
}

.invoice-main,
.invoice-side,
.invoice-form,
.invoice-list,
.party-form,
.invoice-items {
  display: grid;
  gap: 1rem;
}

.filter-search {
  grid-column: 1 / -1;
}

.section-header,
.invoice-list-header,
.invoice-row,
.invoice-row-topline,
.invoice-row-meta,
.invoice-row-actions,
.invoice-badge-row,
.invoice-form-actions,
.invoice-item-header,
.invoice-totals,
.party-list {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.section-header,
.invoice-list-header,
.invoice-row-topline,
.invoice-item-header {
  justify-content: space-between;
  align-items: center;
}

.party-chip {
  border: 1px solid rgba(24, 70, 54, 0.14);
  background: rgba(255, 255, 255, 0.88);
  border-radius: 999px;
  padding: 0.4rem 0.7rem;
}

.party-chip.active {
  border-color: rgba(47, 122, 95, 0.5);
}

.invoice-row {
  border: 1px solid rgba(24, 70, 54, 0.12);
  border-radius: 16px;
  padding: 1rem;
  justify-content: space-between;
}

.invoice-row.active {
  border-color: rgba(47, 122, 95, 0.6);
}

.invoice-row-main {
  display: grid;
  gap: 0.55rem;
}

.invoice-row-meta,
.invoice-row-description {
  color: var(--text-secondary);
}

.invoice-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 0.2rem 0.55rem;
  font-size: 0.78rem;
  font-weight: 700;
}

.direction-outgoing {
  background: rgba(47, 122, 95, 0.12);
  color: var(--primary-strong);
}

.direction-incoming {
  background: rgba(61, 118, 196, 0.12);
  color: #295b9c;
}

.status-draft {
  background: rgba(160, 112, 64, 0.14);
  color: #8a5b1d;
}

.status-issued,
.status-partially_paid {
  background: rgba(61, 118, 196, 0.12);
  color: #295b9c;
}

.status-paid {
  background: rgba(47, 122, 95, 0.12);
  color: var(--primary-strong);
}

.status-cancelled,
.status-archived {
  background: rgba(120, 120, 120, 0.16);
  color: #5b5b5b;
}

.invoice-item-row {
  display: grid;
  grid-template-columns: minmax(220px, 1.8fr) repeat(3, minmax(120px, 0.8fr)) auto;
  gap: 0.75rem;
  align-items: end;
}

.invoice-form label,
.invoice-filter-grid label,
.party-form label,
.invoice-item-row label {
  min-width: 0;
}

.invoice-form input,
.invoice-form select,
.invoice-form textarea,
.invoice-filter-grid input,
.invoice-filter-grid select,
.party-form input,
.party-form select,
.invoice-item-row input {
  width: 100%;
  box-sizing: border-box;
}

.invoice-form span,
.invoice-filter-grid span,
.party-form span,
.invoice-item-row span {
  display: block;
  margin-bottom: 0.35rem;
}

.item-description {
  min-width: 0;
}

.invoice-totals {
  justify-content: space-between;
  padding: 1rem;
}

.invoice-totals > div {
  display: grid;
  gap: 0.2rem;
}

.state-banner {
  margin: 0;
  color: var(--text-secondary);
}

@media (max-width: 1024px) {
  .invoice-layout {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 820px) {
  .invoice-stats-grid,
  .invoice-filter-grid,
  .invoice-form-grid,
  .invoice-item-row {
    grid-template-columns: 1fr;
  }

  .invoice-row {
    flex-direction: column;
  }
}
</style>
