/**
 * WhatsApp Language Preference Service
 *
 * Manages language preferences for WhatsApp users on a per-organization basis.
 * Used by n8n workflows to persist user language choices for bilingual AI agents.
 *
 * @module lib/services/whatsapp-language.service
 */

import { prisma } from "@/lib/db";
import { logger } from "@/lib/logger";

// =============================================================================
// Types
// =============================================================================

export type SupportedLanguage = "en" | "ar";

export interface LanguagePreferenceResult {
  id: string;
  organizationId: string;
  userId: string; // This is actually userPhone in the context
  language: string;
  selectedAt: Date;
}

// =============================================================================
// Service Functions
// =============================================================================

/**
 * Get language preference for a user (identified by phone) in an organization
 *
 * @param organizationId - The organization ID
 * @param phone - User's phone number (normalized)
 * @returns The language preference ('en' or 'ar') or null if not set
 *
 * @example
 * const lang = await getLanguagePreference('org_123', '+97412345678');
 * // Returns: 'ar' | 'en' | null
 */
export async function getLanguagePreference(
  organizationId: string,
  phone: string
): Promise<string | null> {
  try {
    // Normalize phone number (remove non-digits, keep + prefix if present)
    const normalizedPhone = normalizePhoneNumber(phone);

    const preference = await prisma.user_language_preferences.findUnique({
      where: {
        organizationId_userPhone: {
          organizationId,
          userPhone: normalizedPhone,
        },
      },
      select: {
        language: true,
      },
    });

    if (!preference) {
      logger.debug("No language preference found", {
        organizationId,
        phone: maskPhone(normalizedPhone),
      });
      return null;
    }

    return preference.language;
  } catch (error) {
    logger.error("Failed to get language preference", {
      error: error instanceof Error ? error.message : "Unknown error",
      organizationId,
    });
    throw error;
  }
}

/**
 * Set language preference for a user (identified by phone) in an organization
 *
 * Creates a new preference or updates existing one (upsert).
 *
 * @param organizationId - The organization ID
 * @param phone - User's phone number
 * @param language - Preferred language ('en' or 'ar')
 * @returns The created/updated preference record
 *
 * @example
 * const pref = await setLanguagePreference('org_123', '+97412345678', 'ar');
 * // Returns: { id, organizationId, userId, language, selectedAt }
 */
export async function setLanguagePreference(
  organizationId: string,
  phone: string,
  language: SupportedLanguage
): Promise<LanguagePreferenceResult> {
  try {
    // Validate organization exists
    const org = await prisma.organizations.findUnique({
      where: { id: organizationId },
      select: { id: true },
    });

    if (!org) {
      throw new Error(`Organization not found: ${organizationId}`);
    }

    // Normalize phone number
    const normalizedPhone = normalizePhoneNumber(phone);
    const now = new Date();

    const preference = await prisma.user_language_preferences.upsert({
      where: {
        organizationId_userPhone: {
          organizationId,
          userPhone: normalizedPhone,
        },
      },
      create: {
        organizationId,
        userPhone: normalizedPhone,
        language,
        selectedAt: now,
        updatedAt: now,
      },
      update: {
        language,
        selectedAt: now,
        updatedAt: now,
      },
    });

    logger.info("Language preference set", {
      organizationId,
      phone: maskPhone(normalizedPhone),
      language,
    });

    return {
      id: preference.id,
      organizationId: preference.organizationId,
      userId: preference.userPhone, // Map userPhone to userId for API compatibility
      language: preference.language,
      selectedAt: preference.selectedAt,
    };
  } catch (error) {
    logger.error("Failed to set language preference", {
      error: error instanceof Error ? error.message : "Unknown error",
      organizationId,
      language,
    });
    throw error;
  }
}

/**
 * Delete language preference for a user
 * Useful when a user wants to reset their preference or for cleanup
 *
 * @param organizationId - The organization ID
 * @param phone - User's phone number
 * @returns true if deleted, false if not found
 */
export async function deleteLanguagePreference(
  organizationId: string,
  phone: string
): Promise<boolean> {
  try {
    const normalizedPhone = normalizePhoneNumber(phone);

    const deleted = await prisma.user_language_preferences.deleteMany({
      where: {
        organizationId,
        userPhone: normalizedPhone,
      },
    });

    if (deleted.count > 0) {
      logger.info("Language preference deleted", {
        organizationId,
        phone: maskPhone(normalizedPhone),
      });
      return true;
    }

    return false;
  } catch (error) {
    logger.error("Failed to delete language preference", {
      error: error instanceof Error ? error.message : "Unknown error",
      organizationId,
    });
    throw error;
  }
}

/**
 * Get all language preferences for an organization
 * Useful for analytics and bulk operations
 *
 * @param organizationId - The organization ID
 * @param limit - Maximum number of records to return (default: 100)
 * @returns Array of language preferences
 */
export async function getOrganizationLanguagePreferences(
  organizationId: string,
  limit: number = 100
): Promise<LanguagePreferenceResult[]> {
  try {
    const preferences = await prisma.user_language_preferences.findMany({
      where: { organizationId },
      orderBy: { selectedAt: "desc" },
      take: limit,
    });

    return preferences.map((pref) => ({
      id: pref.id,
      organizationId: pref.organizationId,
      userId: pref.userPhone,
      language: pref.language,
      selectedAt: pref.selectedAt,
    }));
  } catch (error) {
    logger.error("Failed to get organization language preferences", {
      error: error instanceof Error ? error.message : "Unknown error",
      organizationId,
    });
    throw error;
  }
}

/**
 * Get language distribution statistics for an organization
 *
 * @param organizationId - The organization ID
 * @returns Object with language counts { en: number, ar: number, total: number }
 */
export async function getLanguageStats(
  organizationId: string
): Promise<{ en: number; ar: number; total: number }> {
  try {
    const [enCount, arCount] = await Promise.all([
      prisma.user_language_preferences.count({
        where: { organizationId, language: "en" },
      }),
      prisma.user_language_preferences.count({
        where: { organizationId, language: "ar" },
      }),
    ]);

    return {
      en: enCount,
      ar: arCount,
      total: enCount + arCount,
    };
  } catch (error) {
    logger.error("Failed to get language stats", {
      error: error instanceof Error ? error.message : "Unknown error",
      organizationId,
    });
    throw error;
  }
}

// =============================================================================
// Helper Functions
// =============================================================================

/**
 * Normalize phone number for consistent storage
 * Keeps the + prefix and digits only
 */
function normalizePhoneNumber(phone: string): string {
  // Keep + prefix if present, then keep only digits
  const hasPlus = phone.startsWith("+");
  const digits = phone.replace(/\D/g, "");
  return hasPlus ? `+${digits}` : digits;
}

/**
 * Mask phone number for logging (privacy)
 * Shows only last 4 digits
 */
function maskPhone(phone: string): string {
  if (phone.length <= 4) {
    return "****";
  }
  return `****${phone.slice(-4)}`;
}
