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

export type ContractType = "standard" | "tfp";
export type ContractStatus = "draft" | "sent" | "signed" | "declined";

export interface StandardContractData {
  amount: number;
  currency: "EUR";
  characterOrConcept: string;
  eventLocation: string;
  datePeriod: string;
  shootingType: string;
  // Schnappschuss von Order.usageRights zum Erstellungszeitpunkt — siehe
  // lib/orderConstants.ts USAGE_RIGHTS_OPTIONS.
  usageRights: string;
}

export interface TfpGuardian {
  name: string;
  // Strukturiert wie überall sonst auf der Seite (Straße/PLZ/Ort statt
  // einer Freitext-Zeile) — `address` bleibt nur für vor dieser Umstellung
  // angelegte Verträge erhalten, siehe contractPdf.tsx Fallback.
  address?: string;
  street: string;
  postCode: string;
  city: string;
  contact: string;
  relation: string;
}

export interface TfpStylist {
  name: string;
  address?: string;
  street: string;
  postCode: string;
  city: string;
  instagram: string;
  usage: string[]; // eigenes Portfolio / Social Media / Webseite / nur nach Freigabe
  credit: string;
}

export interface TfpContractData {
  modelBirthdate: string; // ISO date
  modelAddress?: string;
  modelStreet: string;
  modelPostCode: string;
  modelCity: string;
  modelInstagram: string;
  stylist: TfpStylist | null;
  shootingTheme: string;
  shootingLocation: string;
  shootingDate: string;
  shootingKinds: string[]; // Portrait/Cosplay/Fashion/Event/Sonstiges
  finalImageCount: string;
  photographerUsage: string[];
  publicationChannels: string[];
  publicationRestrictions: string;
  creditPreference: "nennen" | "nicht_nennen" | "nach_absprache";
  creditHandle: string;
  // Umgekehrte Richtung zu creditPreference (das ist Fotograf → Model): muss
  // das Model bei eigener Veröffentlichung Rakku Photography nennen/
  // verlinken? Steuert den entsprechenden Satz im PDF, siehe contractPdf.tsx.
  photographerCreditRequired: boolean;
  companionAllowed: boolean;
  specialAgreements: string;
  isMinor: boolean;
  guardians: TfpGuardian[];
}

export interface ContractSignature {
  role: "photographer" | "model" | "guardian1" | "guardian2" | "stylist";
  name: string;
  signedAt: Date;
  ip: string;
}

// Kleines Audit-Log für die "Erinnerung senden"-Aktion (status "sent", noch
// nicht unterschrieben) - sentByClientId wird bewusst nur als Referenz
// gespeichert (wie sonst auch, z. B. OrderMessage.senderId), nicht als
// Namens-Schnappschuss - anders als bei Rechnungen/Verträgen selbst ist das
// hier ein rein internes Audit-Log, keine rechtsverbindliche Ausfertigung.
export interface ContractReminderLogEntry {
  sentAt: Date;
  sentByClientId: mongoose.Types.ObjectId;
}

export interface ContractDoc {
  _id: string;
  orderId: mongoose.Types.ObjectId;
  clientId: mongoose.Types.ObjectId;
  type: ContractType;
  status: ContractStatus;
  // Sprache, in der dieser Vertrag erzeugt wurde (zweisprachige Verträge,
  // 28.09.2026) — bewusst ein expliziter Auswahl beim Erstellen statt
  // automatisch aus Client.locale abgeleitet (anders als sonst im Code
  // üblich, siehe lib/orderEmails.ts), weil Till das ausdrücklich so
  // gewünscht hat. Als Schnappschuss gespeichert: eine spätere Änderung an
  // Client.locale oder eine Nachübersetzung der Vorlage darf diesen bereits
  // erzeugten Vertrag nicht rückwirkend in der Sprache wechseln.
  locale: "de" | "en";
  standardData: StandardContractData | null;
  tfpData: TfpContractData | null;
  signatures: ContractSignature[];
  reminders: ContractReminderLogEntry[];
  sentAt: Date | null;
  signedAt: Date | null;
  createdAt: Date;
}

const signatureSchema = new Schema<ContractSignature>(
  {
    role: { type: String, enum: ["photographer", "model", "guardian1", "guardian2", "stylist"], required: true },
    name: { type: String, required: true },
    signedAt: { type: Date, required: true },
    ip: { type: String, required: true },
  },
  { _id: false }
);

const reminderLogSchema = new Schema<ContractReminderLogEntry>(
  {
    sentAt: { type: Date, required: true },
    sentByClientId: { type: Schema.Types.ObjectId, ref: "Client", required: true },
  },
  { _id: false }
);

const contractSchema = new Schema<ContractDoc>(
  {
    orderId: { type: Schema.Types.ObjectId, ref: "Order", required: true, index: true },
    clientId: { type: Schema.Types.ObjectId, ref: "Client", required: true, index: true },
    type: { type: String, enum: ["standard", "tfp"], required: true },
    status: { type: String, enum: ["draft", "sent", "signed", "declined"], default: "draft" },
    locale: { type: String, enum: ["de", "en"], default: "de" },
    standardData: { type: Schema.Types.Mixed, default: null },
    tfpData: { type: Schema.Types.Mixed, default: null },
    signatures: { type: [signatureSchema], default: [] },
    reminders: { type: [reminderLogSchema], default: [] },
    sentAt: { type: Date, default: null },
    signedAt: { type: Date, default: null },
  },
  { timestamps: true }
);

export const Contract =
  (models.Contract as mongoose.Model<ContractDoc>) || model<ContractDoc>("Contract", contractSchema);
