/**
 * Preferences Tab Component
 * Language, timezone, notifications, dashboard settings
 *
 * Features:
 * - Language switching with automatic page redirect
 * - Timezone selection for GCC countries
 * - Email notification preferences with 6 categories
 * - Real-time save with confirmation email
 * - Error handling with user-friendly messages
 */

"use client";

import {
  useState,
  useEffect,
  useCallback,
  useMemo,
  Component,
  type ReactNode,
} from "react";
import type { Lang } from "@/lib/config";

// ============================================================================
// Error Boundary Component (H2 Fix)
// ============================================================================

interface ErrorBoundaryProps {
  lang: Lang;
  children: ReactNode;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error: Error | null;
}

/**
 * Error Boundary for PreferencesTab
 * Catches rendering errors and displays a user-friendly fallback UI
 */
class PreferencesErrorBoundary extends Component<
  ErrorBoundaryProps,
  ErrorBoundaryState
> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error(
      "[PreferencesTab] Error caught by boundary:",
      error,
      errorInfo,
    );
  }

  handleRetry = () => {
    this.setState({ hasError: false, error: null });
  };

  render() {
    if (this.state.hasError) {
      const isAr = this.props.lang === "ar";

      return (
        <div className="rounded-lg bg-red-50 border border-red-200 p-6 text-center">
          <svg
            className="mx-auto h-12 w-12 text-red-400"
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
            aria-hidden="true"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
            />
          </svg>
          <h3 className="mt-4 text-lg font-semibold text-red-800">
            {isAr ? "حدث خطأ في تحميل التفضيلات" : "Error Loading Preferences"}
          </h3>
          <p className="mt-2 text-sm text-red-600">
            {isAr
              ? "نواجه مشكلة في عرض إعدادات التفضيلات. يرجى المحاولة مرة أخرى."
              : "We encountered a problem displaying your preferences. Please try again."}
          </p>
          <button
            onClick={this.handleRetry}
            className="mt-4 rounded-lg bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 transition-colors"
          >
            {isAr ? "إعادة المحاولة" : "Try Again"}
          </button>
        </div>
      );
    }

    return this.props.children;
  }
}

// ============================================================================
// Type Definitions
// ============================================================================

interface PreferencesTabProps {
  lang: Lang;
  onUnsavedChanges?: (hasChanges: boolean) => void;
}

interface EmailNotifications {
  bookings: boolean;
  reminders: boolean;
  payments: boolean;
  marketing: boolean;
  security: boolean;
  weeklyReport: boolean;
}

interface Preferences {
  language: string;
  timezone: string;
  emailNotifications: EmailNotifications;
  emailFrequency: string;
}

interface NotificationConfig {
  readonly key: keyof EmailNotifications;
  readonly labelEn: string;
  readonly labelAr: string;
}

interface TimezoneConfig {
  readonly value: string;
  readonly labelEn: string;
  readonly labelAr: string;
  readonly gmt: string;
}

// ============================================================================
// Configuration Arrays
// ============================================================================

/**
 * Notification types configuration
 * Makes it easy to add new notification categories
 */
const NOTIFICATION_TYPES: readonly NotificationConfig[] = [
  {
    key: "bookings",
    labelEn: "New bookings",
    labelAr: "حجوزات جديدة",
  },
  {
    key: "reminders",
    labelEn: "Appointment reminders",
    labelAr: "تذكيرات المواعيد",
  },
  {
    key: "payments",
    labelEn: "Payment receipts",
    labelAr: "إيصالات الدفع",
  },
  {
    key: "marketing",
    labelEn: "Marketing emails",
    labelAr: "رسائل تسويقية",
  },
  {
    key: "security",
    labelEn: "Security alerts",
    labelAr: "تنبيهات أمنية",
  },
  {
    key: "weeklyReport",
    labelEn: "Weekly report",
    labelAr: "تقرير أسبوعي",
  },
] as const;

/**
 * GCC timezone options
 * Covers all major GCC countries
 */
const TIMEZONE_OPTIONS: readonly TimezoneConfig[] = [
  {
    value: "Asia/Qatar",
    labelEn: "Qatar",
    labelAr: "قطر",
    gmt: "GMT+3",
  },
  {
    value: "Asia/Dubai",
    labelEn: "UAE",
    labelAr: "الإمارات",
    gmt: "GMT+4",
  },
  {
    value: "Asia/Riyadh",
    labelEn: "Saudi Arabia",
    labelAr: "السعودية",
    gmt: "GMT+3",
  },
  {
    value: "Asia/Kuwait",
    labelEn: "Kuwait",
    labelAr: "الكويت",
    gmt: "GMT+3",
  },
  {
    value: "Asia/Bahrain",
    labelEn: "Bahrain",
    labelAr: "البحرين",
    gmt: "GMT+3",
  },
  {
    value: "Asia/Muscat",
    labelEn: "Oman",
    labelAr: "عمان",
    gmt: "GMT+4",
  },
] as const;

/**
 * Default email notification settings
 */
const DEFAULT_EMAIL_NOTIFICATIONS: EmailNotifications = {
  bookings: true,
  reminders: true,
  payments: true,
  marketing: false,
  security: true,
  weeklyReport: false,
};

// ============================================================================
// Custom Hook
// ============================================================================

/**
 * Custom hook for managing user preferences state and API interactions
 *
 * @param lang - Current language ('ar' | 'en')
 * @param onUnsavedChanges - Callback fired when preferences have unsaved changes
 * @returns Object containing preferences state, loading states, and save function
 */
function usePreferences(
  lang: Lang,
  onUnsavedChanges?: (hasChanges: boolean) => void,
) {
  const isAr = lang === "ar";

  // State management
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [success, setSuccess] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const [preferences, setPreferences] = useState<Preferences>({
    language: lang,
    timezone: "Asia/Qatar",
    emailNotifications: DEFAULT_EMAIL_NOTIFICATIONS,
    emailFrequency: "instant",
  });

  const [originalPreferences, setOriginalPreferences] =
    useState<Preferences>(preferences);

  /**
   * Fetches user preferences from the API
   */
  const fetchPreferences = useCallback(async () => {
    try {
      setError(null);
      const response = await fetch("/api/user/preferences");
      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || "Failed to fetch preferences");
      }

      if (data.success && data.preferences) {
        const prefs: Preferences = {
          language: data.preferences.language || lang,
          timezone: data.preferences.timezone || "Asia/Qatar",
          emailNotifications:
            data.preferences.emailNotifications || DEFAULT_EMAIL_NOTIFICATIONS,
          emailFrequency: data.preferences.emailFrequency || "instant",
        };
        setPreferences(prefs);
        setOriginalPreferences(prefs);
      }
    } catch (err) {
      console.error("Failed to fetch preferences:", err);
      setError(isAr ? "فشل في تحميل التفضيلات" : "Failed to load preferences");
    } finally {
      setLoading(false);
    }
  }, [lang, isAr]);

  /**
   * Saves preferences to the API
   */
  const handleSave = useCallback(async () => {
    setSaving(true);
    setSuccess(false);
    setError(null);

    try {
      const csrfResponse = await fetch("/api/csrf");
      const { csrfToken } = await csrfResponse.json();

      const response = await fetch("/api/user/preferences", {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
          "x-csrf-token": csrfToken,
        },
        body: JSON.stringify(preferences),
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || "Failed to save preferences");
      }

      if (data.success) {
        setSuccess(true);
        setOriginalPreferences(preferences);
        onUnsavedChanges?.(false);

        // If language changed, redirect after showing success message briefly
        if (preferences.language !== originalPreferences.language) {
          setTimeout(() => {
            window.location.href = `/${preferences.language}/dashboard`;
          }, 1000);
        } else {
          setTimeout(() => setSuccess(false), 3000);
        }
      }
    } catch (err) {
      console.error("Failed to save preferences:", err);
      setError(
        err instanceof Error
          ? err.message
          : isAr
            ? "فشل في حفظ التفضيلات"
            : "Failed to save preferences",
      );
    } finally {
      setSaving(false);
    }
  }, [preferences, originalPreferences, onUnsavedChanges, isAr]);

  // Fetch preferences on mount
  useEffect(() => {
    fetchPreferences();
  }, [fetchPreferences]);

  // Track unsaved changes
  useEffect(() => {
    const hasChanges =
      JSON.stringify(preferences) !== JSON.stringify(originalPreferences);
    onUnsavedChanges?.(hasChanges);
  }, [preferences, originalPreferences, onUnsavedChanges]);

  // Check if language will change on save (memoized for performance)
  const languageWillChange = useMemo(
    () => preferences.language !== originalPreferences.language,
    [preferences.language, originalPreferences.language],
  );

  // Check if save button should be disabled (memoized for performance - H1 fix)
  const hasUnsavedChanges = useMemo(() => {
    // Shallow comparison for better performance than JSON.stringify
    if (preferences.language !== originalPreferences.language) return true;
    if (preferences.timezone !== originalPreferences.timezone) return true;
    if (preferences.emailFrequency !== originalPreferences.emailFrequency)
      return true;

    // Check email notification changes
    const notifKeys = Object.keys(preferences.emailNotifications) as Array<
      keyof EmailNotifications
    >;
    for (const key of notifKeys) {
      if (
        preferences.emailNotifications[key] !==
        originalPreferences.emailNotifications[key]
      ) {
        return true;
      }
    }
    return false;
  }, [preferences, originalPreferences]);

  return {
    preferences,
    setPreferences,
    originalPreferences,
    loading,
    saving,
    success,
    error,
    languageWillChange,
    hasUnsavedChanges,
    handleSave,
  };
}

// ============================================================================
// Component
// ============================================================================

/**
 * Internal preferences tab content component
 * This is wrapped by the Error Boundary in the default export
 */
function PreferencesTabContent({
  lang,
  onUnsavedChanges,
}: PreferencesTabProps) {
  const isAr = lang === "ar";

  const {
    preferences,
    setPreferences,
    loading,
    saving,
    success,
    error,
    languageWillChange,
    hasUnsavedChanges,
    handleSave,
  } = usePreferences(lang, onUnsavedChanges);

  /**
   * Toggles a notification setting
   */
  const toggleNotification = (key: keyof EmailNotifications) => {
    setPreferences({
      ...preferences,
      emailNotifications: {
        ...preferences.emailNotifications,
        [key]: !preferences.emailNotifications[key],
      },
    });
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12">
        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-brand-green"></div>
        <span className="mr-3 ml-3 text-slate-600">
          {isAr ? "جاري التحميل..." : "Loading..."}
        </span>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div>
        <h2 className="text-lg font-semibold text-slate-900">
          {isAr ? "التفضيلات" : "Preferences"}
        </h2>
        <p className="text-sm text-slate-600 mt-1">
          {isAr
            ? "تخصيص تجربتك وإشعاراتك"
            : "Customize your experience and notifications"}
        </p>
      </div>

      {/* Success Message */}
      {success && (
        <div className="rounded-lg bg-emerald-50 border border-emerald-200 p-4">
          <p className="text-sm text-emerald-700 flex items-center gap-2">
            <svg
              className="h-5 w-5 text-emerald-500"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M5 13l4 4L19 7"
              />
            </svg>
            {languageWillChange
              ? isAr
                ? "تم الحفظ! جاري إعادة التوجيه..."
                : "Saved! Redirecting..."
              : isAr
                ? "تم حفظ التفضيلات بنجاح"
                : "Preferences saved successfully"}
          </p>
        </div>
      )}

      {/* Error Message */}
      {error && (
        <div className="rounded-lg bg-red-50 border border-red-200 p-4">
          <p className="text-sm text-red-700 flex items-center gap-2">
            <svg
              className="h-5 w-5 text-red-500"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M6 18L18 6M6 6l12 12"
              />
            </svg>
            {error}
          </p>
        </div>
      )}

      {/* Language & Localization */}
      <div className="space-y-4">
        <h3 className="text-base font-semibold text-slate-900">
          {isAr ? "اللغة والتوطين" : "Language & Localization"}
        </h3>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <label className="text-sm font-medium text-slate-700 block mb-2">
              {isAr ? "اللغة" : "Language"}
            </label>
            <select
              value={preferences.language}
              onChange={(e) =>
                setPreferences({ ...preferences, language: e.target.value })
              }
              className="w-full rounded-lg border border-slate-300 px-4 py-2.5 text-sm focus:border-brand-green focus:ring-2 focus:ring-brand-green/20"
            >
              <option value="ar">العربية (Arabic)</option>
              <option value="en">English</option>
            </select>
            {/* Language change warning */}
            {languageWillChange && (
              <p className="mt-2 text-xs text-amber-600 flex items-center gap-1">
                <svg
                  className="h-4 w-4"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                  />
                </svg>
                {isAr
                  ? "سيتم إعادة تحميل الصفحة عند الحفظ"
                  : "Page will reload after saving"}
              </p>
            )}
          </div>

          <div>
            <label className="text-sm font-medium text-slate-700 block mb-2">
              {isAr ? "المنطقة الزمنية" : "Timezone"}
            </label>
            <select
              value={preferences.timezone}
              onChange={(e) =>
                setPreferences({ ...preferences, timezone: e.target.value })
              }
              className="w-full rounded-lg border border-slate-300 px-4 py-2.5 text-sm focus:border-brand-green focus:ring-2 focus:ring-brand-green/20"
            >
              {TIMEZONE_OPTIONS.map((tz) => (
                <option key={tz.value} value={tz.value}>
                  {isAr ? tz.labelAr : tz.labelEn} ({tz.gmt})
                </option>
              ))}
            </select>
          </div>
        </div>
      </div>

      {/* Email Notifications */}
      <div className="space-y-4">
        <h3 className="text-base font-semibold text-slate-900">
          {isAr ? "إشعارات البريد الإلكتروني" : "Email Notifications"}
        </h3>

        <div className="space-y-3">
          {NOTIFICATION_TYPES.map((notif) => {
            const enabled = preferences.emailNotifications[notif.key];
            return (
              <label
                key={notif.key}
                className="flex items-center justify-between p-3 rounded-lg border border-slate-200 hover:bg-slate-50 cursor-pointer"
              >
                <div>
                  <p className="text-sm font-medium text-slate-900">
                    {isAr ? notif.labelAr : notif.labelEn}
                  </p>
                </div>
                <button
                  type="button"
                  role="switch"
                  aria-checked={enabled}
                  aria-label={`${isAr ? "تبديل" : "Toggle"} ${isAr ? notif.labelAr : notif.labelEn}`}
                  onClick={() => toggleNotification(notif.key)}
                  className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-brand-green focus:ring-offset-2 ${
                    enabled ? "bg-brand-green" : "bg-slate-300"
                  }`}
                >
                  <span className="sr-only">
                    {isAr ? notif.labelAr : notif.labelEn}
                  </span>
                  <span
                    className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                      enabled ? "translate-x-6" : "translate-x-1"
                    }`}
                  />
                </button>
              </label>
            );
          })}
        </div>
      </div>

      {/* Save Button */}
      <div className="flex justify-end pt-4 border-t border-slate-200">
        <button
          onClick={handleSave}
          disabled={saving || !hasUnsavedChanges}
          className="rounded-lg bg-brand-green px-6 py-2.5 text-sm font-semibold text-white hover:bg-brand-greenHover shadow-md hover:shadow-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {saving
            ? isAr
              ? "جاري الحفظ..."
              : "Saving..."
            : isAr
              ? "حفظ التغييرات"
              : "Save Changes"}
        </button>
      </div>
    </div>
  );
}

// ============================================================================
// Exported Component with Error Boundary (H2 Fix)
// ============================================================================

/**
 * PreferencesTab wrapped with Error Boundary
 * Provides graceful error handling for any rendering issues
 */
export default function PreferencesTab(props: PreferencesTabProps) {
  return (
    <PreferencesErrorBoundary lang={props.lang}>
      <PreferencesTabContent {...props} />
    </PreferencesErrorBoundary>
  );
}
