/**
 * Account Metrics Service
 * CRUD-Operationen für account_metrics Collection
 * Verwaltet tägliche Account-Metriken (Refresh-Status, Sales-Daten)
 */

import { databases, databaseId } from "../lib/appwrite";
import { ID, Query } from "appwrite";

const accountMetricsCollectionId = "account_metrics";

/**
 * Berechnet Sales-Bucket aus Sales-Count
 * @param {number|null} salesCount - Sales-Count oder null
 * @returns {string|null} Bucket ("1+", "5+", "10+", "50+") oder null
 */
export function calculateSalesBucket(salesCount) {
  if (salesCount === null || salesCount === undefined || salesCount === 0) {
    return null;
  }

  if (salesCount >= 1 && salesCount <= 4) {
    return "1+";
  }
  if (salesCount >= 5 && salesCount <= 9) {
    return "5+";
  }
  if (salesCount >= 10 && salesCount <= 49) {
    return "10+";
  }
  if (salesCount >= 50) {
    return "50+";
  }

  return null;
}

/**
 * Formatiert Datum zu "yyyy-mm-dd" String
 * @param {Date|string} date - Date-Objekt oder ISO-String
 * @returns {string} Formatierte Datum-String
 */
function formatDate(date) {
  if (typeof date === 'string') {
    // Wenn bereits String, stelle sicher dass es yyyy-mm-dd Format ist
    const d = new Date(date);
    return d.toISOString().split('T')[0];
  }
  return date.toISOString().split('T')[0];
}

/**
 * Formatiert Datum zu "yyyy-mm" String
 * @param {Date|string} date - Date-Objekt oder ISO-String
 * @returns {string} Formatierte Monat-String
 */
function formatMonth(date) {
  const dateStr = formatDate(date);
  return dateStr.substring(0, 7); // "yyyy-mm"
}

/**
 * Erstellt oder aktualisiert eine Account-Metrik für einen Tag
 * @param {string} accountId - ID des Accounts
 * @param {string|Date} date - Datum (yyyy-mm-dd String oder Date-Objekt)
 * @param {Object} data - Metrik-Daten
 * @param {boolean} data.refreshed - Refresh-Status
 * @param {string} data.refreshStatus - "success" | "failed"
 * @param {number|null} [data.salesCount] - Sales-Differenz
 * @returns {Promise<Object>} Erstelltes oder aktualisiertes Metrik-Dokument
 */
export async function upsertAccountMetric(accountId, date, data) {
  if (!accountId) {
    throw new Error("accountId ist erforderlich");
  }

  const dateStr = formatDate(date);
  const monthStr = formatMonth(date);

  // Berechne Sales-Bucket aus salesCount
  const salesBucket = calculateSalesBucket(data.salesCount);

  // Prüfe ob Metrik für diesen Tag bereits existiert
  try {
    const existing = await databases.listDocuments(
      databaseId,
      accountMetricsCollectionId,
      [
        Query.equal("account_metrics_account_id", accountId),
        Query.equal("account_metrics_date", dateStr),
        Query.limit(1)
      ]
    );

    const payload = {
      account_metrics_account_id: accountId,
      account_metrics_date: dateStr,
      account_metrics_month: monthStr,
      account_metrics_refreshed: data.refreshed,
      account_metrics_refresh_status: data.refreshStatus,
      account_metrics_refreshed_at: data.refreshedAt || null,
      account_metrics_sales_count: data.salesCount ?? null,
      account_metrics_sales_bucket: salesBucket
    };

    // Speichere lastSalesTotal in rawSnapshot (falls vorhanden)
    // Da rawSnapshot nicht in der erlaubten Liste ist, speichern wir es nicht
    // Stattdessen: lastSalesTotal wird beim nächsten Refresh aus dem Account-Dokument geholt

    let result;
    if (existing.documents.length > 0) {
      // Update existing document
      const existingDoc = existing.documents[0];
      result = await databases.updateDocument(
        databaseId,
        accountMetricsCollectionId,
        existingDoc.$id,
        payload
      );
    } else {
      // Create new document
      result = await databases.createDocument(
        databaseId,
        accountMetricsCollectionId,
        ID.unique(),
        payload
      );
    }
    return result;
  } catch (e) {
    console.error("Fehler beim Upsert der Account-Metrik:", e);
    throw e;
  }
}

/**
 * Lädt alle Account-Metriken für einen Monat
 * @param {string} accountId - ID des Accounts
 * @param {number} year - Jahr (z.B. 2026)
 * @param {number} month - Monat (1-12)
 * @returns {Promise<Map<string, Object>>} Map von date (yyyy-mm-dd) -> Metrik-Dokument
 */
export async function fetchAccountMetricsForMonth(accountId, year, month) {
  if (!accountId) {
    throw new Error("accountId ist erforderlich");
  }

  // Formatiere Monat zu "yyyy-mm"
  const monthStr = `${year}-${String(month).padStart(2, '0')}`;

  try {
    const response = await databases.listDocuments(
      databaseId,
      accountMetricsCollectionId,
      [
        Query.equal("account_metrics_account_id", accountId),
        Query.equal("account_metrics_month", monthStr),
        Query.orderAsc("account_metrics_date")
      ]
    );

    // Konvertiere Array zu Map: date -> metric
    const metricsMap = new Map();
    for (const doc of response.documents) {
      const date = doc.account_metrics_date;
      if (date) {
        metricsMap.set(date, doc);
      }
    }

    return metricsMap;
  } catch (e) {
    // Wenn Collection nicht existiert, gib leere Map zurück
    if (e.code === 404 || e.type === 'collection_not_found') {
      console.warn("account_metrics Collection existiert noch nicht. Bitte Schema erstellen.");
      return new Map();
    }
    console.error("Fehler beim Laden der Account-Metriken:", e);
    throw e;
  }
}

/**
 * Lädt die letzte erfolgreiche Account-Metrik
 * @param {string} accountId - ID des Accounts
 * @returns {Promise<Object|null>} Letzte erfolgreiche Metrik oder null
 */
export async function getLastSuccessfulAccountMetric(accountId) {
  if (!accountId) {
    throw new Error("accountId ist erforderlich");
  }

  try {
    const response = await databases.listDocuments(
      databaseId,
      accountMetricsCollectionId,
      [
        Query.equal("account_metrics_account_id", accountId),
        Query.equal("account_metrics_refresh_status", "success"),
        Query.orderDesc("account_metrics_date"),
        Query.limit(1)
      ]
    );

    if (response.documents.length > 0) {
      return response.documents[0];
    }

    return null;
  } catch (e) {
    // Wenn Collection nicht existiert, gib null zurück
    if (e.code === 404 || e.type === 'collection_not_found') {
      return null;
    }
    console.error("Fehler beim Laden der letzten erfolgreichen Metrik:", e);
    throw e;
  }
}

