import axios from 'axios';
import type { ApiResponse, Customer, Contract, ContractTask, ContractTaskSubtask, ContractTaskStatus, SalesPlatform, CancellationPeriod, ContractDuration, ContractCategory, Provider, Tariff, User, Address, BankCard, IdentityDocument, Meter, MeterReading, Invoice, Role, PortalSettings, CustomerRepresentative, CustomerSummary, CustomerReferrals, CreditNote, CreditNoteListItem, CreditNoteDefaults, CreditNoteNumberRange, CompanyProfile, ContractHistoryEntry, AuditLog, AuditSensitivity, AuditRetentionPolicy, CustomerConsent, ConsentType, ConsentStatus, DataDeletionRequest, DeletionRequestStatus, GDPRDashboardStats, RepresentativeAuthorization } from '../types';

// ============================================================================
// In-Memory-Token-Store
// ============================================================================
// Der Access-Token wird BEWUSST nicht in localStorage gespeichert (XSS-Schutz).
// Stattdessen lebt er im Modul-State + wird über den /api/auth/refresh-Endpoint
// nach Page-Reload neu geholt (Refresh-Token sitzt in einem httpOnly-Cookie,
// das JavaScript nie sieht).
let accessToken: string | null = null;
const tokenListeners = new Set<(t: string | null) => void>();

export function setAccessToken(t: string | null): void {
  accessToken = t;
  tokenListeners.forEach((l) => l(t));
}
export function getAccessToken(): string | null {
  return accessToken;
}
export function subscribeToken(listener: (t: string | null) => void): () => void {
  tokenListeners.add(listener);
  return () => tokenListeners.delete(listener);
}

// ============================================================================
// Axios-Instance
// ============================================================================
const api = axios.create({
  baseURL: '/api',
  headers: { 'Content-Type': 'application/json' },
  // withCredentials: Cookies werden bei same-origin-Requests mitgeschickt.
  // Wichtig für den /auth/refresh-Endpoint (liest den refresh_token-Cookie).
  withCredentials: true,
});

// Request: Bearer-Header aus dem in-memory-Store
api.interceptors.request.use((config) => {
  if (accessToken) {
    config.headers.Authorization = `Bearer ${accessToken}`;
  }
  return config;
});

// Refresh-Retry-Mechanismus für 401-Antworten.
//
// Wenn der Access-Token abgelaufen ist (15-min-Lifetime), antwortet jeder
// API-Aufruf mit 401. Der Interceptor probiert dann einmal /auth/refresh →
// holt neuen Access-Token (Refresh-Token kommt automatisch via httpOnly-Cookie)
// → wiederholt den ursprünglichen Request transparent. Wenn der Refresh selbst
// scheitert (echt abgemeldet / Cookie weg): wir leiten zur Login-Seite um.
//
// Concurrent-Request-Protection: wenn 401 mehrfach parallel kommt, gibt's
// nur einen aktiven refresh-Aufruf; alle wartenden Requests teilen sich das
// Ergebnis.
let refreshInflight: Promise<string | null> | null = null;
async function doRefresh(): Promise<string | null> {
  if (refreshInflight) return refreshInflight;
  refreshInflight = (async () => {
    try {
      const res = await axios.post<ApiResponse<{ token: string }>>(
        '/api/auth/refresh',
        {},
        { withCredentials: true },
      );
      const newToken = res.data?.data?.token || null;
      setAccessToken(newToken);
      return newToken;
    } catch {
      setAccessToken(null);
      return null;
    } finally {
      refreshInflight = null;
    }
  })();
  return refreshInflight;
}

api.interceptors.response.use(
  (response) => response,
  async (error) => {
    const original = error.config;
    const status = error.response?.status;
    const url: string = original?.url || '';

    // Auth-Endpoints selbst nicht refreshen – sonst Endlos-Schleife
    const isAuthEndpoint =
      url.includes('/auth/login') ||
      url.includes('/auth/customer-login') ||
      url.includes('/auth/refresh') ||
      url.includes('/auth/logout');

    if (status === 401 && !isAuthEndpoint && !original?._retried) {
      original._retried = true;
      const newToken = await doRefresh();
      if (newToken) {
        original.headers = original.headers || {};
        original.headers.Authorization = `Bearer ${newToken}`;
        return api(original);
      }
      // Refresh fehlgeschlagen → echt abmelden + zur Login-Seite
      if (typeof window !== 'undefined' && !window.location.pathname.startsWith('/login')) {
        window.location.href = '/login';
      }
    }

    const message = error.response?.data?.error || error.message || 'Ein Fehler ist aufgetreten';
    return Promise.reject(new Error(message));
  },
);

// Auth
export const authApi = {
  login: async (email: string, password: string) => {
    const res = await api.post<ApiResponse<{ token: string; user: User }>>('/auth/login', { email, password });
    return res.data;
  },
  customerLogin: async (email: string, password: string) => {
    const res = await api.post<ApiResponse<{ token: string; user: User }>>('/auth/customer-login', { email, password });
    return res.data;
  },
  me: async () => {
    const res = await api.get<ApiResponse<User>>('/auth/me');
    return res.data;
  },
  logout: async () => {
    const res = await api.post<ApiResponse<void>>('/auth/logout');
    return res.data;
  },
  changeInitialPortalPassword: async (newPassword: string) => {
    const res = await api.post<ApiResponse<void>>('/auth/change-initial-portal-password', { newPassword });
    return res.data;
  },
  // Kurzlebiger Download-Token (60s) für URL-basierte Aufrufe wie
  // iframe-PDF-Preview oder window.open mit ?token=. Selbst wenn dieser
  // Token in einem Access-Log oder der Browser-History landet, ist er nach
  // einer Minute wertlos.
  getDownloadToken: async (): Promise<string | null> => {
    try {
      const res = await api.post<ApiResponse<{ token: string }>>('/auth/download-token');
      return res.data?.data?.token || null;
    } catch {
      return null;
    }
  },
};

// Customers
export const customerApi = {
  getAll: async (params?: { search?: string; type?: string; page?: number; limit?: number }) => {
    const res = await api.get<ApiResponse<Customer[]>>('/customers', { params });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<Customer>>(`/customers/${id}`);
    return res.data;
  },
  create: async (data: Partial<Customer>) => {
    const res = await api.post<ApiResponse<Customer>>('/customers', data);
    return res.data;
  },
  update: async (id: number, data: Partial<Customer>) => {
    const res = await api.put<ApiResponse<Customer>>(`/customers/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/customers/${id}`);
    return res.data;
  },
  // Portal-Einstellungen
  getPortalSettings: async (customerId: number) => {
    const res = await api.get<ApiResponse<PortalSettings>>(`/customers/${customerId}/portal`);
    return res.data;
  },
  updatePortalSettings: async (customerId: number, data: { portalEnabled?: boolean; portalEmail?: string | null }) => {
    const res = await api.put<ApiResponse<PortalSettings>>(`/customers/${customerId}/portal`, data);
    return res.data;
  },
  setPortalPassword: async (customerId: number, password: string) => {
    const res = await api.post<ApiResponse<void>>(`/customers/${customerId}/portal/password`, { password });
    return res.data;
  },
  getPortalPassword: async (customerId: number) => {
    const res = await api.get<ApiResponse<{ password: string | null }>>(`/customers/${customerId}/portal/password`);
    return res.data;
  },
  generatePortalPassword: async (customerId: number) => {
    const res = await api.post<ApiResponse<{ password: string }>>(`/customers/${customerId}/portal/password/generate`);
    return res.data;
  },
  sendPortalCredentials: async (customerId: number) => {
    const res = await api.post<ApiResponse<void>>(`/customers/${customerId}/portal/send-credentials`);
    return res.data;
  },
  // Vertreter-Verwaltung
  getRepresentatives: async (customerId: number) => {
    const res = await api.get<ApiResponse<CustomerRepresentative[]>>(`/customers/${customerId}/representatives`);
    return res.data;
  },
  addRepresentative: async (customerId: number, representativeId: number, notes?: string) => {
    const res = await api.post<ApiResponse<CustomerRepresentative>>(`/customers/${customerId}/representatives`, { representativeId, notes });
    return res.data;
  },
  removeRepresentative: async (customerId: number, representativeId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/customers/${customerId}/representatives/${representativeId}`);
    return res.data;
  },
  // Persönliche Anrede-Präferenz (Du/Sie) des eingeloggten Mitarbeiters
  // für einen bestimmten Kunden. Fehlender Override → Kunden-Default.
  getSalutationPreference: async (customerId: number) => {
    const res = await api.get<ApiResponse<{ preference: 'DU' | 'SIE'; source: 'user' | 'customer-default' }>>(
      `/customers/${customerId}/salutation-preference`,
    );
    return res.data;
  },
  setSalutationPreference: async (customerId: number, preference: 'DU' | 'SIE') => {
    const res = await api.put<ApiResponse<{ preference: 'DU' | 'SIE'; source: 'user' | 'customer-default' }>>(
      `/customers/${customerId}/salutation-preference`,
      { preference },
    );
    return res.data;
  },
  clearSalutationPreference: async (customerId: number) => {
    const res = await api.delete<ApiResponse<{ preference: 'DU' | 'SIE'; source: 'user' | 'customer-default' }>>(
      `/customers/${customerId}/salutation-preference`,
    );
    return res.data;
  },
  searchForRepresentative: async (customerId: number, search: string) => {
    const res = await api.get<ApiResponse<CustomerSummary[]>>(`/customers/${customerId}/representatives/search`, { params: { search } });
    return res.data;
  },
};

// Werbung ("Geworben / angeworben")
export const referralApi = {
  get: async (customerId: number) => {
    const res = await api.get<ApiResponse<CustomerReferrals>>(`/customers/${customerId}/referrals`);
    return res.data;
  },
  search: async (customerId: number, search: string) => {
    const res = await api.get<ApiResponse<CustomerSummary[]>>(`/customers/${customerId}/referrals/search`, { params: { search } });
    return res.data;
  },
  create: async (
    customerId: number,
    payload: { direction: 'recruitedBy' | 'recruited'; otherCustomerId: number; relationship: string },
  ) => {
    const res = await api.post<ApiResponse<unknown>>(`/customers/${customerId}/referrals`, payload);
    return res.data;
  },
  update: async (
    customerId: number,
    referralId: number,
    payload: { direction: 'recruitedBy' | 'recruited'; otherCustomerId: number; relationship: string },
  ) => {
    const res = await api.put<ApiResponse<unknown>>(`/customers/${customerId}/referrals/${referralId}`, payload);
    return res.data;
  },
  remove: async (customerId: number, referralId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/customers/${customerId}/referrals/${referralId}`);
    return res.data;
  },
};

// Firmenstammdaten (Absender für Gutschrift-PDF/ZUGFeRD)
export const companyProfileApi = {
  get: async () => {
    const res = await api.get<ApiResponse<CompanyProfile>>('/company-profile');
    return res.data;
  },
  update: async (payload: Partial<CompanyProfile>) => {
    const res = await api.put<ApiResponse<CompanyProfile>>('/company-profile', payload);
    return res.data;
  },
};

// Gutschriften (Subventionen am Vertrag)
export const creditNoteApi = {
  listAll: async (params?: { page?: number; limit?: number; search?: string }) => {
    const res = await api.get<ApiResponse<{ items: CreditNoteListItem[]; pagination: { page: number; limit: number; total: number; totalPages: number } }>>('/credit-notes', { params });
    return res.data;
  },
  listByContract: async (contractId: number) => {
    const res = await api.get<ApiResponse<CreditNote[]>>(`/contracts/${contractId}/credit-notes`);
    return res.data;
  },
  getDefaults: async (contractId: number) => {
    const res = await api.get<ApiResponse<CreditNoteDefaults>>(`/contracts/${contractId}/credit-notes/defaults`);
    return res.data;
  },
  create: async (contractId: number, payload: Record<string, unknown>) => {
    const res = await api.post<ApiResponse<CreditNote>>(`/contracts/${contractId}/credit-notes`, payload);
    return res.data;
  },
  get: async (id: number) => {
    const res = await api.get<ApiResponse<CreditNote>>(`/credit-notes/${id}`);
    return res.data;
  },
  update: async (id: number, payload: Record<string, unknown>) => {
    const res = await api.put<ApiResponse<CreditNote>>(`/credit-notes/${id}`, payload);
    return res.data;
  },
  remove: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/credit-notes/${id}`);
    return res.data;
  },
  generatePdf: async (id: number) => {
    const res = await api.post<ApiResponse<{ pdfPath: string }>>(`/credit-notes/${id}/pdf`, {});
    return res.data;
  },
  getNumberRange: async () => {
    const res = await api.get<ApiResponse<CreditNoteNumberRange>>(`/credit-notes/number-range`);
    return res.data;
  },
  updateNumberRange: async (payload: Partial<CreditNoteNumberRange>) => {
    const res = await api.put<ApiResponse<CreditNoteNumberRange>>(`/credit-notes/number-range`, payload);
    return res.data;
  },
  getDeliveryNoteNumberRange: async () => {
    const res = await api.get<ApiResponse<CreditNoteNumberRange>>(`/credit-notes/delivery-note-number-range`);
    return res.data;
  },
  updateDeliveryNoteNumberRange: async (payload: Partial<CreditNoteNumberRange>) => {
    const res = await api.put<ApiResponse<CreditNoteNumberRange>>(`/credit-notes/delivery-note-number-range`, payload);
    return res.data;
  },
  uploadReceipt: async (id: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ receiptPath: string }>>(`/upload/credit-notes/${id}/receipt`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteReceipt: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/credit-notes/${id}/receipt`);
    return res.data;
  },
};

// Addresses
export const addressApi = {
  getByCustomer: async (customerId: number) => {
    const res = await api.get<ApiResponse<Address[]>>(`/customers/${customerId}/addresses`);
    return res.data;
  },
  create: async (customerId: number, data: Partial<Address>) => {
    const res = await api.post<ApiResponse<Address>>(`/customers/${customerId}/addresses`, data);
    return res.data;
  },
  update: async (id: number, data: Partial<Address>) => {
    const res = await api.put<ApiResponse<Address>>(`/addresses/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/addresses/${id}`);
    return res.data;
  },
};

// Bank Cards
export const bankCardApi = {
  getByCustomer: async (customerId: number, showInactive = false) => {
    const res = await api.get<ApiResponse<BankCard[]>>(`/customers/${customerId}/bank-cards`, { params: { showInactive } });
    return res.data;
  },
  create: async (customerId: number, data: Partial<BankCard>) => {
    const res = await api.post<ApiResponse<BankCard>>(`/customers/${customerId}/bank-cards`, data);
    return res.data;
  },
  update: async (id: number, data: Partial<BankCard>) => {
    const res = await api.put<ApiResponse<BankCard>>(`/bank-cards/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/bank-cards/${id}`);
    return res.data;
  },
  // IBAN-Prüfung + BIC/Bank-Nachschlag (offline, Bundesbank-BLZ) – die IBAN
  // verlässt nur unser eigenes Backend, kein Dritt-Dienst.
  ibanLookup: async (iban: string) => {
    const res = await api.post<ApiResponse<IbanLookupResult>>(`/bank-cards/iban-lookup`, { iban });
    return res.data;
  },
};

export interface IbanLookupResult {
  valid: boolean;
  iban: string;
  country?: string;
  bic?: string | null;
  bankName?: string | null;
  blz?: string | null;
}

// Identity Documents
export const documentApi = {
  getByCustomer: async (customerId: number, showInactive = false) => {
    const res = await api.get<ApiResponse<IdentityDocument[]>>(`/customers/${customerId}/documents`, { params: { showInactive } });
    return res.data;
  },
  create: async (customerId: number, data: Partial<IdentityDocument>) => {
    const res = await api.post<ApiResponse<IdentityDocument>>(`/customers/${customerId}/documents`, data);
    return res.data;
  },
  update: async (id: number, data: Partial<IdentityDocument>) => {
    const res = await api.put<ApiResponse<IdentityDocument>>(`/documents/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/documents/${id}`);
    return res.data;
  },
};

// Meters
export const meterApi = {
  getByCustomer: async (customerId: number, showInactive = false) => {
    const res = await api.get<ApiResponse<Meter[]>>(`/customers/${customerId}/meters`, { params: { showInactive } });
    return res.data;
  },
  create: async (customerId: number, data: Partial<Meter>) => {
    const res = await api.post<ApiResponse<Meter>>(`/customers/${customerId}/meters`, data);
    return res.data;
  },
  update: async (id: number, data: Partial<Meter>) => {
    const res = await api.put<ApiResponse<Meter>>(`/meters/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/meters/${id}`);
    return res.data;
  },
  getReadings: async (meterId: number) => {
    const res = await api.get<ApiResponse<MeterReading[]>>(`/meters/${meterId}/readings`);
    return res.data;
  },
  addReading: async (meterId: number, data: Partial<MeterReading>) => {
    const res = await api.post<ApiResponse<MeterReading>>(`/meters/${meterId}/readings`, data);
    return res.data;
  },
  updateReading: async (meterId: number, readingId: number, data: Partial<MeterReading>) => {
    const res = await api.put<ApiResponse<MeterReading>>(`/meters/${meterId}/readings/${readingId}`, data);
    return res.data;
  },
  deleteReading: async (meterId: number, readingId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/meters/${meterId}/readings/${readingId}`);
    return res.data;
  },
  // Portal: Zählerstand melden
  reportReading: async (meterId: number, data: { value: number; readingDate?: string; notes?: string }) => {
    const res = await api.post<ApiResponse<MeterReading>>(`/meters/${meterId}/readings/report`, data);
    return res.data;
  },
  getMyMeters: async () => {
    const res = await api.get<ApiResponse<Meter[]>>('/meters/my-meters');
    return res.data;
  },
  // Status-Update
  markTransferred: async (meterId: number, readingId: number) => {
    const res = await api.patch<ApiResponse<MeterReading>>(`/meters/${meterId}/readings/${readingId}/transfer`);
    return res.data;
  },
};

// Invoice API
export const invoiceApi = {
  getInvoices: async (ecdId: number) => {
    const res = await api.get<ApiResponse<Invoice[]>>(`/energy-details/${ecdId}/invoices`);
    return res.data;
  },
  addInvoice: async (ecdId: number, data: Partial<Invoice>) => {
    const res = await api.post<ApiResponse<Invoice>>(`/energy-details/${ecdId}/invoices`, data);
    return res.data;
  },
  addInvoiceByContract: async (contractId: number, data: Partial<Invoice>) => {
    const res = await api.post<ApiResponse<Invoice>>(`/contracts/${contractId}/invoices`, data);
    return res.data;
  },
  updateInvoice: async (ecdId: number, invoiceId: number, data: Partial<Invoice>) => {
    const res = await api.put<ApiResponse<Invoice>>(`/energy-details/${ecdId}/invoices/${invoiceId}`, data);
    return res.data;
  },
  deleteInvoice: async (ecdId: number, invoiceId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/energy-details/${ecdId}/invoices/${invoiceId}`);
    return res.data;
  },
  uploadDocument: async (invoiceId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(
      `/upload/invoices/${invoiceId}`,
      formData,
      { headers: { 'Content-Type': 'multipart/form-data' } }
    );
    return res.data;
  },
  deleteDocument: async (invoiceId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/invoices/${invoiceId}`);
    return res.data;
  },
};

// Stressfrei-Wechseln E-Mail-Adressen
export interface StressfreiEmail {
  id: number;
  customerId: number;
  email: string;
  platform?: string;
  notes?: string;
  isActive: boolean;
  isProvisioned?: boolean;
  hasMailbox: boolean;
  /** Zusätzliche Weiterleitungs-E-Mails als JSON-Array-String. */
  additionalForwardingEmails?: string | null;
  createdAt: string;
  updatedAt: string;
}

// Mailbox-Konto (für Dropdown-Auswahl)
export interface MailboxAccount {
  id: number;
  email: string;
  notes?: string;
  hasMailbox: boolean;
  _count: {
    cachedEmails: number;
  };
}

// Gecachte E-Mail
export interface CachedEmail {
  id: number;
  stressfreiEmailId: number;
  folder: 'INBOX' | 'SENT';
  messageId: string;
  uid: number;
  subject?: string;
  fromAddress: string;
  fromName?: string;
  toAddresses: string; // JSON Array
  ccAddresses?: string; // JSON Array
  receivedAt: string;
  textBody?: string;
  htmlBody?: string;
  hasAttachments: boolean;
  attachmentNames?: string; // JSON Array
  contractId?: number;
  assignedAt?: string;
  assignedBy?: number;
  isAutoAssigned?: boolean; // true = automatisch beim Senden aus Vertrag zugeordnet
  isRead: boolean;
  isStarred: boolean;
  isDeleted: boolean;
  deletedAt?: string;
  createdAt: string;
  updatedAt: string;
  stressfreiEmail?: {
    id: number;
    email: string;
    customerId: number;
  };
  contract?: {
    id: number;
    contractNumber: string;
  } | null;
}

export interface SyncResult {
  newEmails: number;
  totalEmails: number;
}

export interface EmailAttachment {
  filename: string;
  content: string;       // Base64-kodierter Inhalt
  contentType?: string;  // MIME-Type (z.B. 'application/pdf')
}

export interface SendEmailParams {
  to: string | string[];
  cc?: string | string[];
  subject: string;
  text?: string;
  html?: string;
  inReplyTo?: string;
  references?: string[];
  attachments?: EmailAttachment[];
  contractId?: number; // Vertrag dem die gesendete E-Mail zugeordnet wird
}

// Anhang-Speicher-Ziele
export interface AttachmentTargetSlot {
  key: string;
  label: string;
  field: string;
  hasDocument: boolean;
  currentPath?: string;
}

export interface AttachmentEntityWithSlots {
  id: number;
  label: string;
  slots: AttachmentTargetSlot[];
}

export interface AttachmentTargetsResponse {
  customer: {
    id: number;
    name: string;
    type: 'PRIVATE' | 'BUSINESS';
    slots: AttachmentTargetSlot[];
  };
  identityDocuments: AttachmentEntityWithSlots[];
  bankCards: AttachmentEntityWithSlots[];
  contract?: {
    id: number;
    contractNumber: string;
    type: string;
    energyDetailsId?: number;
    slots: AttachmentTargetSlot[];
  };
}

export const stressfreiEmailApi = {
  getByCustomer: async (customerId: number, includeInactive = false) => {
    const res = await api.get<ApiResponse<StressfreiEmail[]>>(`/customers/${customerId}/stressfrei-emails`, { params: { includeInactive } });
    return res.data;
  },
  create: async (customerId: number, data: {
    email: string;
    platform?: string;
    notes?: string;
    provisionAtProvider?: boolean;
    createMailbox?: boolean;
  }) => {
    const res = await api.post<ApiResponse<StressfreiEmail>>(`/customers/${customerId}/stressfrei-emails`, data);
    return res.data;
  },
  update: async (id: number, data: Partial<StressfreiEmail>) => {
    const res = await api.put<ApiResponse<StressfreiEmail>>(`/stressfrei-emails/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/stressfrei-emails/${id}`);
    return res.data;
  },
  // Mailbox nachträglich aktivieren
  enableMailbox: async (id: number) => {
    const res = await api.post<ApiResponse<null>>(`/stressfrei-emails/${id}/enable-mailbox`);
    return res.data;
  },
  // Mailbox-Status mit Provider synchronisieren
  syncMailboxStatus: async (id: number) => {
    const res = await api.post<ApiResponse<{ hasMailbox: boolean; wasUpdated: boolean }>>(`/stressfrei-emails/${id}/sync-mailbox-status`);
    return res.data;
  },
  // Mailbox-Zugangsdaten abrufen (IMAP/SMTP)
  getMailboxCredentials: async (id: number) => {
    const res = await api.get<ApiResponse<{
      email: string;
      password: string;
      imap: { server: string; port: number; encryption: string } | null;
      smtp: { server: string; port: number; encryption: string } | null;
    }>>(`/stressfrei-emails/${id}/credentials`);
    return res.data;
  },
  // Passwort zurücksetzen (generiert neues Passwort beim Provider)
  resetPassword: async (id: number) => {
    const res = await api.post<ApiResponse<{ password: string }>>(`/stressfrei-emails/${id}/reset-password`);
    return res.data;
  },
  // Weiterleitungen neu setzen (z.B. nach Änderung der Kunden-Stamm-E-Mail).
  // Wenn die Adresse hasMailbox=true ist, wird zusätzlich das im CRM
  // hinterlegte Passwort am Provider neu gesetzt (Self-Healing).
  syncForwarding: async (id: number) => {
    const res = await api.post<ApiResponse<{
      forwardTargets: string[];
      customerEmail: string;
      passwordReset?: boolean;
    }>>(`/stressfrei-emails/${id}/sync-forwarding`);
    return res.data;
  },
  // Zusätzliche Weiterleitungs-Adressen ersetzen + sofort am Provider syncen.
  updateAdditionalForwards: async (id: number, emails: string[]) => {
    const res = await api.put<ApiResponse<{ forwardTargets: string[] }>>(
      `/stressfrei-emails/${id}/additional-forwards`,
      { emails },
    );
    return res.data;
  },
  // E-Mails synchronisieren
  syncEmails: async (id: number, fullSync = false) => {
    const res = await api.post<ApiResponse<SyncResult>>(`/stressfrei-emails/${id}/sync`, {}, { params: { full: fullSync } });
    return res.data;
  },
  // E-Mail senden
  sendEmail: async (id: number, params: SendEmailParams) => {
    const res = await api.post<ApiResponse<{ messageId: string }>>(`/stressfrei-emails/${id}/send`, params);
    return res.data;
  },
  // Ordner-Anzahlen abrufen (total und ungelesen pro Ordner)
  getFolderCounts: async (id: number) => {
    const res = await api.get<ApiResponse<{
      inbox: number;
      inboxUnread: number;
      sent: number;
      sentUnread: number;
      spam: number;
      spamUnread: number;
      trash: number;
      trashUnread: number;
    }>>(`/stressfrei-emails/${id}/folder-counts`);
    return res.data;
  },
};

// Cached Email API (E-Mail-Client)
export interface EmailFilterParams {
  accountId?: number;
  folder?: 'INBOX' | 'SENT' | 'SPAM';
  limit?: number;
  offset?: number;
  // Suche / Filter (alle AND-verknüpft)
  search?: string;
  fromFilter?: string;
  toFilter?: string;
  subjectFilter?: string;
  bodyFilter?: string;
  attachmentNameFilter?: string;
  hasAttachments?: boolean;
  isRead?: boolean;
  isStarred?: boolean;
  receivedFrom?: string;   // ISO date
  receivedTo?: string;     // ISO date
}

export const cachedEmailApi = {
  // E-Mails für Kunden abrufen
  getForCustomer: async (customerId: number, options?: EmailFilterParams) => {
    const res = await api.get<ApiResponse<CachedEmail[]>>(`/customers/${customerId}/emails`, { params: options });
    return res.data;
  },
  // E-Mails für Vertrag abrufen (optional pro Postfach gefiltert)
  getForContract: async (
    contractId: number,
    options?: { folder?: 'INBOX' | 'SENT'; accountId?: number; limit?: number; offset?: number },
  ) => {
    const res = await api.get<ApiResponse<CachedEmail[]>>(`/contracts/${contractId}/emails`, { params: options });
    return res.data;
  },
  // Ordner-Anzahlen für Vertrag abrufen (zugeordnete E-Mails, optional pro Postfach)
  getContractFolderCounts: async (contractId: number, accountId?: number) => {
    const res = await api.get<ApiResponse<{
      inbox: number;
      inboxUnread: number;
      sent: number;
      sentUnread: number;
      trash: number;
      trashUnread: number;
    }>>(`/contracts/${contractId}/emails/folder-counts`, { params: accountId ? { accountId } : undefined });
    return res.data;
  },
  // Mailbox-Konten eines Kunden abrufen
  getMailboxAccounts: async (customerId: number) => {
    const res = await api.get<ApiResponse<MailboxAccount[]>>(`/customers/${customerId}/mailbox-accounts`);
    return res.data;
  },
  // Einzelne E-Mail abrufen (mit Body)
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<CachedEmail>>(`/emails/${id}`);
    return res.data;
  },
  // E-Mail-Thread abrufen
  getThread: async (id: number) => {
    const res = await api.get<ApiResponse<CachedEmail[]>>(`/emails/${id}/thread`);
    return res.data;
  },
  // Als gelesen/ungelesen markieren
  markAsRead: async (id: number, isRead: boolean) => {
    const res = await api.patch<ApiResponse<void>>(`/emails/${id}/read`, { isRead });
    return res.data;
  },
  // Stern umschalten
  toggleStar: async (id: number) => {
    const res = await api.post<ApiResponse<{ isStarred: boolean }>>(`/emails/${id}/star`);
    return res.data;
  },
  // Vertrag zuordnen
  assignToContract: async (emailId: number, contractId: number) => {
    const res = await api.post<ApiResponse<CachedEmail>>(`/emails/${emailId}/assign`, { contractId });
    return res.data;
  },
  // Zuordnung aufheben
  unassignFromContract: async (emailId: number) => {
    const res = await api.delete<ApiResponse<CachedEmail>>(`/emails/${emailId}/assign`);
    return res.data;
  },
  // E-Mail löschen (nur Admin)
  delete: async (emailId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/emails/${emailId}`);
    return res.data;
  },
  // Anhang-URL (view=true für inline anzeigen, sonst download)
  // Hinweis: gibt die URL mit dem aktuellen Access-Token als Query-Param zurück,
  // weil <iframe>/<a> keinen Authorization-Header senden können. Der Token läuft
  // nach 15 min ab – wenn Anhang dann geöffnet wird, kommt 401; UI muss in dem
  // Fall die URL frisch holen.
  getAttachmentUrl: (emailId: number, filename: string, view?: boolean) => {
    const token = getAccessToken();
    const encodedFilename = encodeURIComponent(filename);
    const viewParam = view ? '&view=true' : '';
    return `${api.defaults.baseURL}/emails/${emailId}/attachments/${encodedFilename}?token=${token || ''}${viewParam}`;
  },
  // Ungelesene E-Mails zählen
  getUnreadCount: async (params: { customerId?: number; contractId?: number }) => {
    const res = await api.get<ApiResponse<{ count: number }>>('/emails/unread-count', { params });
    return res.data;
  },
  // ==================== PAPIERKORB ====================
  // Papierkorb-E-Mails für Kunden abrufen (optional pro Postfach/Vertrag gefiltert)
  getTrash: async (customerId: number, options?: { accountId?: number; contractId?: number }) => {
    const res = await api.get<ApiResponse<CachedEmail[]>>(`/customers/${customerId}/emails/trash`, { params: options });
    return res.data;
  },
  // Papierkorb-Anzahl für Kunden (gleiche Filter wie getTrash)
  getTrashCount: async (customerId: number, options?: { accountId?: number; contractId?: number }) => {
    const res = await api.get<ApiResponse<{ count: number }>>(`/customers/${customerId}/emails/trash/count`, { params: options });
    return res.data;
  },
  // E-Mail aus Papierkorb wiederherstellen
  restore: async (emailId: number) => {
    const res = await api.post<ApiResponse<void>>(`/emails/${emailId}/restore`);
    return res.data;
  },
  // E-Mail endgültig löschen (aus Papierkorb)
  permanentDelete: async (emailId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/emails/${emailId}/permanent`);
    return res.data;
  },
  // ==================== ANHANG-SPEICHERUNG ====================
  // Verfügbare Dokumenten-Ziele für Anhänge abrufen
  getAttachmentTargets: async (emailId: number) => {
    const res = await api.get<ApiResponse<AttachmentTargetsResponse>>(`/emails/${emailId}/attachment-targets`);
    return res.data;
  },
  // Anhang in Dokumentenfeld speichern
  saveAttachmentTo: async (emailId: number, filename: string, params: { entityType: string; entityId?: number; targetKey: string }) => {
    const encodedFilename = encodeURIComponent(filename);
    const res = await api.post<ApiResponse<{ path: string; filename: string; originalName: string; size: number }>>(
      `/emails/${emailId}/attachments/${encodedFilename}/save-to`,
      params
    );
    return res.data;
  },
  // E-Mail als PDF speichern
  saveEmailAsPdf: async (emailId: number, params: { entityType: string; entityId?: number; targetKey: string }) => {
    const res = await api.post<ApiResponse<{ path: string; filename: string; size: number }>>(
      `/emails/${emailId}/save-as-pdf`,
      params
    );
    return res.data;
  },
  // E-Mail als Rechnung speichern (für Energieverträge)
  saveEmailAsInvoice: async (emailId: number, params: { invoiceDate: string; invoiceType: string; notes?: string }) => {
    const res = await api.post<ApiResponse<{ id: number; invoiceDate: string; invoiceType: string; documentPath: string }>>(
      `/emails/${emailId}/save-as-invoice`,
      params
    );
    return res.data;
  },
  // E-Mail als Vertragsdokument speichern (PDF aus der Mail wird als
  // ContractDocument hinterlegt – parallel zur Anhang-Variante)
  saveEmailAsContractDocument: async (
    emailId: number,
    params: { documentType: string; notes?: string; deliveryDate?: string },
  ) => {
    const res = await api.post<ApiResponse<{ id: number; documentType: string; documentPath: string }>>(
      `/emails/${emailId}/save-as-contract-document`,
      params,
    );
    return res.data;
  },
  // Anhang als Rechnung speichern (für Energieverträge)
  saveAttachmentAsInvoice: async (emailId: number, filename: string, params: { invoiceDate: string; invoiceType: string; notes?: string }) => {
    const encodedFilename = encodeURIComponent(filename);
    const res = await api.post<ApiResponse<{ id: number; invoiceDate: string; invoiceType: string; documentPath: string }>>(
      `/emails/${emailId}/attachments/${encodedFilename}/save-as-invoice`,
      params
    );
    return res.data;
  },
  saveAttachmentAsContractDocument: async (
    emailId: number,
    filename: string,
    params: { documentType: string; notes?: string; deliveryDate?: string },
  ) => {
    const encodedFilename = encodeURIComponent(filename);
    const res = await api.post<ApiResponse<{ id: number; documentType: string; documentPath: string }>>(
      `/emails/${emailId}/attachments/${encodedFilename}/save-as-contract-document`,
      params,
    );
    return res.data;
  },
};

// Contracts - Vertragsbaum für Kundenansicht
export interface ContractTreeNodeContract {
  id: number;
  contractNumber: string;
  type: string;
  status: string;
  startDate: string | null;
  endDate: string | null;
  cancellationConfirmationDate?: string | null;
  providerName: string | null;
  tariffName: string | null;
  previousContractId: number | null;
  provider?: { id: number; name: string } | null;
  tariff?: { id: number; name: string } | null;
  contractCategory?: { id: number; name: string } | null;
  customer?: { id: number; firstName: string; lastName: string; companyName: string | null; customerNumber: string } | null;
  address?: { street: string; houseNumber: string; postalCode: string; city: string } | null;
  mobileDetails?: {
    phoneNumber: string | null;
    mobileNetwork?: string | null;
    simCards: { phoneNumber: string | null; isMain: boolean; cardUser?: string | null }[];
  } | null;
  carInsuranceDetails?: { licensePlate: string | null } | null;
}

export interface ContractTreeNode {
  contract: ContractTreeNodeContract;
  predecessors: ContractTreeNode[];
  hasHistory: boolean;
}

export const contractApi = {
  getAll: async (params?: { customerId?: number; type?: string; status?: string; search?: string; page?: number; limit?: number; includeDeactivated?: boolean }) => {
    const query = params?.includeDeactivated
      ? { ...params, includeDeactivated: 'true' }
      : params;
    const res = await api.get<ApiResponse<Contract[]>>('/contracts', { params: query });
    return res.data;
  },
  getTreeForCustomer: async (customerId: number, includeDeactivated = false) => {
    const res = await api.get<ApiResponse<ContractTreeNode[]>>('/contracts', {
      params: { customerId, tree: 'true', ...(includeDeactivated ? { includeDeactivated: 'true' } : {}) },
    });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<Contract>>(`/contracts/${id}`);
    return res.data;
  },
  create: async (data: Partial<Contract> & { [key: string]: unknown }) => {
    const res = await api.post<ApiResponse<Contract>>('/contracts', data);
    return res.data;
  },
  update: async (id: number, data: Partial<Contract> & { [key: string]: unknown }) => {
    const res = await api.put<ApiResponse<Contract>>(`/contracts/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/contracts/${id}`);
    return res.data;
  },
  createFollowUp: async (id: number) => {
    const res = await api.post<ApiResponse<Contract>>(`/contracts/${id}/follow-up`);
    return res.data;
  },
  createRenewal: async (id: number) => {
    const res = await api.post<ApiResponse<Contract>>(`/contracts/${id}/renewal`);
    return res.data;
  },
  getPassword: async (id: number) => {
    const res = await api.get<ApiResponse<{ password: string }>>(`/contracts/${id}/password`);
    return res.data;
  },
  getSimCardCredentials: async (simCardId: number) => {
    const res = await api.get<ApiResponse<{ pin: string | null; puk: string | null }>>(`/contracts/simcard/${simCardId}/credentials`);
    return res.data;
  },
  getInternetCredentials: async (contractId: number) => {
    const res = await api.get<ApiResponse<{ password: string | null }>>(`/contracts/${contractId}/internet-credentials`);
    return res.data;
  },
  getSipCredentials: async (phoneNumberId: number) => {
    const res = await api.get<ApiResponse<{ password: string | null }>>(`/contracts/phonenumber/${phoneNumberId}/sip-credentials`);
    return res.data;
  },
  // Vertrags-Cockpit
  getCockpit: async () => {
    const res = await api.get<ApiResponse<import('../types').CockpitResult>>('/contracts/cockpit');
    return res.data;
  },
  // Vertragsdokumente
  getDocuments: async (contractId: number) => {
    const res = await api.get<ApiResponse<import('../types').ContractDocument[]>>(`/contracts/${contractId}/documents`);
    return res.data;
  },
  uploadDocument: async (contractId: number, file: File, documentType: string, notes?: string, deliveryDate?: string) => {
    const formData = new FormData();
    formData.append('file', file);
    formData.append('documentType', documentType);
    if (notes) formData.append('notes', notes);
    if (deliveryDate) formData.append('deliveryDate', deliveryDate);
    const res = await api.post<ApiResponse<import('../types').ContractDocument>>(`/contracts/${contractId}/documents`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteDocument: async (contractId: number, documentId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/contracts/${contractId}/documents/${documentId}`);
    return res.data;
  },
  // Folgezähler
  addSuccessorMeter: async (contractId: number, data: { meterId: number; installedAt?: string; finalReadingPrevious?: number; deactivatePredecessor?: boolean }) => {
    const res = await api.post<ApiResponse<any>>(`/contracts/${contractId}/successor-meter`, data);
    return res.data;
  },
  removeContractMeter: async (contractId: number, contractMeterId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/contracts/${contractId}/contract-meter/${contractMeterId}`);
    return res.data;
  },
  // Snooze: Vertrag zurückstellen
  snooze: async (id: number, data: { nextReviewDate?: string; months?: number }) => {
    const res = await api.patch<ApiResponse<{ id: number; contractNumber: string; nextReviewDate: string | null }>>(`/contracts/${id}/snooze`, data);
    return res.data;
  },
};

// Contract History (Vertragshistorie - nur intern)
export const contractHistoryApi = {
  getByContract: async (contractId: number) => {
    const res = await api.get<ApiResponse<ContractHistoryEntry[]>>(`/contracts/${contractId}/history`);
    return res.data;
  },
  create: async (contractId: number, data: { title: string; description?: string }) => {
    const res = await api.post<ApiResponse<ContractHistoryEntry>>(`/contracts/${contractId}/history`, data);
    return res.data;
  },
  update: async (contractId: number, entryId: number, data: { title?: string; description?: string }) => {
    const res = await api.put<ApiResponse<ContractHistoryEntry>>(`/contracts/${contractId}/history/${entryId}`, data);
    return res.data;
  },
  delete: async (contractId: number, entryId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/contracts/${contractId}/history/${entryId}`);
    return res.data;
  },
};

// Contract Tasks (Aufgaben)
export const contractTaskApi = {
  // Alle Tasks über alle Verträge (für Task-Liste & Dashboard)
  getAll: async (params?: { status?: ContractTaskStatus; customerId?: number }) => {
    const res = await api.get<ApiResponse<ContractTask[]>>('/tasks', { params });
    return res.data;
  },
  // Task-Statistik (offene Aufgaben)
  getStats: async () => {
    const res = await api.get<ApiResponse<{ openCount: number }>>('/tasks/stats');
    return res.data;
  },
  // Tasks für einen spezifischen Vertrag
  getByContract: async (contractId: number, status?: ContractTaskStatus) => {
    const res = await api.get<ApiResponse<ContractTask[]>>(`/contracts/${contractId}/tasks`, { params: { status } });
    return res.data;
  },
  create: async (contractId: number, data: { title: string; description?: string; visibleInPortal?: boolean }) => {
    const res = await api.post<ApiResponse<ContractTask>>(`/contracts/${contractId}/tasks`, data);
    return res.data;
  },
  // Allgemeine Aufgabe ohne Vertrag/Kunde (nur Mitarbeiter).
  createGeneral: async (data: { title: string; description?: string }) => {
    const res = await api.post<ApiResponse<ContractTask>>(`/tasks`, data);
    return res.data;
  },
  update: async (taskId: number, data: { title?: string; description?: string; visibleInPortal?: boolean }) => {
    const res = await api.put<ApiResponse<ContractTask>>(`/tasks/${taskId}`, data);
    return res.data;
  },
  complete: async (taskId: number) => {
    const res = await api.post<ApiResponse<ContractTask>>(`/tasks/${taskId}/complete`);
    return res.data;
  },
  reopen: async (taskId: number) => {
    const res = await api.post<ApiResponse<ContractTask>>(`/tasks/${taskId}/reopen`);
    return res.data;
  },
  delete: async (taskId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/tasks/${taskId}`);
    return res.data;
  },
  // Subtasks
  createSubtask: async (taskId: number, title: string) => {
    const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/tasks/${taskId}/subtasks`, { title });
    return res.data;
  },
  // Kundenportal: Antwort auf eigenes Ticket
  createReply: async (taskId: number, title: string) => {
    const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/tasks/${taskId}/reply`, { title });
    return res.data;
  },
  updateSubtask: async (subtaskId: number, title: string) => {
    const res = await api.put<ApiResponse<ContractTaskSubtask>>(`/subtasks/${subtaskId}`, { title });
    return res.data;
  },
  completeSubtask: async (subtaskId: number) => {
    const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/subtasks/${subtaskId}/complete`);
    return res.data;
  },
  reopenSubtask: async (subtaskId: number) => {
    const res = await api.post<ApiResponse<ContractTaskSubtask>>(`/subtasks/${subtaskId}/reopen`);
    return res.data;
  },
  deleteSubtask: async (subtaskId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/subtasks/${subtaskId}`);
    return res.data;
  },
  // Support-Ticket erstellen (für Kundenportal)
  createSupportTicket: async (contractId: number, data: { title: string; description?: string }) => {
    const res = await api.post<ApiResponse<ContractTask>>(`/contracts/${contractId}/support-ticket`, data);
    return res.data;
  },
};

// App Settings
export const appSettingsApi = {
  getPublic: async () => {
    const res = await api.get<ApiResponse<Record<string, string>>>('/settings/public');
    return res.data;
  },
  getAll: async () => {
    const res = await api.get<ApiResponse<Record<string, string>>>('/settings');
    return res.data;
  },
  update: async (settings: Record<string, string>) => {
    const res = await api.put<ApiResponse<void>>('/settings', settings);
    return res.data;
  },
  updateOne: async (key: string, value: string) => {
    const res = await api.put<ApiResponse<void>>(`/settings/${key}`, { value });
    return res.data;
  },
};

// BLZ-/Bankdaten (Bundesbank-Bankleitzahlen) – Status + Auto-Update
export interface BlzStatus {
  activeSource: 'volume' | 'builtin';
  activeVersion: string;
  builtinVersion: string;
  entryCount: number;
  nextValidFrom: string | null;
  fetchedAt: string | null;
  autoUpdateEnabled: boolean;
  intervalDays: number;
  lastCheckedAt: string | null;
  lastUpdatedAt: string | null;
  latestVersion: string | null;
  updateAvailable: boolean;
  lastError: string | null;
}

export const blzDataApi = {
  getStatus: async () => {
    const res = await api.get<ApiResponse<BlzStatus>>('/settings/blz');
    return res.data;
  },
  updateNow: async (force = false) => {
    const res = await api.post<ApiResponse<{ result: { changed: boolean; version: string; message: string }; status: BlzStatus }>>(
      `/settings/blz/update-now${force ? '?force=1' : ''}`,
    );
    return res.data;
  },
};

// Backup & Restore
export interface BackupInfo {
  name: string;
  timestamp: string;
  totalRecords: number;
  tables: { table: string; count: number }[];
  sizeBytes: number;
  hasUploads: boolean;
  uploadSizeBytes: number;
}

export const backupApi = {
  list: async () => {
    const res = await api.get<ApiResponse<BackupInfo[]>>('/settings/backups');
    return res.data;
  },
  create: async () => {
    const res = await api.post<ApiResponse<{ backupName: string }>>('/settings/backup');
    return res.data;
  },
  restore: async (name: string) => {
    // Server erzwingt confirm-Body als Schutz gegen versehentliche
    // Datenüberschreibung (Pentest 2026-05-19 KRITISCH, Analog zu
    // factoryReset). Der Confirm-String muss exakt dieser Wert sein.
    const res = await api.post<ApiResponse<{ restoredRecords: number; restoredFiles: number }>>(
      `/settings/backup/${name}/restore`,
      { confirm: 'RESTORE-BESTAETIGT' },
    );
    return res.data;
  },
  delete: async (name: string) => {
    const res = await api.delete<ApiResponse<void>>(`/settings/backup/${name}`);
    return res.data;
  },
  getDownloadUrl: (name: string) => {
    return `/api/settings/backup/${name}/download`;
  },
  upload: async (file: File) => {
    const formData = new FormData();
    formData.append('backup', file);
    const res = await api.post<ApiResponse<{ backupName: string }>>('/settings/backup/upload', formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  factoryReset: async () => {
    // Server erzwingt confirm-Body als Schutz gegen versehentliche
    // DB-Plättung (Pentest Runde 11). Der Confirm-String muss exakt
    // dieser Wert sein.
    const res = await api.post<ApiResponse<void>>('/settings/factory-reset', {
      confirm: 'FACTORY-RESET-BESTAETIGT',
    });
    return res.data;
  },
};

export interface BackupLogEntry {
  id: number;
  operation: 'CREATE' | 'RESTORE';
  backupName: string | null;
  success: boolean;
  durationMs: number;
  summary: string;
  userEmail: string | null;
  ipAddress: string | null;
  createdAt: string;
}
export interface BackupLogDetail extends BackupLogEntry {
  fullLog: string;
}
export const backupLogApi = {
  list: async (operation: 'CREATE' | 'RESTORE') => {
    const res = await api.get<ApiResponse<BackupLogEntry[]>>('/settings/backup-logs', {
      params: { operation, limit: 50 },
    });
    return res.data;
  },
  get: async (id: number) => {
    const res = await api.get<ApiResponse<BackupLogDetail>>(`/settings/backup-logs/${id}`);
    return res.data;
  },
};

// Rate-Limit-Verwaltung (Admin)
export interface ActiveRateLimit {
  ipAddress: string;
  email: string | null;
  lastHit: string;
  hitCount: number;
  lastEndpoint: string | null;
  limiters: string[];
}
export const rateLimitApi = {
  getActive: async () => {
    const res = await api.get<ApiResponse<ActiveRateLimit[]>>('/settings/rate-limits/active');
    return res.data;
  },
  reset: async (body: { ipAddress: string; email?: string }) => {
    const res = await api.post<ApiResponse<void>>('/settings/rate-limits/reset', body);
    return res.data;
  },
};

// Platforms
export const platformApi = {
  getAll: async (includeInactive = false) => {
    const res = await api.get<ApiResponse<SalesPlatform[]>>('/platforms', { params: { includeInactive } });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<SalesPlatform>>(`/platforms/${id}`);
    return res.data;
  },
  create: async (data: Partial<SalesPlatform>) => {
    const res = await api.post<ApiResponse<SalesPlatform>>('/platforms', data);
    return res.data;
  },
  update: async (id: number, data: Partial<SalesPlatform>) => {
    const res = await api.put<ApiResponse<SalesPlatform>>(`/platforms/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/platforms/${id}`);
    return res.data;
  },
};

// Cancellation Periods
export const cancellationPeriodApi = {
  getAll: async (includeInactive = false) => {
    const res = await api.get<ApiResponse<CancellationPeriod[]>>('/cancellation-periods', { params: { includeInactive } });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<CancellationPeriod>>(`/cancellation-periods/${id}`);
    return res.data;
  },
  create: async (data: Partial<CancellationPeriod>) => {
    const res = await api.post<ApiResponse<CancellationPeriod>>('/cancellation-periods', data);
    return res.data;
  },
  update: async (id: number, data: Partial<CancellationPeriod>) => {
    const res = await api.put<ApiResponse<CancellationPeriod>>(`/cancellation-periods/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/cancellation-periods/${id}`);
    return res.data;
  },
};

// Contract Durations
export const contractDurationApi = {
  getAll: async (includeInactive = false) => {
    const res = await api.get<ApiResponse<ContractDuration[]>>('/contract-durations', { params: { includeInactive } });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<ContractDuration>>(`/contract-durations/${id}`);
    return res.data;
  },
  create: async (data: Partial<ContractDuration>) => {
    const res = await api.post<ApiResponse<ContractDuration>>('/contract-durations', data);
    return res.data;
  },
  update: async (id: number, data: Partial<ContractDuration>) => {
    const res = await api.put<ApiResponse<ContractDuration>>(`/contract-durations/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/contract-durations/${id}`);
    return res.data;
  },
};

// Contract Categories (Vertragstypen)
export const contractCategoryApi = {
  getAll: async (includeInactive = false) => {
    const res = await api.get<ApiResponse<ContractCategory[]>>('/contract-categories', { params: { includeInactive } });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<ContractCategory>>(`/contract-categories/${id}`);
    return res.data;
  },
  create: async (data: Partial<ContractCategory>) => {
    const res = await api.post<ApiResponse<ContractCategory>>('/contract-categories', data);
    return res.data;
  },
  update: async (id: number, data: Partial<ContractCategory>) => {
    const res = await api.put<ApiResponse<ContractCategory>>(`/contract-categories/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/contract-categories/${id}`);
    return res.data;
  },
};

// Providers (Anbieter)
export const providerApi = {
  getAll: async (includeInactive = false) => {
    const res = await api.get<ApiResponse<Provider[]>>('/providers', { params: { includeInactive } });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<Provider>>(`/providers/${id}`);
    return res.data;
  },
  create: async (data: Partial<Provider>) => {
    const res = await api.post<ApiResponse<Provider>>('/providers', data);
    return res.data;
  },
  update: async (id: number, data: Partial<Provider>) => {
    const res = await api.put<ApiResponse<Provider>>(`/providers/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/providers/${id}`);
    return res.data;
  },
  getTariffs: async (providerId: number, includeInactive = false) => {
    const res = await api.get<ApiResponse<Tariff[]>>(`/providers/${providerId}/tariffs`, { params: { includeInactive } });
    return res.data;
  },
  createTariff: async (providerId: number, data: Partial<Tariff>) => {
    const res = await api.post<ApiResponse<Tariff>>(`/providers/${providerId}/tariffs`, data);
    return res.data;
  },
};

// Tariffs (Tarife)
export const tariffApi = {
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<Tariff>>(`/tariffs/${id}`);
    return res.data;
  },
  update: async (id: number, data: Partial<Tariff>) => {
    const res = await api.put<ApiResponse<Tariff>>(`/tariffs/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/tariffs/${id}`);
    return res.data;
  },
};

// Upload
export const uploadApi = {
  uploadBankCardDocument: async (bankCardId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/bank-cards/${bankCardId}`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  uploadIdentityDocument: async (documentId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/documents/${documentId}`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteBankCardDocument: async (bankCardId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/bank-cards/${bankCardId}`);
    return res.data;
  },
  deleteIdentityDocument: async (documentId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/documents/${documentId}`);
    return res.data;
  },
  uploadBusinessRegistration: async (customerId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/customers/${customerId}/business-registration`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteBusinessRegistration: async (customerId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/customers/${customerId}/business-registration`);
    return res.data;
  },
  uploadCommercialRegister: async (customerId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/customers/${customerId}/commercial-register`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteCommercialRegister: async (customerId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/customers/${customerId}/commercial-register`);
    return res.data;
  },
  uploadPrivacyPolicy: async (customerId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/customers/${customerId}/privacy-policy`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deletePrivacyPolicy: async (customerId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/customers/${customerId}/privacy-policy`);
    return res.data;
  },
  // Contract Documents
  uploadCancellationLetter: async (contractId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-letter`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteCancellationLetter: async (contractId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-letter`);
    return res.data;
  },
  uploadCancellationConfirmation: async (contractId: number, file: File, confirmationDate?: string) => {
    const formData = new FormData();
    formData.append('document', file);
    if (confirmationDate) formData.append('confirmationDate', confirmationDate);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-confirmation`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteCancellationConfirmation: async (contractId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-confirmation`);
    return res.data;
  },
  uploadCancellationLetterOptions: async (contractId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-letter-options`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteCancellationLetterOptions: async (contractId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-letter-options`);
    return res.data;
  },
  uploadCancellationConfirmationOptions: async (contractId: number, file: File, confirmationDate?: string) => {
    const formData = new FormData();
    formData.append('document', file);
    if (confirmationDate) formData.append('confirmationDate', confirmationDate);
    const res = await api.post<ApiResponse<{ path: string; filename: string }>>(`/upload/contracts/${contractId}/cancellation-confirmation-options`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  deleteCancellationConfirmationOptions: async (contractId: number) => {
    const res = await api.delete<ApiResponse<void>>(`/upload/contracts/${contractId}/cancellation-confirmation-options`);
    return res.data;
  },
};

// Users
export const userApi = {
  getAll: async (params?: { search?: string; isActive?: boolean; roleId?: number; page?: number; limit?: number }) => {
    const res = await api.get<ApiResponse<User[]>>('/users', { params });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<User>>(`/users/${id}`);
    return res.data;
  },
  create: async (data: { email: string; password: string; firstName: string; lastName: string; roleIds: number[]; customerId?: number; hasDeveloperAccess?: boolean; hasGdprAccess?: boolean;
    hasAuditOpsAccess?: boolean; isServiceAccount?: boolean; confirm?: string; whatsappNumber?: string; telegramUsername?: string; signalNumber?: string }) => {
    const res = await api.post<ApiResponse<User>>('/users', data);
    return res.data;
  },
  update: async (id: number, data: Partial<User> & { password?: string; roleIds?: number[]; isServiceAccount?: boolean; hasGdprAccess?: boolean; hasDeveloperAccess?: boolean; hasAuditOpsAccess?: boolean; confirm?: string }) => {
    const res = await api.put<ApiResponse<User>>(`/users/${id}`, data);
    return res.data;
  },
  // Passwort eines Users zurücksetzen (Admin-Funktion). Separat vom generischen
  // Update, damit der Vorgang einen eigenen Audit-Eintrag bekommt.
  // Pentest 47.3: braucht currentPassword (eigenes Admin-Passwort) als Re-Auth.
  setPassword: async (id: number, password: string, currentPassword: string) => {
    const res = await api.post<ApiResponse<void>>(`/users/${id}/password`, { password, currentPassword });
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/users/${id}`);
    return res.data;
  },
  getRoles: async () => {
    const res = await api.get<ApiResponse<Role[]>>('/users/roles/list');
    return res.data;
  },
};

// Developer
export const developerApi = {
  getSchema: async () => {
    const res = await api.get<ApiResponse<any[]>>('/developer/schema');
    return res.data;
  },
  getTableData: async (tableName: string, page = 1, limit = 50) => {
    const res = await api.get<ApiResponse<any[]>>(`/developer/table/${tableName}`, { params: { page, limit } });
    return res.data;
  },
  updateRow: async (tableName: string, id: string, data: Record<string, any>) => {
    const res = await api.put<ApiResponse<any>>(`/developer/table/${tableName}/${id}`, data);
    return res.data;
  },
  deleteRow: async (tableName: string, id: string) => {
    const res = await api.delete<ApiResponse<void>>(`/developer/table/${tableName}/${id}`);
    return res.data;
  },
  getReference: async (tableName: string) => {
    const res = await api.get<ApiResponse<any[]>>(`/developer/reference/${tableName}`);
    return res.data;
  },
};

// Email Provider (für Stressfrei-Wechseln Provisionierung)
export interface EmailProviderConfig {
  id: number;
  name: string;
  type: 'PLESK' | 'CPANEL' | 'DIRECTADMIN';
  apiUrl: string;
  apiKey?: string;
  username?: string;
  passwordEncrypted?: string;
  domain: string;
  defaultForwardEmail?: string;
  // IMAP/SMTP-Server (für E-Mail-Client)
  imapServer?: string;
  imapPort?: number;
  smtpServer?: string;
  smtpPort?: number;
  // Verschlüsselungs-Einstellungen
  imapEncryption?: 'SSL' | 'STARTTLS' | 'NONE';
  smtpEncryption?: 'SSL' | 'STARTTLS' | 'NONE';
  allowSelfSignedCerts?: boolean; // Selbstsignierte Zertifikate erlauben
  // System-E-Mail für automatisierten Versand
  systemEmailAddress?: string;
  systemEmailPasswordEncrypted?: string;
  // UI-Label für Kunden-E-Mail-Adressen (z.B. "Stressfrei-Wechseln")
  customerEmailLabel?: string | null;
  isActive: boolean;
  isDefault: boolean;
  createdAt: string;
  updatedAt: string;
}

export interface EmailOperationResult {
  success: boolean;
  message?: string;
  error?: string;
}

export const emailProviderApi = {
  // Config CRUD
  getConfigs: async () => {
    const res = await api.get<ApiResponse<EmailProviderConfig[]>>('/email-providers/configs');
    return res.data;
  },
  getConfig: async (id: number) => {
    const res = await api.get<ApiResponse<EmailProviderConfig>>(`/email-providers/configs/${id}`);
    return res.data;
  },
  createConfig: async (data: Partial<EmailProviderConfig> & { password?: string }) => {
    const res = await api.post<ApiResponse<EmailProviderConfig>>('/email-providers/configs', data);
    return res.data;
  },
  updateConfig: async (id: number, data: Partial<EmailProviderConfig> & { password?: string }) => {
    const res = await api.put<ApiResponse<EmailProviderConfig>>(`/email-providers/configs/${id}`, data);
    return res.data;
  },
  deleteConfig: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/email-providers/configs/${id}`);
    return res.data;
  },
  // Email Operations
  testConnection: async (options?: {
    id?: number;
    testData?: {
      type: 'PLESK' | 'CPANEL' | 'DIRECTADMIN';
      apiUrl: string;
      apiKey?: string;
      username?: string;
      password?: string;
      domain: string;
    };
  }) => {
    const body = options?.testData
      ? { ...options.testData }
      : options?.id
        ? { id: options.id }
        : {};
    const res = await api.post<ApiResponse<EmailOperationResult>>('/email-providers/test-connection', body);
    return res.data;
  },
  testMailAccess: async (body: {
    id?: number;
    apiUrl?: string;
    domain?: string;
    systemEmailAddress?: string;
    systemEmailPassword?: string;
    imapEncryption?: 'SSL' | 'STARTTLS' | 'NONE';
    smtpEncryption?: 'SSL' | 'STARTTLS' | 'NONE';
    allowSelfSignedCerts?: boolean;
  }) => {
    const res = await api.post<ApiResponse<{
      imap: { success: boolean; error?: string; server: string; port: number; encryption: string };
      smtp: { success: boolean; error?: string; server: string; port: number; encryption: string };
      user: string;
    }>>('/email-providers/test-mail-access', body);
    return res.data;
  },
  getDomain: async () => {
    const res = await api.get<ApiResponse<{ domain: string | null }>>('/email-providers/domain');
    return res.data;
  },
  getPublicSettings: async () => {
    const res = await api.get<ApiResponse<{
      domain: string | null;
      customerEmailLabel: string;
      customerEmailLabelIsCustom: boolean;
    }>>('/email-providers/public-settings');
    return res.data;
  },
  checkEmailExists: async (localPart: string) => {
    const res = await api.get<ApiResponse<{ exists: boolean; email?: string }>>(`/email-providers/check/${localPart}`);
    return res.data;
  },
  provisionEmail: async (localPart: string, customerEmail: string) => {
    const res = await api.post<ApiResponse<EmailOperationResult>>('/email-providers/provision', { localPart, customerEmail });
    return res.data;
  },
  deprovisionEmail: async (localPart: string) => {
    const res = await api.delete<ApiResponse<EmailOperationResult>>(`/email-providers/deprovision/${localPart}`);
    return res.data;
  },
};

// ==================== AUDIT-LOGS ====================

export interface AuditLogSearchParams {
  page?: number;
  limit?: number;
  userId?: number;
  action?: string;
  resourceType?: string;
  sensitivity?: AuditSensitivity;
  dataSubjectId?: number;
  startDate?: string;
  endDate?: string;
  search?: string;
}

/** Ergebnis der Integritaetspruefung des Audit-Protokolls. */
export interface IntegrityResult {
  valid: boolean;
  checkedCount: number;
  /** Noch offene Beanstandungen – nur hieran haengt `valid`. */
  invalidEntries: number[];
  /** ERNST: Inhalt einer bestehenden Zeile wurde nachtraeglich veraendert. */
  tamperedEntries: number[];
  /** Verkettung unterbrochen; die Zeilen selbst koennen unversehrt sein. */
  chainGaps: number[];
  /** Luecken ohne protokolliertes Loeschungs-Manifest. */
  unexplainedGaps: number[];
  /** Alt-Luecken, die das Bestandssiegel als bereits vorhanden beglaubigt. */
  attestedGaps: number[];
  /**
   * Protokollierte Neuberechnungen der Kette. Nach einem Rehash ist die Kette
   * zwangslaeufig stimmig - auch ueber Loeschungen hinweg. Die Aussage der
   * Pruefung reicht dann nur bis zur letzten Neuberechnung zurueck.
   */
  rehashes: Array<{
    id: number;
    zeitpunkt: string;
    neuBerechnet: number | null;
    signiert: boolean;
    vorbefund: { manipuliert: number; luecken: number } | null;
  }>;
  /** Signierte Zeilen, die ohne AUDIT_HMAC_KEY nicht pruefbar sind. */
  unverifiableEntries: number[];
  backlogSealStatus: 'kein_siegel' | 'intakt' | 'leer' | 'gebrochen' | 'entfernt' | 'nicht_noetig';
  backlogTampered: number[];
  backlogMissing: number[];
  backlogSealCount: number;
  tampered: boolean;
  message: string;
}

export const auditLogApi = {
  search: async (params?: AuditLogSearchParams) => {
    const res = await api.get<ApiResponse<AuditLog[]>>('/audit-logs', { params });
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<AuditLog>>(`/audit-logs/${id}`);
    return res.data;
  },
  getByCustomer: async (customerId: number) => {
    const res = await api.get<ApiResponse<AuditLog[]>>(`/audit-logs/customer/${customerId}`);
    return res.data;
  },
  export: async (params?: AuditLogSearchParams & { format?: 'json' | 'csv' }) => {
    const res = await api.get<ApiResponse<{ data: AuditLog[]; format: string }>>('/audit-logs/export', { params });
    return res.data;
  },
  verifyIntegrity: async () => {
    const res = await api.post<ApiResponse<IntegrityResult>>('/audit-logs/verify');
    return res.data;
  },
  rehash: async () => {
    const res = await api.post<ApiResponse<{ rehashedCount: number }>>('/audit-logs/rehash');
    return res.data;
  },
  getRetentionPolicies: async () => {
    const res = await api.get<ApiResponse<AuditRetentionPolicy[]>>('/audit-logs/retention-policies');
    return res.data;
  },
  updateRetentionPolicy: async (id: number, data: { retentionDays: number; isActive?: boolean }) => {
    const res = await api.put<ApiResponse<AuditRetentionPolicy>>(`/audit-logs/retention-policies/${id}`, data);
    return res.data;
  },
  runRetentionCleanup: async () => {
    const res = await api.post<ApiResponse<{ deletedCount: number }>>('/audit-logs/cleanup');
    return res.data;
  },
};

// ==================== PDF TEMPLATES ====================

export const pdfTemplateApi = {
  getAll: async () => {
    const res = await api.get<ApiResponse<import('../types').PdfTemplate[]>>('/pdf-templates');
    return res.data;
  },
  getById: async (id: number) => {
    const res = await api.get<ApiResponse<import('../types').PdfTemplate>>(`/pdf-templates/${id}`);
    return res.data;
  },
  create: async (formData: FormData) => {
    const res = await api.post<ApiResponse<import('../types').PdfTemplate & { pdfFields?: import('../types').PdfField[] }>>('/pdf-templates', formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return res.data;
  },
  update: async (id: number, data: Record<string, unknown>) => {
    const res = await api.put<ApiResponse<import('../types').PdfTemplate>>(`/pdf-templates/${id}`, data);
    return res.data;
  },
  delete: async (id: number) => {
    const res = await api.delete<ApiResponse<void>>(`/pdf-templates/${id}`);
    return res.data;
  },
  getFields: async (id: number) => {
    const res = await api.get<ApiResponse<import('../types').PdfField[]>>(`/pdf-templates/${id}/fields`);
    return res.data;
  },
  getCrmFields: async (maxPhoneFields?: number) => {
    const res = await api.get<ApiResponse<import('../types').CrmField[]>>('/pdf-templates/crm-fields', { params: { maxPhoneFields } });
    return res.data;
  },
  getRequiredInputs: async (templateId: number, contractId: number) => {
    const res = await api.get<ApiResponse<{
      needsStressfreiEmail: boolean;
      stressfreiEmails: { id: number; email: string }[];
      manualFields: { key: string; pdfFieldName: string }[];
    }>>(`/pdf-templates/${templateId}/generate/${contractId}/inputs`);
    return res.data;
  },
  generatePdf: async (templateId: number, contractId: number, extras?: { stressfreiEmailId?: number; manualValues?: Record<string, string> }) => {
    const res = await api.post(`/pdf-templates/${templateId}/generate/${contractId}`, extras || {}, { responseType: 'blob' });
    return res.data;
  },
  generateUrl: (templateId: number, contractId: number) =>
    `/api/pdf-templates/${templateId}/generate/${contractId}`,
};

// ==================== EMAIL LOG ====================

export interface EmailLog {
  id: number;
  fromAddress: string;
  toAddress: string;
  subject: string;
  context: string;
  customerId?: number;
  triggeredBy?: string;
  smtpServer: string;
  smtpPort: number;
  smtpEncryption: string;
  smtpUser: string;
  success: boolean;
  messageId?: string;
  errorMessage?: string;
  smtpResponse?: string;
  sentAt: string;
}

// ==================== MONITORING ====================

export type SecurityEventType =
  | 'LOGIN_FAILED' | 'LOGIN_SUCCESS' | 'RATE_LIMIT_HIT' | 'ACCESS_DENIED'
  | 'SSRF_BLOCKED' | 'PASSWORD_RESET_REQUEST' | 'PASSWORD_RESET_CONFIRM'
  | 'LOGOUT' | 'TOKEN_REJECTED' | 'PERMISSION_CHANGED' | 'AUDIT_SEAL_CHANGED' | 'SUSPICIOUS';

export type SecuritySeverity = 'INFO' | 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';

export interface SecurityEvent {
  id: number;
  type: SecurityEventType;
  severity: SecuritySeverity;
  message: string;
  ipAddress: string | null;
  userId: number | null;
  customerId: number | null;
  userEmail: string | null;
  endpoint: string | null;
  details: Record<string, unknown> | null;
  alerted: boolean;
  alertedAt: string | null;
  createdAt: string;
}

export interface MonitoringSettings {
  alertEmail: string;
  digestEnabled: boolean;
  lastDigestAt: string | null;
}

export const monitoringApi = {
  getEvents: async (params?: { page?: number; limit?: number; type?: SecurityEventType | ''; severity?: SecuritySeverity | ''; search?: string; ip?: string; since?: string }) => {
    const q = new URLSearchParams();
    if (params?.page) q.set('page', String(params.page));
    if (params?.limit) q.set('limit', String(params.limit));
    if (params?.type) q.set('type', params.type);
    if (params?.severity) q.set('severity', params.severity);
    if (params?.search) q.set('search', params.search);
    if (params?.ip) q.set('ip', params.ip);
    if (params?.since) q.set('since', params.since);
    const res = await api.get<ApiResponse<SecurityEvent[]> & {
      pagination: { page: number; limit: number; total: number; totalPages: number };
      stats: { byType: Record<string, number>; bySeverity: Record<string, number> };
    }>(`/monitoring/events?${q}`);
    return res.data;
  },
  getSettings: async () => {
    const res = await api.get<ApiResponse<MonitoringSettings>>('/monitoring/settings');
    return res.data;
  },
  updateSettings: async (data: { alertEmail?: string; digestEnabled?: boolean }) => {
    const res = await api.put<ApiResponse<void>>('/monitoring/settings', data);
    return res.data;
  },
  testAlert: async () => {
    const res = await api.post<ApiResponse<void>>('/monitoring/test-alert');
    return res.data;
  },
  runDigest: async () => {
    const res = await api.post<ApiResponse<{ sent: boolean; eventCount: number; reason?: string }>>('/monitoring/run-digest');
    return res.data;
  },
  clearEvents: async (olderThanDays?: number) => {
    const q = olderThanDays ? `?olderThanDays=${olderThanDays}` : '';
    const res = await api.delete<ApiResponse<{ deletedCount: number }>>(`/monitoring/events${q}`);
    return res.data;
  },
};

export const emailLogApi = {
  getLogs: async (params?: { page?: number; limit?: number; success?: string; search?: string; context?: string }) => {
    const query = new URLSearchParams();
    if (params?.page) query.set('page', params.page.toString());
    if (params?.limit) query.set('limit', params.limit.toString());
    if (params?.success !== undefined) query.set('success', params.success);
    if (params?.search) query.set('search', params.search);
    if (params?.context) query.set('context', params.context);
    const res = await api.get<ApiResponse<EmailLog[]> & { pagination: { page: number; limit: number; total: number; totalPages: number } }>(`/email-logs?${query}`);
    return res.data;
  },
  getStats: async () => {
    const res = await api.get<ApiResponse<{ total: number; success: number; failed: number; last24h: number }>>('/email-logs/stats');
    return res.data;
  },
  getDetail: async (id: number) => {
    const res = await api.get<ApiResponse<EmailLog>>(`/email-logs/${id}`);
    return res.data;
  },
};

// ==================== DSGVO ====================

export const gdprApi = {
  // Dashboard
  getDashboardStats: async () => {
    const res = await api.get<ApiResponse<GDPRDashboardStats>>('/gdpr/dashboard');
    return res.data;
  },
  // Datenexport (Art. 15)
  exportCustomerData: async (customerId: number) => {
    const res = await api.get<ApiResponse<unknown>>(`/gdpr/customer/${customerId}/export`);
    return res.data;
  },
  // Löschanfragen
  getDeletionRequests: async (params?: { status?: DeletionRequestStatus; page?: number; limit?: number }) => {
    const res = await api.get<ApiResponse<DataDeletionRequest[]>>('/gdpr/deletions', { params });
    return res.data;
  },
  getDeletionRequest: async (id: number) => {
    const res = await api.get<ApiResponse<DataDeletionRequest>>(`/gdpr/deletions/${id}`);
    return res.data;
  },
  createDeletionRequest: async (data: { customerId: number; requestSource: string; requestedBy: string }) => {
    const res = await api.post<ApiResponse<DataDeletionRequest>>('/gdpr/deletions', data);
    return res.data;
  },
  processDeletionRequest: async (id: number, data: { processedBy: string; action: 'complete' | 'partial' | 'reject'; retentionReason?: string }) => {
    const res = await api.put<ApiResponse<DataDeletionRequest>>(`/gdpr/deletions/${id}/process`, data);
    return res.data;
  },
  // Consent-Status prüfen (hat Kunde vollständig zugestimmt?)
  checkConsentStatus: async (customerId: number) => {
    const res = await api.get<ApiResponse<{ hasConsent: boolean; hasPaperConsent: boolean; hasOnlineConsent: boolean; consentDetails: { type: string; status: string }[]; consentHash: string | null }>>(`/gdpr/customer/${customerId}/consent-status`);
    return res.data;
  },
  getMyConsentStatus: async () => {
    const res = await api.get<ApiResponse<{ hasConsent: boolean; hasPaperConsent: boolean; hasOnlineConsent: boolean; consentDetails: { type: string; status: string }[]; consentHash: string | null }>>('/gdpr/my-consent-status');
    return res.data;
  },
  // Einwilligungen
  getCustomerConsents: async (customerId: number) => {
    const res = await api.get<ApiResponse<CustomerConsent[]>>(`/gdpr/customer/${customerId}/consents`);
    return res.data;
  },
  updateConsent: async (customerId: number, consentType: ConsentType, data: { status: ConsentStatus; source?: string }) => {
    const res = await api.put<ApiResponse<CustomerConsent>>(`/gdpr/customer/${customerId}/consents/${consentType}`, data);
    return res.data;
  },
  getConsentOverview: async () => {
    const res = await api.get<ApiResponse<Record<string, { granted: number; withdrawn: number; pending: number }>>>('/gdpr/consents/overview');
    return res.data;
  },
  // Datenschutzerklärung (Editor)
  getPrivacyPolicy: async () => {
    const res = await api.get<ApiResponse<{ html: string }>>('/gdpr/privacy-policy');
    return res.data;
  },
  updatePrivacyPolicy: async (html: string) => {
    const res = await api.put<ApiResponse<void>>('/gdpr/privacy-policy', { html });
    return res.data;
  },
  // Vollmacht-Vorlage
  getAuthorizationTemplate: async () => {
    const res = await api.get<ApiResponse<{ html: string }>>('/gdpr/authorization-template');
    return res.data;
  },
  updateAuthorizationTemplate: async (html: string) => {
    const res = await api.put<ApiResponse<void>>('/gdpr/authorization-template', { html });
    return res.data;
  },
  // Impressum
  getImprint: async () => {
    const res = await api.get<ApiResponse<{ html: string }>>('/gdpr/imprint');
    return res.data;
  },
  updateImprint: async (html: string) => {
    const res = await api.put<ApiResponse<void>>('/gdpr/imprint', { html });
    return res.data;
  },
  // Website-Datenschutzerklärung
  getWebsitePrivacyPolicy: async () => {
    const res = await api.get<ApiResponse<{ html: string }>>('/gdpr/website-privacy-policy');
    return res.data;
  },
  updateWebsitePrivacyPolicy: async (html: string) => {
    const res = await api.put<ApiResponse<void>>('/gdpr/website-privacy-policy', { html });
    return res.data;
  },
  // Consent-Link senden
  sendConsentLink: async (customerId: number, channel: string) => {
    const res = await api.post<ApiResponse<{ url: string; channel: string; hash: string }>>(`/gdpr/customer/${customerId}/send-consent-link`, { channel });
    return res.data;
  },
  // Unterschreibbare Datenschutzerklärung als PDF (Papierform).
  // Liefert die URL inkl. Auth-Token, damit window.open/<a download> klappt
  // (Browser senden bei plain links keinen Authorization-Header).
  getSignablePrivacyPdfUrl: (customerId: number): string => {
    const token = getAccessToken();
    const base = `/api/gdpr/customer/${customerId}/privacy-pdf`;
    return token ? `${base}?token=${encodeURIComponent(token)}` : base;
  },
  // Portal: Eigene Datenschutzseite
  getMyPrivacy: async () => {
    const res = await api.get<ApiResponse<{ privacyPolicyHtml: string; consents: CustomerConsent[] }>>('/gdpr/my-privacy');
    return res.data;
  },
  getMyPrivacyPdfUrl: '/api/gdpr/my-privacy/pdf',
  // Vollmachten (Admin)
  getAuthorizations: async (customerId: number) => {
    const res = await api.get<ApiResponse<RepresentativeAuthorization[]>>(`/gdpr/customer/${customerId}/authorizations`);
    return res.data;
  },
  sendAuthorizationRequest: async (customerId: number, representativeId: number, channel: string) => {
    const res = await api.post<ApiResponse<{ channel: string; portalUrl: string; messageText: string }>>(`/gdpr/customer/${customerId}/authorizations/${representativeId}/send`, { channel });
    return res.data;
  },
  grantAuthorization: async (customerId: number, representativeId: number, data?: { source?: string; notes?: string }) => {
    const res = await api.post<ApiResponse<RepresentativeAuthorization>>(`/gdpr/customer/${customerId}/authorizations/${representativeId}/grant`, data || {});
    return res.data;
  },
  withdrawAuthorization: async (customerId: number, representativeId: number) => {
    const res = await api.post<ApiResponse<RepresentativeAuthorization>>(`/gdpr/customer/${customerId}/authorizations/${representativeId}/withdraw`);
    return res.data;
  },
  uploadAuthorizationDocument: async (customerId: number, representativeId: number, file: File) => {
    const formData = new FormData();
    formData.append('document', file);
    const res = await api.post<ApiResponse<RepresentativeAuthorization>>(
      `/gdpr/customer/${customerId}/authorizations/${representativeId}/upload`,
      formData,
      { headers: { 'Content-Type': 'multipart/form-data' } }
    );
    return res.data;
  },
  deleteAuthorizationDocument: async (customerId: number, representativeId: number) => {
    const res = await api.delete<ApiResponse<RepresentativeAuthorization>>(`/gdpr/customer/${customerId}/authorizations/${representativeId}/document`);
    return res.data;
  },
  // Vollmachten (Portal)
  getMyAuthorizations: async () => {
    const res = await api.get<ApiResponse<RepresentativeAuthorization[]>>('/gdpr/my-authorizations');
    return res.data;
  },
  toggleMyAuthorization: async (representativeId: number, grant: boolean) => {
    const res = await api.put<ApiResponse<RepresentativeAuthorization>>(`/gdpr/my-authorizations/${representativeId}`, { grant });
    return res.data;
  },
  getMyAuthorizationStatus: async () => {
    const res = await api.get<ApiResponse<{ customerId: number; hasAuthorization: boolean }[]>>('/gdpr/my-authorization-status');
    return res.data;
  },
};

// ==================== PUBLIC API (kein Auth-Token) ====================

const publicAxios = axios.create({
  baseURL: '/api/public',
  headers: { 'Content-Type': 'application/json' },
});

export const publicApi = {
  getConsentPage: async (hash: string) => {
    const res = await publicAxios.get<ApiResponse<{
      customer: { firstName: string; lastName: string; customerNumber: string };
      consents: Array<{
        consentType: string;
        status: string;
        label: string;
        description: string;
        grantedAt: string | null;
      }>;
      privacyPolicyHtml: string;
    }>>(`/consent/${hash}`);
    return res.data;
  },
  grantAllConsents: async (hash: string) => {
    const res = await publicAxios.post<ApiResponse<void>>(`/consent/${hash}/grant`);
    return res.data;
  },
  getConsentPdfUrl: (hash: string) => `/api/public/consent/${hash}/pdf`,
};

// ============ BIRTHDAY API ============
export interface BirthdayEntry {
  customerId: number;
  customerNumber: string;
  name: string;
  birthDate: string;
  age: number;
  daysUntil: number;
  isToday: boolean;
  isPast: boolean;
  portalEnabled: boolean;
  email?: string | null;
  phone?: string | null;
}

export interface MyBirthdayCheck {
  show: boolean;
  isToday: boolean;
  daysAgo: number;
  firstName: string;
  lastName: string;
  salutation: string | null;
  useInformalAddress: boolean;
  age: number;
}

export const birthdayApi = {
  getUpcoming: async (past: number = 7, future: number = 30) => {
    const res = await api.get<ApiResponse<BirthdayEntry[]>>('/birthdays/upcoming', {
      params: { past, future },
    });
    return res.data;
  },
  getMyBirthday: async () => {
    const res = await api.get<ApiResponse<MyBirthdayCheck | null>>('/birthdays/my-birthday');
    return res.data;
  },
  acknowledgeMyBirthday: async () => {
    const res = await api.post<ApiResponse<void>>('/birthdays/my-birthday/acknowledge');
    return res.data;
  },
  resetGreeting: async (customerId: number) => {
    const res = await api.post<ApiResponse<void>>(`/birthdays/${customerId}/reset`);
    return res.data;
  },
  sendGreeting: async (customerId: number, channel: 'email' | 'whatsapp' | 'telegram' | 'signal') => {
    const res = await api.post<ApiResponse<{ channel: string; messageText: string }>>(
      `/birthdays/${customerId}/send`,
      { channel },
    );
    return res.data;
  },
};

export default api;
