'use client';

import { useState, useSyncExternalStore } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Clock, X } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { formatTimezoneLabel } from '@/lib/i18n/timezones';

const DISMISS_STORAGE_KEY = 'pn-crm.tz-drift.dismissed';

interface MeResponse {
  data: {
    profile?: {
      timezone?: string | null;
      preferences?: { timezone?: string | null } | null;
    };
  };
}

/**
 * Detects when the user's machine timezone (via Intl) doesn't match the
 * timezone stored on their CRM profile and surfaces a small banner offering
 * a one-tap update.
 *
 * Why a banner (not auto-update): the stored timezone is what the CRM uses
 * to render due-dates, send daily-digest emails, and schedule reminders.
 * Silently re-pinning it when a rep crosses a timezone for a single day
 * would change their reminder firing time underfoot and surprise them. The
 * banner gives them control: keep the home zone, or commit to the new one.
 *
 * Dismissal is sticky per browser via localStorage so the rep isn't nagged
 * once they've decided. Clearing storage or signing in elsewhere re-asks.
 */
function getDetectedTimezone(): string | null {
  try {
    return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
  } catch {
    return null;
  }
}

function getInitialDismissed(): boolean {
  try {
    return window.localStorage.getItem(DISMISS_STORAGE_KEY) === 'true';
  } catch {
    return false;
  }
}

// useSyncExternalStore lets us read window.matchMedia-style external state
// without bouncing through useEffect → setState.
const detectedSubscribe = () => () => {};

export function TimezoneDriftBanner() {
  const queryClient = useQueryClient();
  const detected = useSyncExternalStore(detectedSubscribe, getDetectedTimezone, () => null);
  const [dismissed, setDismissed] = useState(getInitialDismissed);

  const { data: profile, isSuccess: profileLoaded } = useQuery<MeResponse>({
    queryKey: ['me'],
    queryFn: () => apiFetch<MeResponse>('/api/v1/me'),
  });
  const stored =
    profile?.data.profile?.preferences?.timezone ?? profile?.data.profile?.timezone ?? null;

  const mutation = useMutation({
    mutationFn: async (newTz: string) => {
      await apiFetch('/api/v1/users/me/preferences', {
        method: 'PATCH',
        body: { timezone: newTz },
      });
    },
    onSuccess: () => {
      toast.success(`Timezone updated to ${formatTimezoneLabel(detected ?? '')}.`);
      queryClient.invalidateQueries({ queryKey: ['me'] });
    },
    onError: (err) => toastError(err),
  });

  function dismiss() {
    setDismissed(true);
    try {
      window.localStorage.setItem(DISMISS_STORAGE_KEY, 'true');
    } catch {
      // Non-fatal - we just don't persist the dismissal.
    }
  }

  // Render gates: don't show until the profile fetch resolves (avoid
  // flashing the banner against a stale `stored=null`); don't show when
  // the detected and stored zones agree or both are missing; don't show
  // when the rep has dismissed it.
  if (!profileLoaded) return null;
  if (dismissed) return null;
  if (!detected) return null;
  if (!stored) return null;
  if (detected === stored) return null;

  return (
    <div className="flex flex-wrap items-center justify-between gap-3 rounded-md border border-amber-300 bg-amber-50 px-4 py-2.5 text-sm text-amber-900 sm:flex-nowrap">
      <div className="flex items-start gap-2 min-w-0">
        <Clock className="mt-0.5 h-4 w-4 shrink-0" aria-hidden />
        <div className="min-w-0">
          <p className="font-medium leading-tight">
            You appear to be in{' '}
            <span className="font-semibold">{formatTimezoneLabel(detected)}</span>.
          </p>
          <p className="text-xs leading-snug text-amber-900/80">
            Your CRM is set to <span className="font-medium">{formatTimezoneLabel(stored)}</span>.
            Reminders and the daily digest follow the CRM setting.
          </p>
        </div>
      </div>
      <div className="flex items-center gap-2 shrink-0">
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="border-amber-300 bg-white hover:bg-amber-100"
          onClick={() => mutation.mutate(detected)}
          disabled={mutation.isPending}
        >
          Update to {detected.split('/').pop()?.replace(/_/g, ' ')}
        </Button>
        <button
          type="button"
          onClick={dismiss}
          aria-label="Dismiss timezone reminder"
          className="rounded-full p-1 text-amber-700 hover:bg-amber-100"
        >
          <X className="h-3.5 w-3.5" />
        </button>
      </div>
    </div>
  );
}
