const axios = require('axios');
const adminConfig = require('./adminConfig');
const { readNotificationSettings } = require('./userSettingsStore');
const DISPLAY_TIME_ZONE = 'Europe/Berlin';

function formatDateLabel(dateInput) {
  try {
    const date = new Date(dateInput);
    if (Number.isNaN(date.getTime())) {
      return 'unbekanntes Datum';
    }
    return date.toLocaleString('de-DE', {
      weekday: 'short',
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      timeZone: DISPLAY_TIME_ZONE
    });
  } catch (_error) {
    return 'unbekanntes Datum';
  }
}

function formatDateOnly(dateInput) {
  try {
    const date = new Date(dateInput);
    if (Number.isNaN(date.getTime())) {
      return 'unbekanntes Datum';
    }
    return date.toLocaleDateString('de-DE', {
      day: '2-digit',
      month: '2-digit',
      year: 'numeric',
      timeZone: DISPLAY_TIME_ZONE
    });
  } catch (_error) {
    return 'unbekanntes Datum';
  }
}

function extractFirstName(profileName) {
  if (!profileName || typeof profileName !== 'string') {
    return null;
  }
  const trimmed = profileName.trim();
  if (!trimmed) {
    return null;
  }
  if (trimmed.includes(',')) {
    const parts = trimmed.split(',').map((part) => part.trim()).filter(Boolean);
    if (parts.length > 1) {
      return parts[1].split(/\s+/)[0] || null;
    }
  }
  return trimmed.split(/\s+/)[0] || null;
}

async function sendNtfyNotification(adminNtfy, userNtfy, payload) {
  if (!adminNtfy?.enabled || !userNtfy?.enabled || !userNtfy.topic) {
    return;
  }
  const server = (userNtfy.serverUrl || adminNtfy.serverUrl || 'https://ntfy.sh').replace(/\/+$/, '');
  const sanitizedPrefix = (adminNtfy.topicPrefix || '').replace(/^-+|-+$/g, '');
  const sanitizedTopic = (userNtfy.topic || '').replace(/^-+|-+$/g, '');
  const topic = `${sanitizedPrefix}${sanitizedTopic}` || sanitizedPrefix || sanitizedTopic;
  let url = `${server}/${topic}`;
  if (payload.title) {
    const delimiter = url.includes('?') ? '&' : '?';
    url = `${url}${delimiter}title=${encodeURIComponent(payload.title)}`;
  }
  const headers = {
    Priority: payload.priority || 'default',
    'Content-Type': 'text/plain; charset=utf-8'
  };
  if (adminNtfy.username && adminNtfy.password) {
    const credentials = Buffer.from(`${adminNtfy.username}:${adminNtfy.password}`).toString('base64');
    headers.Authorization = `Basic ${credentials}`;
  }
  await axios.post(url, payload.message, { headers, timeout: 15000 });
}

async function sendTelegramNotification(adminTelegram, userTelegram, payload) {
  if (!adminTelegram?.enabled || !adminTelegram.botToken || !userTelegram?.enabled || !userTelegram.chatId) {
    return;
  }
  const endpoint = `https://api.telegram.org/bot${adminTelegram.botToken}/sendMessage`;
  const profileLabel = extractFirstName(payload?.profileName);
  const messageParts = [
    payload?.title ? `*${payload.title}*` : null,
    profileLabel ? `Profil: ${profileLabel}` : null,
    payload?.message || null
  ].filter(Boolean);
  await axios.post(
    endpoint,
    {
      chat_id: userTelegram.chatId,
      text: messageParts.join('\n'),
      parse_mode: payload?.title ? 'Markdown' : undefined,
      disable_web_page_preview: true
    },
    { timeout: 15000 }
  );
}

async function sendAdminTelegramNotification(payload) {
  const adminSettings = adminConfig.readSettings();
  const adminTelegram = adminSettings.notifications?.telegram;
  if (!adminTelegram?.enabled || !adminTelegram.botToken || !adminTelegram.chatId) {
    return;
  }
  await sendTelegramNotification(
    adminTelegram,
    { enabled: true, chatId: adminTelegram.chatId },
    payload
  );
}

async function notifyChannels(profileId, template) {
  const adminSettings = adminConfig.readSettings();
  const userSettings = readNotificationSettings(profileId);
  try {
    await Promise.allSettled([
      sendNtfyNotification(adminSettings.notifications?.ntfy, userSettings.notifications?.ntfy, template),
      sendTelegramNotification(adminSettings.notifications?.telegram, userSettings.notifications?.telegram, template)
    ]);
  } catch (error) {
    console.error('[NOTIFICATIONS] Versand fehlgeschlagen:', error.message);
  }
}

async function sendSlotNotification({ profileId, profileName, storeName, pickupDate, onlyNotify, booked, storeId }) {
  const dateLabel = formatDateLabel(pickupDate);
  const title = onlyNotify
    ? `Slot verfügbar bei ${storeName}`
    : booked
    ? `Slot gebucht bei ${storeName}`
    : `Slot gefunden bei ${storeName}`;
  const baseMessage = onlyNotify
    ? `Es wurde ein freier Slot am ${dateLabel} entdeckt.`
    : booked
    ? `Der Slot am ${dateLabel} wurde erfolgreich gebucht.`
    : `Es wurde ein Slot am ${dateLabel} gefunden.`;
  const storeLink = storeId ? `https://foodsharing.de/store/${storeId}` : null;
  const fullMessage = storeLink ? `${baseMessage}\n${storeLink}` : baseMessage;

  await notifyChannels(profileId, {
    title,
    message: fullMessage,
    link: storeLink,
    priority: booked ? 'high' : 'default',
    profileName
  });
}

function formatStoreWatchStatus(status) {
  if (status === 1) {
    return 'Suchend';
  }
  if (status === 0) {
    return 'Nicht suchend';
  }
  return 'Status unbekannt';
}

async function sendStoreWatchNotification({ profileId, profileName, storeName, storeId, regionName }) {
  const storeLink = storeId ? `https://foodsharing.de/store/${storeId}` : null;
  const title = `Team sucht Verstärkung: ${storeName}`;
  const regionText = regionName ? ` (${regionName})` : '';
  const messageBase = `Der Betrieb${regionText} sucht wieder aktiv neue Teammitglieder.`;
  const message = storeLink ? `${messageBase}\n${storeLink}` : messageBase;
  await notifyChannels(profileId, {
    title,
    message,
    link: storeLink,
    priority: 'high',
    profileName
  });
}

async function sendStoreWatchSummaryNotification({ profileId, profileName, entries = [], triggeredBy = 'manual' }) {
  if (!profileId || !Array.isArray(entries) || entries.length === 0) {
    return;
  }
  const lines = entries
    .map((entry) => {
      const regionSuffix = entry.regionName ? ` (${entry.regionName})` : '';
      const statusLabel = formatStoreWatchStatus(entry.status);
      const timestamp = entry.checkedAt ? ` – Stand ${formatDateLabel(entry.checkedAt)}` : '';
      const errorLabel = entry.error ? ` – Fehler: ${entry.error}` : '';
      return `• ${entry.storeName || `Store ${entry.storeId}`}${regionSuffix}: ${statusLabel}${timestamp}${errorLabel}`;
    })
    .join('\n');
  const prefix =
    triggeredBy === 'manual'
      ? 'Manuell angestoßene Store-Watch-Aktualisierung abgeschlossen:'
      : 'Store-Watch-Prüfung abgeschlossen:';
  const title =
    triggeredBy === 'manual' ? 'Store-Watch-Aktualisierung' : 'Store-Watch-Prüfung';
  const message = `${prefix}\n${lines}`;
  await notifyChannels(profileId, {
    title,
    message,
    priority: 'default',
    profileName
  });
}

async function sendDesiredWindowMissedNotification({ profileId, profileName, storeName, desiredWindowLabel }) {
  if (!profileId) {
    return;
  }
  const title = `Keine Slots gefunden: ${storeName}`;
  const messageBase = desiredWindowLabel
    ? `Für den gewünschten Zeitraum ${desiredWindowLabel} konnte kein Slot gefunden werden.`
    : 'Für den gewünschten Zeitraum konnte kein Slot gefunden werden.';
  const message = `${messageBase} Der Eintrag wurde deaktiviert.`;
  await notifyChannels(profileId, {
    title,
    message,
    link: null,
    priority: 'default',
    profileName
  });
}

async function sendTestNotification(profileId, channel) {
  const title = 'Pickup Benachrichtigung (Test)';
  const message = 'Das ist eine Testnachricht. Bei Fragen wende dich bitte an den Admin.';
  const adminSettings = adminConfig.readSettings();
  const userSettings = readNotificationSettings(profileId);
  const tasks = [];

  if (!channel || channel === 'ntfy') {
    tasks.push(
      sendNtfyNotification(adminSettings.notifications?.ntfy, userSettings.notifications?.ntfy, {
        title,
        message,
        priority: 'default'
      })
    );
  }
  if (!channel || channel === 'telegram') {
    tasks.push(
      sendTelegramNotification(adminSettings.notifications?.telegram, userSettings.notifications?.telegram, {
        title,
        message,
        priority: 'default'
      })
    );
  }

  if (tasks.length === 0) {
    throw new Error('Kein unterstützter Kanal oder Kanal deaktiviert.');
  }

  await Promise.all(tasks);
}

async function sendDormantPickupWarning({ profileId, profileName, storeName, storeId, reasonLines = [] }) {
  if (!profileId || !Array.isArray(reasonLines) || reasonLines.length === 0) {
    return;
  }
  const adminSettings = adminConfig.readSettings();
  const userSettings = readNotificationSettings(profileId);
  const storeLink = storeId ? `https://foodsharing.de/store/${storeId}` : null;
  const title = `Prüfung fällig: ${storeName}`;
  const messageBody = reasonLines.join('\n');
  const message = storeLink ? `${messageBody}\n${storeLink}` : messageBody;

  await sendTelegramNotification(adminSettings.notifications?.telegram, userSettings.notifications?.telegram, {
    title,
    message,
    priority: 'high',
    profileName
  });
}

async function sendJournalReminderNotification({
  profileId,
  profileName,
  storeName,
  pickupDate,
  reminderDate,
  note
}) {
  if (!profileId) {
    return;
  }
  const adminSettings = adminConfig.readSettings();
  const userSettings = readNotificationSettings(profileId);
  const title = `Erinnerung: Abholung bei ${storeName}`;
  const reminderLabel = formatDateOnly(reminderDate);
  const pickupLabel = formatDateOnly(pickupDate);
  const noteLine = note ? `Notiz: ${note}` : null;
  const messageLines = [
    `Geplante Abholung: ${pickupLabel}`,
    `Erinnerungstermin: ${reminderLabel}`,
    noteLine
  ].filter(Boolean);
  await sendTelegramNotification(adminSettings.notifications?.telegram, userSettings.notifications?.telegram, {
    title,
    message: messageLines.join('\n'),
    priority: 'default',
    profileName
  });
}

async function sendAdminBookingErrorNotification({ profileId, profileEmail, storeName, storeId, pickupDate, error }) {
  const dateLabel = formatDateLabel(pickupDate);
  const storeLabel = storeName || storeId || 'Unbekannter Store';
  const storeLink = storeId ? `https://foodsharing.de/store/${storeId}` : null;
  const profileLabel = profileEmail || profileId || 'Unbekanntes Profil';
  const messageLines = [
    `Buchung fehlgeschlagen für ${storeLabel} am ${dateLabel}.`,
    `Profil: ${profileLabel}.`,
    `Fehler: ${error || 'Unbekannter Fehler'}.`
  ];
  if (storeLink) {
    messageLines.push(storeLink);
  }
  await sendAdminTelegramNotification({
    title: 'Fehler beim Slot-Buchen',
    message: messageLines.join('\n'),
    priority: 'high'
  });
}

async function sendAdminSessionErrorNotification({
  profileId,
  profileEmail,
  profileName,
  sessionId,
  error,
  label
}) {
  const profileLabel = profileEmail || profileId || 'Unbekanntes Profil';
  const messageLines = [
    'Session-Login fehlgeschlagen.',
    `Profil: ${profileLabel}.`,
    profileName ? `Name: ${profileName}.` : null,
    sessionId ? `Session: ${sessionId}.` : null,
    label ? `Kontext: ${label}.` : null,
    `Fehler: ${error || 'Unbekannter Fehler'}.`
  ].filter(Boolean);
  await sendAdminTelegramNotification({
    title: 'Fehler beim Session-Login',
    message: messageLines.join('\n'),
    priority: 'high'
  });
}

async function sendAdminMaintenanceModeNotification({ reason, activatedAt, errorThreshold, errorWindowMinutes }) {
  const messageLines = [
    'Der Wartungsmodus wurde automatisch aktiviert.',
    activatedAt ? `Aktiv seit: ${formatDateLabel(activatedAt)}.` : null,
    Number.isFinite(errorThreshold) && Number.isFinite(errorWindowMinutes)
      ? `Schwelle: ${errorThreshold} relevante Fehler in ${errorWindowMinutes} Minuten.`
      : null,
    reason ? `Grund: ${reason}.` : null
  ].filter(Boolean);
  await sendAdminTelegramNotification({
    title: 'Wartungsmodus aktiviert',
    message: messageLines.join('\n'),
    priority: 'high'
  });
}

module.exports = {
  sendSlotNotification,
  sendStoreWatchNotification,
  sendStoreWatchSummaryNotification,
  sendTestNotification,
  sendDesiredWindowMissedNotification,
  sendDormantPickupWarning,
  sendJournalReminderNotification,
  sendAdminBookingErrorNotification,
  sendAdminSessionErrorNotification,
  sendAdminMaintenanceModeNotification
};
