import mongoose, { Schema, models, model } from "mongoose";

export interface SettingsDoc {
  key: string;
  maintenanceMode: {
    enabled: boolean;
    message: string;
    // Optional — wer dieses Passwort auf der Wartungsseite eingibt, sieht die
    // Seite trotz aktiviertem Wartungsmodus normal (ohne echten Login nötig).
    // Leer = keine Passwort-Vorschau möglich, nur Mitarbeiter-Logins kommen durch.
    previewPassword: string;
  };
  liveChat: {
    enabled: boolean;
    provider: "tawk";
    tawkPropertyId: string;
    tawkWidgetId: string;
  };
  copyProtection: {
    disableContextMenu: boolean;
    disableTextSelection: boolean;
    disableCopy: boolean;
    disableSaveShortcut: boolean;
    disablePrintShortcut: boolean;
    disableSourceShortcut: boolean;
    disableDevToolsShortcuts: boolean;
    disableImageDrag: boolean;
  };
  socialLinks: {
    instagram: string;
    twitter: string;
    tiktok: string;
    twitch: string;
    youtube: string;
    discord: string;
    email: string;
  };
  legal: {
    impressumUrl: string;
    privacyUpdated: string;
    privacyTextDe: string;
    privacyTextEn: string;
    termsUpdated: string;
    termsTextDe: string;
    termsTextEn: string;
  };
  invoiceSettings: {
    businessName: string;
    // Bürgerlicher Name des Inhabers — bei Einzelunternehmen mit Markennamen
    // (z. B. "Rakku Photography") schreibt § 14 UStG vor, dass zusätzlich zum
    // Markennamen auch der bürgerliche Name des Inhabers auf der Rechnung steht.
    legalName: string;
    street: string;
    postCode: string;
    city: string;
    countryCode: string;
    email: string;
    taxId: string;
    kleinunternehmer: boolean;
    vatRate: number;
    iban: string;
    bic: string;
    bankName: string;
    // Name, auf den das Bankkonto tatsächlich lautet — kann vom Marken-/Firmennamen
    // abweichen (z. B. Konto läuft auf den bürgerlichen Namen des Inhabers).
    accountHolderName: string;
    invoiceNumberPrefix: string;
    nextInvoiceNumber: number;
  };
  paymentSettings: {
    // Nutzer-Vorgabe (04.08.2026): muss jederzeit deaktivierbar sein — Kunden
    // sehen den "Jetzt online bezahlen"-Button nur, wenn dieser Schalter an
    // ist UND ein Stripe-Secret-Key in .env.local hinterlegt ist.
    enabled: boolean;
  };
  bannerSettings: {
    enabled: boolean;
    text: string;
    textEn: string;
  };
  // Schalter, um neue Gutschein-Käufe auf /gutscheine zu sperren — bestehende
  // Gutscheine bleiben davon unberührt. Default an (Käufe sind heute möglich).
  voucherSettings: {
    enabled: boolean;
  };
  seoSettings: {
    metaTitleSuffix: string;
    defaultMetaDescription: string;
    defaultMetaDescriptionEn: string;
    keywords: string;
    keywordsEn: string;
    ogImage: string;
    googleSiteVerification: string;
    bingSiteVerification: string;
    googleAnalyticsId: string;
    businessPhone: string;
    priceRange: string;
    // Freitext im schema.org-openingHours-Format (z. B. "Mo-Fr 09:00-18:00"
    // oder "Nach Vereinbarung") fürs LocalBusiness-JSON-LD — leer bis Till
    // ihn einträgt (26.09.2026, SEO-Nachschärfung). Leer = Feld wird im
    // strukturierten Datenblock einfach weggelassen, kein Pflichtfeld.
    openingHours: string;
    // Site-weit de-/indexierbar — z. B. während der v2-Vorschauphase vor dem
    // eigentlichen Umzug auf rakku.de auf "aus" stellbar, um doppelten
    // Suchmaschinen-Content auf zwei Domains zu vermeiden.
    indexable: boolean;
  };
  referralSettings: {
    enabled: boolean;
    // Rabatt für den geworbenen Neukunden, sobald er den Empfehlungscode einlöst.
    refereeDiscountType: "percent" | "fixed";
    refereeDiscountValue: number;
    // Prämie, die der Werber als neuer Rabattcode gutgeschrieben bekommt.
    referrerRewardType: "percent" | "fixed";
    referrerRewardValue: number;
  };
  reviewRewardSettings: {
    enabled: boolean;
    // Prämie, die ein Kunde als neuer Rabattcode gutgeschrieben bekommt,
    // sobald er beim Feedback-Formular einen geschriebenen Kommentar
    // hinterlässt (nicht schon bei einer reinen Sternebewertung) — siehe
    // actions/feedback.ts.
    type: "percent" | "fixed";
    value: number;
  };
  loyaltySettings: {
    enabled: boolean;
    // Alle N bezahlten Aufträge gibt's automatisch eine neue Prämie — nicht
    // nur einmalig, damit auch langjährige Stammkund:innen wiederholt
    // profitieren (siehe lib/loyalty.ts).
    ordersThreshold: number;
    rewardType: "percent" | "fixed";
    rewardValue: number;
  };
  reengagementSettings: {
    enabled: boolean;
    // Wie viele Tage seit dem letzten (vergangenen) shootDate eines Kunden
    // vergangen sein müssen, bevor die Wiedervorlage-Mail rausgeht.
    delayDays: number;
    // Leer = eingebauter Standardtext. Admin-editierbar statt fest im Code,
    // damit der Wortlaut ohne Code-Änderung angepasst werden kann.
    customText: string;
    customTextEn: string;
  };
  // Backup-Überwachung: Zeitstempel der letzten erfolgreichen automatischen
  // Datenbank-Sicherung (vom Backup-Skript per internem API-Aufruf gesetzt),
  // damit die Einstellungsseite warnen kann, falls sie ausbleibt.
  lastBackupAt: Date | null;
  preshootReminderSettings: {
    enabled: boolean;
    // Wie viele Stunden vor dem gesetzten shootDate die Erinnerungs-Mail
    // rausgeht (Standard 48h) — läuft im 2-Stunden-Cron-Raster, muss also
    // nicht exakt treffen.
    hoursBefore: number;
    customText: string;
    customTextEn: string;
  };
  weatherCheckSettings: {
    enabled: boolean;
    // Wie viele Stunden vor shootDate der Wetter-Check läuft (Standard 48h —
    // früh genug, um bei Bedarf noch umplanen zu können, aber nah genug dran,
    // dass die Vorhersage schon zuverlässig ist).
    hoursBefore: number;
  };
  feedbackRequestSettings: {
    enabled: boolean;
    // Wie viele Tage nach Freigabe der Foto-Galerie automatisch nachgefragt
    // wird, falls das Team es nicht vorher schon manuell angestoßen hat.
    delayDays: number;
  };
  googleReviewSettings: {
    // Link zur Google-Bewertungsseite des Unternehmens — leer bis Till ihn
    // einträgt (26.09.2026). Solange leer, bleibt der Google-CTA nach einer
    // guten internen Bewertung (/feedback/[token]) ausgeblendet, siehe
    // FeedbackForm.tsx.
    url: string;
  };
  taxReserveSettings: {
    // Grober Richtwert in Prozent des Umsatzes, den die Statistik-Seite als
    // Steuerrücklage-Hinweis anzeigt — bewusst kein Steuerberater-Ersatz,
    // nur eine Orientierung.
    percentage: number;
  };
  mileageSettings: {
    // Kilometerpauschale in € — Standardwert für den Fahrtkosten-Rechner
    // (/admin/mileage), dort pro Berechnung noch überschreibbar. 0,30 €/km
    // ist der gängige Richtwert für betrieblich gefahrene Kilometer mit dem
    // eigenen Auto, kein verbindlicher Steuerwert.
    ratePerKm: number;
  };
  reminderEscalationSettings: {
    // Bewusst standardmäßig AUS — ein automatisches System, das echten
    // Kund:innen von sich aus Mahnungen mit Zusatzgebühren schickt, soll
    // nicht ungefragt "von selbst" loslaufen, sondern erst nach bewusster
    // Aktivierung unter Einstellungen.
    autoEnabled: boolean;
    // Ab Rechnungsdatum bis zur ersten (meist gebührenfreien) Zahlungserinnerung.
    daysUntilFirstReminder: number;
    // Ab Fälligkeit einer Mahnstufe bis zur nächsten, falls weiterhin unbezahlt.
    daysBetweenLevels: number;
    // Zusatzgebühr je Stufe: [Zahlungserinnerung, 1. Mahnung, 2. Mahnung, ...].
    // Stufen darüber hinaus verwenden den letzten Wert des Arrays weiter.
    levelFees: number[];
  };
  googleSyncSettings: {
    // Bewusst standardmäßig AUS (wie reminderEscalationSettings.autoEnabled)
    // — ein im Google Kalender gelöschter/abgesagter Termin wird sonst
    // automatisch auch lokal entfernt (shootDate zurückgesetzt bzw. Termin
    // gelöscht), was bei einem unbeaufsichtigten Cron-Lauf riskant ist, falls
    // die Löschung in Google versehentlich war.
    reflectDeletionsFromGoogle: boolean;
  };
  bookingSettings: {
    // Mindestvorlauf in Wochen zwischen heute und einem vom Team gesetzten
    // shootDate — reine Richtlinie, kein hartes Limit: setOrderShootDateAction
    // lässt sich mit einer expliziten Bestätigung (confirmLeadTimeOverride)
    // trotzdem unterschreiten, damit das Team im Einzelfall Ausnahmen machen
    // kann, ohne dass Kund:innen das selbst erzwingen können (siehe
    // ShootDatePanel.tsx).
    minLeadTimeWeeks: number;
  };
}

const settingsSchema = new Schema<SettingsDoc>(
  {
    key: { type: String, unique: true, default: "main" },
    maintenanceMode: {
      enabled: { type: Boolean, default: false },
      message: { type: String, default: "" },
      previewPassword: { type: String, default: "" },
    },
    liveChat: {
      enabled: { type: Boolean, default: false },
      provider: { type: String, default: "tawk" },
      tawkPropertyId: { type: String, default: "" },
      tawkWidgetId: { type: String, default: "" },
    },
    copyProtection: {
      disableContextMenu: { type: Boolean, default: true },
      disableTextSelection: { type: Boolean, default: true },
      disableCopy: { type: Boolean, default: true },
      disableSaveShortcut: { type: Boolean, default: true },
      disablePrintShortcut: { type: Boolean, default: true },
      disableSourceShortcut: { type: Boolean, default: true },
      disableDevToolsShortcuts: { type: Boolean, default: true },
      disableImageDrag: { type: Boolean, default: true },
    },
    socialLinks: {
      instagram: { type: String, default: "" },
      twitter: { type: String, default: "" },
      tiktok: { type: String, default: "" },
      twitch: { type: String, default: "" },
      youtube: { type: String, default: "" },
      discord: { type: String, default: "" },
      email: { type: String, default: "" },
    },
    legal: {
      impressumUrl: { type: String, default: "" },
      privacyUpdated: { type: String, default: "" },
      privacyTextDe: { type: String, default: "" },
      privacyTextEn: { type: String, default: "" },
      termsUpdated: { type: String, default: "" },
      termsTextDe: { type: String, default: "" },
      termsTextEn: { type: String, default: "" },
    },
    invoiceSettings: {
      businessName: { type: String, default: "Rakku Photography" },
      legalName: { type: String, default: "" },
      street: { type: String, default: "" },
      postCode: { type: String, default: "" },
      city: { type: String, default: "" },
      countryCode: { type: String, default: "DE" },
      email: { type: String, default: "" },
      taxId: { type: String, default: "" },
      kleinunternehmer: { type: Boolean, default: true },
      vatRate: { type: Number, default: 19 },
      iban: { type: String, default: "" },
      bic: { type: String, default: "" },
      bankName: { type: String, default: "" },
      accountHolderName: { type: String, default: "" },
      invoiceNumberPrefix: { type: String, default: "RG-" },
      nextInvoiceNumber: { type: Number, default: 1 },
    },
    paymentSettings: {
      enabled: { type: Boolean, default: false },
    },
    bannerSettings: {
      enabled: { type: Boolean, default: false },
      text: { type: String, default: "" },
      textEn: { type: String, default: "" },
    },
    voucherSettings: {
      enabled: { type: Boolean, default: true },
    },
    seoSettings: {
      metaTitleSuffix: { type: String, default: " · Rakku Photography" },
      defaultMetaDescription: { type: String, default: "" },
      defaultMetaDescriptionEn: { type: String, default: "" },
      keywords: { type: String, default: "" },
      keywordsEn: { type: String, default: "" },
      ogImage: { type: String, default: "" },
      googleSiteVerification: { type: String, default: "" },
      bingSiteVerification: { type: String, default: "" },
      googleAnalyticsId: { type: String, default: "" },
      businessPhone: { type: String, default: "" },
      priceRange: { type: String, default: "" },
      openingHours: { type: String, default: "", trim: true, maxlength: 200 },
      indexable: { type: Boolean, default: true },
    },
    referralSettings: {
      enabled: { type: Boolean, default: true },
      refereeDiscountType: { type: String, enum: ["percent", "fixed"], default: "percent" },
      refereeDiscountValue: { type: Number, default: 10 },
      referrerRewardType: { type: String, enum: ["percent", "fixed"], default: "percent" },
      referrerRewardValue: { type: Number, default: 10 },
    },
    reviewRewardSettings: {
      enabled: { type: Boolean, default: true },
      type: { type: String, enum: ["percent", "fixed"], default: "fixed" },
      value: { type: Number, default: 5 },
    },
    loyaltySettings: {
      enabled: { type: Boolean, default: true },
      ordersThreshold: { type: Number, default: 3 },
      rewardType: { type: String, enum: ["percent", "fixed"], default: "percent" },
      rewardValue: { type: Number, default: 10 },
    },
    reengagementSettings: {
      enabled: { type: Boolean, default: true },
      delayDays: { type: Number, default: 365 },
      customText: { type: String, default: "", trim: true, maxlength: 1000 },
      customTextEn: { type: String, default: "", trim: true, maxlength: 1000 },
    },
    lastBackupAt: { type: Date, default: null },
    preshootReminderSettings: {
      enabled: { type: Boolean, default: true },
      hoursBefore: { type: Number, default: 48 },
      customText: { type: String, default: "", trim: true, maxlength: 1000 },
      customTextEn: { type: String, default: "", trim: true, maxlength: 1000 },
    },
    weatherCheckSettings: {
      enabled: { type: Boolean, default: true },
      hoursBefore: { type: Number, default: 48 },
    },
    feedbackRequestSettings: {
      enabled: { type: Boolean, default: true },
      delayDays: { type: Number, default: 5 },
    },
    googleReviewSettings: {
      url: { type: String, default: "", trim: true, maxlength: 500 },
    },
    taxReserveSettings: {
      percentage: { type: Number, default: 28, min: 0, max: 100 },
    },
    mileageSettings: {
      ratePerKm: { type: Number, default: 0.3, min: 0, max: 5 },
    },
    reminderEscalationSettings: {
      autoEnabled: { type: Boolean, default: false },
      daysUntilFirstReminder: { type: Number, default: 14 },
      daysBetweenLevels: { type: Number, default: 10 },
      levelFees: { type: [Number], default: [0, 5, 15] },
    },
    googleSyncSettings: {
      reflectDeletionsFromGoogle: { type: Boolean, default: false },
    },
    bookingSettings: {
      minLeadTimeWeeks: { type: Number, default: 2, min: 0, max: 26 },
    },
  },
  { timestamps: true }
);

export const Settings =
  (models.Settings as mongoose.Model<SettingsDoc>) ||
  model<SettingsDoc>("Settings", settingsSchema);
