import prisma from '../lib/prisma.js';

export interface BirthdayEntry {
  customerId: number;
  customerNumber: string;
  name: string;
  birthDate: Date;
  age: number;            // Alter das der Kunde wird bzw. geworden ist
  daysUntil: number;      // 0 = heute, -3 = vor 3 Tagen, +5 = in 5 Tagen
  isToday: boolean;
  isPast: boolean;        // Geburtstag war in den letzten Tagen
  portalEnabled: boolean;
  email?: string | null;
  phone?: string | null;
}

/**
 * Berechnet die Anzahl Tage von "heute" bis zum nächsten Vorkommen eines Geburtstags.
 * Negative Werte = Geburtstag war kürzlich, positive = Geburtstag steht bevor.
 *
 * Für den Zeitraum `[-pastDays, +futureDays]` suchen wir den relevantesten Wert:
 * - ist der Geburtstag dieses Jahr innerhalb des Fensters → dieser
 * - sonst: nichts (nicht relevant)
 */
function daysDifferenceInWindow(
  birthDate: Date,
  today: Date,
  pastDays: number,
  futureDays: number,
): number | null {
  const month = birthDate.getMonth();
  const day = birthDate.getDate();

  // Geburtstag dieses Jahr
  const thisYear = new Date(today.getFullYear(), month, day);
  thisYear.setHours(0, 0, 0, 0);

  const todayNormalized = new Date(today);
  todayNormalized.setHours(0, 0, 0, 0);

  const msPerDay = 1000 * 60 * 60 * 24;
  const diffThisYear = Math.round((thisYear.getTime() - todayNormalized.getTime()) / msPerDay);

  // Falls im Fenster → nutzen
  if (diffThisYear >= -pastDays && diffThisYear <= futureDays) {
    return diffThisYear;
  }

  // Falls Geburtstag schon lange vorbei (>pastDays her), ist nächstes Jahr relevant
  if (diffThisYear < -pastDays) {
    const nextYear = new Date(today.getFullYear() + 1, month, day);
    nextYear.setHours(0, 0, 0, 0);
    const diffNextYear = Math.round((nextYear.getTime() - todayNormalized.getTime()) / msPerDay);
    if (diffNextYear <= futureDays) {
      return diffNextYear;
    }
  }

  return null;
}

function calculateAge(birthDate: Date, refDate: Date): number {
  let age = refDate.getFullYear() - birthDate.getFullYear();
  const m = refDate.getMonth() - birthDate.getMonth();
  if (m < 0 || (m === 0 && refDate.getDate() < birthDate.getDate())) {
    age--;
  }
  return age;
}

/**
 * Kommende und vergangene Geburtstage in einem Fenster von [pastDays, futureDays].
 * Default: 7 Tage zurück, 30 Tage voraus.
 */
export async function getUpcomingBirthdays(
  pastDays: number = 7,
  futureDays: number = 30,
): Promise<BirthdayEntry[]> {
  const customers = await prisma.customer.findMany({
    where: {
      birthDate: { not: null },
    },
    select: {
      id: true,
      customerNumber: true,
      firstName: true,
      lastName: true,
      companyName: true,
      birthDate: true,
      portalEnabled: true,
      email: true,
      phone: true,
    },
  });

  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const entries: BirthdayEntry[] = [];
  for (const c of customers) {
    if (!c.birthDate) continue;
    const daysUntil = daysDifferenceInWindow(c.birthDate, today, pastDays, futureDays);
    if (daysUntil === null) continue;

    // Alter am nächsten Geburtstag (bei daysUntil >= 0) bzw. aktuelles Alter (daysUntil < 0)
    const refDate = new Date(today);
    refDate.setDate(refDate.getDate() + daysUntil);
    const age = calculateAge(c.birthDate, refDate);

    entries.push({
      customerId: c.id,
      customerNumber: c.customerNumber,
      name: c.companyName || `${c.firstName} ${c.lastName}`.trim(),
      birthDate: c.birthDate,
      age,
      daysUntil,
      isToday: daysUntil === 0,
      isPast: daysUntil < 0,
      portalEnabled: c.portalEnabled,
      email: c.email,
      phone: c.phone,
    });
  }

  // Sortiert: zuerst heute, dann kommende aufsteigend, dann vergangene absteigend
  entries.sort((a, b) => {
    if (a.daysUntil === 0 && b.daysUntil !== 0) return -1;
    if (b.daysUntil === 0 && a.daysUntil !== 0) return 1;
    if (a.daysUntil >= 0 && b.daysUntil >= 0) return a.daysUntil - b.daysUntil;
    if (a.daysUntil < 0 && b.daysUntil < 0) return b.daysUntil - a.daysUntil;
    // kommende vor vergangenen
    return a.daysUntil >= 0 ? -1 : 1;
  });

  return entries;
}

export interface MyBirthdayCheck {
  show: boolean;              // Modal anzeigen?
  isToday: boolean;
  daysAgo: number;            // 0 = heute, >0 = x Tage her
  firstName: string;
  lastName: string;
  salutation: string | null;
  useInformalAddress: boolean;
  age: number;
}

/**
 * Portal-Check: Soll dem Kunden ein Geburtstagsmodal angezeigt werden?
 * - Heute oder in den letzten 7 Tagen
 * - Modal dieses Jahr noch nicht gezeigt (lastBirthdayGreetingYear != aktuelles Jahr)
 */
export async function checkMyBirthday(customerId: number): Promise<MyBirthdayCheck | null> {
  const customer = await prisma.customer.findUnique({
    where: { id: customerId },
    select: {
      firstName: true,
      lastName: true,
      salutation: true,
      useInformalAddress: true,
      birthDate: true,
      lastBirthdayGreetingYear: true,
    },
  });

  if (!customer?.birthDate) return null;

  const baseInfo = {
    firstName: customer.firstName,
    lastName: customer.lastName,
    salutation: customer.salutation,
    useInformalAddress: customer.useInformalAddress,
  };

  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const thisYear = today.getFullYear();

  // Schon dieses Jahr angezeigt?
  if (customer.lastBirthdayGreetingYear === thisYear) {
    return { show: false, isToday: false, daysAgo: 0, ...baseInfo, age: 0 };
  }

  const birthday = new Date(thisYear, customer.birthDate.getMonth(), customer.birthDate.getDate());
  birthday.setHours(0, 0, 0, 0);

  const msPerDay = 1000 * 60 * 60 * 24;
  const diff = Math.round((today.getTime() - birthday.getTime()) / msPerDay);

  // Nur wenn heute oder in den letzten 7 Tagen (diff: 0–7)
  if (diff < 0 || diff > 7) {
    return { show: false, isToday: false, daysAgo: 0, ...baseInfo, age: 0 };
  }

  const age = calculateAge(customer.birthDate, today);

  return {
    show: true,
    isToday: diff === 0,
    daysAgo: diff,
    ...baseInfo,
    age,
  };
}

/**
 * Markiert, dass dem Kunden das Geburtstagsmodal dieses Jahr bereits gezeigt wurde.
 */
export async function acknowledgeBirthdayGreeting(customerId: number): Promise<void> {
  const thisYear = new Date().getFullYear();
  await prisma.customer.update({
    where: { id: customerId },
    data: { lastBirthdayGreetingYear: thisYear },
  });
}

/**
 * Setzt den Gruß-Marker zurück, damit das Modal beim nächsten Login wieder erscheint.
 * (Für Mitarbeiter – nützlich zum Debuggen und als Fallback wenn etwas schief ging.)
 */
export async function resetBirthdayGreeting(customerId: number): Promise<void> {
  await prisma.customer.update({
    where: { id: customerId },
    data: { lastBirthdayGreetingYear: null },
  });
}

/**
 * Generiert den persönlichen Geburtstagsgruß-Text (Du/Sie-abhängig).
 */
export function buildBirthdayGreetingText(
  customer: {
    firstName: string;
    lastName: string;
    salutation: string | null;
    useInformalAddress: boolean;
  },
  age: number,
): { subject: string; plain: string; html: string } {
  const name = customer.useInformalAddress
    ? customer.firstName
    : [customer.salutation, customer.lastName].filter(Boolean).join(' ') || customer.firstName;
  const du = customer.useInformalAddress;
  const pronoun = du ? 'dir' : 'Ihnen';
  const possessive = du ? 'deinem' : 'Ihrem';
  const yourLower = du ? 'dein' : 'Ihr';

  const subject = du
    ? `Alles Gute zum Geburtstag, ${customer.firstName}! 🎉`
    : 'Herzlichen Glückwunsch zum Geburtstag 🎉';

  // Plain-Text ohne Emojis, damit WhatsApp/Telegram/Signal-URL-Handler nicht stolpern
  const plain = [
    `Herzlichen Glückwunsch, ${name}!`,
    '',
    age > 0
      ? `Alles Gute zu ${possessive} ${age}. Geburtstag!`
      : `Alles Gute zu ${possessive} Geburtstag!`,
    '',
    `Wir wünschen ${pronoun} einen wunderschönen Tag und alles Gute für ${yourLower} neues Lebensjahr.`,
    '',
    'Herzliche Grüße',
    'Hacker-Net Telekommunikation',
  ].join('\n');

  const html = `
    <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
      <div style="background: linear-gradient(135deg, #ec4899 0%, #8b5cf6 50%, #6366f1 100%); padding: 40px 20px; text-align: center; border-radius: 12px 12px 0 0;">
        <div style="font-size: 64px; margin-bottom: 8px;">🎉🎂🎈</div>
      </div>
      <div style="padding: 32px; background: #ffffff; border: 1px solid #e5e7eb; border-top: none; border-radius: 0 0 12px 12px;">
        <h2 style="color: #1f2937; margin-top: 0;">Herzlichen Glückwunsch, ${name}!</h2>
        <p style="color: #4b5563; font-size: 16px; line-height: 1.6;">
          ${age > 0 ? `Alles Gute zu ${possessive} <strong>${age}. Geburtstag</strong>!` : `Alles Gute zu ${possessive} Geburtstag!`}
        </p>
        <p style="color: #6b7280; font-size: 14px; line-height: 1.6;">
          Wir wünschen ${pronoun} einen wunderschönen Tag und alles Gute für ${yourLower} neues Lebensjahr. 🌟
        </p>
        <hr style="border: none; border-top: 1px solid #e5e7eb; margin: 24px 0;">
        <p style="color: #9ca3af; font-size: 12px; margin: 0;">
          Herzliche Grüße<br>
          <strong>Hacker-Net Telekommunikation</strong><br>
          Am Wunderburgpark 5b, 26135 Oldenburg<br>
          info@hacker-net.de
        </p>
      </div>
    </div>
  `;

  return { subject, plain, html };
}

/**
 * Lädt die für den Gruß benötigten Kundendaten inkl. aktuellem Alter heute.
 */
export async function getBirthdayGreetingData(customerId: number): Promise<{
  firstName: string;
  lastName: string;
  salutation: string | null;
  useInformalAddress: boolean;
  email: string | null;
  phone: string | null;
  mobile: string | null;
  age: number;
} | null> {
  const c = await prisma.customer.findUnique({
    where: { id: customerId },
    select: {
      firstName: true,
      lastName: true,
      salutation: true,
      useInformalAddress: true,
      email: true,
      phone: true,
      mobile: true,
      birthDate: true,
    },
  });

  if (!c?.birthDate) return null;

  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const age = calculateAge(c.birthDate, today);

  return {
    firstName: c.firstName,
    lastName: c.lastName,
    salutation: c.salutation,
    useInformalAddress: c.useInformalAddress,
    email: c.email,
    phone: c.phone,
    mobile: c.mobile,
    age,
  };
}
