'use client';
import { FunctionComponent, useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useSnackbar } from 'notistack';
import { Box, Divider, MenuItem, Skeleton, Stack, Typography } from '@mui/material';
import {
  AppButton,
  AppIcon,
  ConfirmDialog,
  ErrorState,
  FormDialogShell,
  PhoneNumberField,
  ProfileSummary,
  RhfControlGroup,
  RhfTextField,
} from '@/components';
import LocaleSwitcher from '@/components/common/LocaleSwitcher';
import { ThemeModeSetting } from '@/components/settings';
import { isIranianMobile } from '@/components/PhoneNumberField';
import { ROUTES } from '@/constants';
import { digitsOnly } from '@/utils';
import { ActorSwitcher } from '@/layout';
import { useCustomerProfile, useUpsertCustomerProfile } from '@/services/profiles';
import { useMe, useLogout } from '@/services/auth';
import type { CustomerProfile } from '@/services/profiles/types';

/** Customer profile — the account hub: identity header, grouped rows, emergency-contact status card. */
export default function CustomerProfilePage() {
  const t = useTranslations('profile');
  const tc = useTranslations('common');
  const { data: profile, isLoading, isError, refetch } = useCustomerProfile();
  const { data: me, isLoading: meLoading } = useMe();

  if (isLoading || meLoading) return <ProfileSkeleton />;
  // The form must never render on a failed fetch — it would otherwise show blank/undefined fields
  // whose save could overwrite server truth.
  if (isError) return <ErrorState message={t('load_error')} retryLabel={tc('retry')} onRetry={() => refetch()} />;

  return (
    <AccountHub
      initial={profile ?? null}
      nameFallback={{ firstName: me?.firstName ?? null, lastName: me?.lastName ?? null }}
      phone={me?.phone}
    />
  );
}

interface AccountFormValues {
  firstName: string;
  lastName: string;
  language: string;
  emergencyName: string;
  emergencyPhone: string;
}

const AccountHub: FunctionComponent<{
  initial: CustomerProfile | null;
  nameFallback: { firstName: string | null; lastName: string | null };
  phone?: string;
}> = ({ initial, nameFallback, phone }) => {
  const t = useTranslations('profile');
  const tc = useTranslations('common');
  const locale = useLocale();
  const router = useRouter();
  const { enqueueSnackbar } = useSnackbar();
  const upsert = useUpsertCustomerProfile();
  const logout = useLogout();

  const [personalSheetOpen, setPersonalSheetOpen] = useState(false);
  const [languageSheetOpen, setLanguageSheetOpen] = useState(false);
  const [emergencySheetOpen, setEmergencySheetOpen] = useState(false);
  const [signOutOpen, setSignOutOpen] = useState(false);

  // ONE form behind all three sheets. Each sheet edits its own slice, but every save writes the whole
  // profile (the wire upsert has no PATCH semantics), so the untouched fields have to come from
  // somewhere — a single form is that somewhere, and `dirtyFields` then answers per-sheet "is there
  // unsaved work here?" without a hand-written comparison per section.
  const form = useForm<AccountFormValues>({
    mode: 'onTouched',
    defaultValues: {
      firstName: initial?.firstName ?? nameFallback.firstName ?? '',
      lastName: initial?.lastName ?? nameFallback.lastName ?? '',
      language: initial?.preferredLanguage ?? 'fa',
      emergencyName: initial?.defaultEmergencyContactName ?? '',
      emergencyPhone: digitsOnly(initial?.defaultEmergencyContactPhone ?? ''),
    },
  });
  const { control, formState, getValues, reset, trigger } = form;
  const { dirtyFields } = formState;
  const watched = useWatch({ control });

  const displayName = [watched.firstName, watched.lastName].filter(Boolean).join(' ').trim() || phone || '';
  const emergencyComplete = Boolean(watched.emergencyName?.trim() && watched.emergencyPhone);

  const save = (onDone: () => void) => {
    const values = getValues();
    upsert.mutate(
      {
        defaultEmergencyContactName: values.emergencyName.trim(),
        defaultEmergencyContactPhone: values.emergencyPhone,
        firstName: values.firstName.trim() || null,
        lastName: values.lastName.trim() || null,
        preferredLanguage: values.language,
      },
      {
        onSuccess: () => {
          enqueueSnackbar(t('saved'), { variant: 'success' });
          // Re-baseline so the saved slice stops counting as unsaved work in its sheet's discard guard.
          reset(getValues());
          onDone();
        },
      },
    );
  };

  const savePersonal = () => save(() => setPersonalSheetOpen(false));
  const saveLanguage = () => save(() => setLanguageSheetOpen(false));
  const saveEmergency = async () => {
    if (!(await trigger(['emergencyName', 'emergencyPhone']))) return;
    save(() => setEmergencySheetOpen(false));
  };

  const personalDirty = Boolean(dirtyFields.firstName || dirtyFields.lastName);
  const languageDirty = Boolean(dirtyFields.language);
  const emergencyDirty = Boolean(dirtyFields.emergencyName || dirtyFields.emergencyPhone);

  const goTo = (path: string) => router.push(`/${locale}${path}`);

  // Shared discard-confirm strings for every FormDialogShell instance below.
  const closeLabel = tc('close');
  const discardTitle = tc('discard_title');
  const discardBody = tc('discard_body');
  const discardConfirmLabel = tc('discard_confirm');
  const cancelLabel = tc('cancel');

  return (
    <FormProvider {...form}>
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: 520 }}>
      <ProfileSummary displayName={displayName} phone={phone} initialsFallback={displayName || undefined} />

      <Stack sx={{ gap: 1 }}>
        <AccountRow icon="account" label={t('row_personal')} onClick={() => setPersonalSheetOpen(true)} />
        <EmergencyContactCard
          complete={emergencyComplete}
          name={watched.emergencyName ?? ''}
          phone={watched.emergencyPhone ?? ''}
          onEdit={() => setEmergencySheetOpen(true)}
        />
        <AccountRow icon="location" label={t('row_addresses')} onClick={() => goTo(ROUTES.ADDRESSES)} />
        <AccountRow icon="language" label={t('row_language')} onClick={() => setLanguageSheetOpen(true)} />
        {/* The app's appearance control lives here (and in each other actor's settings hub) — it
            used to occupy a permanent slot in every top bar for a preference set once. */}
        <ThemeModeSetting />
        <AccountRow icon="notifications" label={t('row_notifications')} onClick={() => goTo(ROUTES.NOTIFICATIONS)} />
        <AccountRow icon="support" label={t('row_support')} onClick={() => goTo(ROUTES.SUPPORT_TICKETS)} />
      </Stack>

      {/* Renders nothing for a single-role session — see ActorSwitcher's own doc. */}
      <ActorSwitcher target="nurse" />

      <Stack sx={{ gap: 1 }}>
        <Divider sx={{ my: 0.5 }} />
        <AccountRow icon="logout" label={t('sign_out')} onClick={() => setSignOutOpen(true)} tone="error" />
      </Stack>

      {/* اطلاعات شخصی */}
      <FormDialogShell
        open={personalSheetOpen}
        title={t('row_personal')}
        dirty={personalDirty}
        onClose={() => setPersonalSheetOpen(false)}
        closeLabel={closeLabel}
        discardTitle={discardTitle}
        discardBody={discardBody}
        discardConfirmLabel={discardConfirmLabel}
        discardCancelLabel={cancelLabel}
      >
        <Stack sx={{ gap: 2.5 }}>
          <RhfTextField<AccountFormValues> name="firstName" label={t('first_name')} fullWidth />
          <RhfTextField<AccountFormValues> name="lastName" label={t('last_name')} fullWidth />
          <SheetActions onCancel={() => setPersonalSheetOpen(false)} onSave={savePersonal} saving={upsert.isPending} saveLabel={tc('save')} cancelLabel={cancelLabel} />
        </Stack>
      </FormDialogShell>

      {/* زبان — the row owns the server-stored preference; the actual UI locale switch is phase 2's LocaleSwitcher, reused verbatim. */}
      <FormDialogShell
        open={languageSheetOpen}
        title={t('row_language')}
        dirty={languageDirty}
        onClose={() => setLanguageSheetOpen(false)}
        closeLabel={closeLabel}
        discardTitle={discardTitle}
        discardBody={discardBody}
        discardConfirmLabel={discardConfirmLabel}
        discardCancelLabel={cancelLabel}
      >
        <Stack sx={{ gap: 2.5 }}>
          <Stack sx={{ gap: 1 }}>
            <Typography variant="subtitle2" sx={{ fontWeight: 700 }}>
              {t('app_language')}
            </Typography>
            <Typography variant="body2" sx={{ color: 'text.secondary' }}>
              {t('app_language_hint')}
            </Typography>
            <LocaleSwitcher />
          </Stack>
          <Divider />
          <RhfTextField<AccountFormValues> name="language" select label={t('language')} helperText={t('language_hint')}>
            <MenuItem value="fa">{t('language_fa')}</MenuItem>
            <MenuItem value="en">{t('language_en')}</MenuItem>
          </RhfTextField>
          <SheetActions onCancel={() => setLanguageSheetOpen(false)} onSave={saveLanguage} saving={upsert.isPending} saveLabel={tc('save')} cancelLabel={cancelLabel} />
        </Stack>
      </FormDialogShell>

      {/* مخاطب اضطراری */}
      <FormDialogShell
        open={emergencySheetOpen}
        title={t('emergency_section')}
        dirty={emergencyDirty}
        onClose={() => setEmergencySheetOpen(false)}
        closeLabel={closeLabel}
        discardTitle={discardTitle}
        discardBody={discardBody}
        discardConfirmLabel={discardConfirmLabel}
        discardCancelLabel={cancelLabel}
      >
        <Stack sx={{ gap: 2.5 }}>
          <Typography variant="body2" sx={{ color: 'text.secondary' }}>
            {t('emergency_hint')}
          </Typography>
          <RhfTextField<AccountFormValues>
            name="emergencyName"
            label={t('emergency_name')}
            rules={{ validate: (value) => String(value ?? '').trim().length > 0 }}
            fullWidth
          />
          <RhfControlGroup<AccountFormValues>
            name="emergencyPhone"
            rules={{ validate: (value) => isIranianMobile(String(value ?? '')) }}
          >
            {({ field, hasError }) => (
              <PhoneNumberField
                label={t('emergency_phone')}
                value={(field.value as string) ?? ''}
                onChange={field.onChange}
                error={hasError}
                helperText={hasError ? t('emergency_phone_invalid') : undefined}
                fullWidth
              />
            )}
          </RhfControlGroup>
          <SheetActions onCancel={() => setEmergencySheetOpen(false)} onSave={saveEmergency} saving={upsert.isPending} saveLabel={tc('save')} cancelLabel={cancelLabel} />
        </Stack>
      </FormDialogShell>

      <ConfirmDialog
        open={signOutOpen}
        title={t('sign_out_confirm_title')}
        body={t('sign_out_confirm_body')}
        confirmLabel={t('sign_out')}
        cancelLabel={cancelLabel}
        confirmColor="error"
        onClose={() => setSignOutOpen(false)}
        onConfirm={() => {
          setSignOutOpen(false);
          logout.mutate();
        }}
      />
    </Box>
    </FormProvider>
  );
};

const AccountRow: FunctionComponent<{
  icon: string;
  label: string;
  onClick: () => void;
  tone?: 'default' | 'error';
}> = ({ icon, label, onClick, tone = 'default' }) => (
  <Box
    component="button"
    type="button"
    onClick={onClick}
    sx={{ background: 'none', border: 'none', p: 0, width: '100%', textAlign: 'start', font: 'inherit', cursor: 'pointer' }}
  >
    <Stack
      direction="row"
      sx={{
        alignItems: 'center',
        gap: 1.5,
        p: 1.5,
        borderRadius: 'var(--bal-radius-md)',
        color: tone === 'error' ? 'var(--bal-error)' : 'text.primary',
        '&:hover': { bgcolor: 'action.hover' },
      }}
    >
      <AppIcon icon={icon} size={22} color={tone === 'error' ? 'var(--bal-error)' : 'var(--bal-primary)'} />
      <Typography variant="body1" sx={{ flexGrow: 1, fontWeight: 500 }}>
        {label}
      </Typography>
      {tone !== 'error' ? <AppIcon icon="forward" size={18} color="var(--bal-text-secondary)" /> : null}
    </Stack>
  </Box>
);

const EmergencyContactCard: FunctionComponent<{
  complete: boolean;
  name: string;
  phone: string;
  onEdit: () => void;
}> = ({ complete, name, phone, onEdit }) => {
  const t = useTranslations('profile');
  return (
    <Box sx={{ p: 1.5, borderRadius: 'var(--bal-radius-md)', border: '1px solid', borderColor: 'divider' }}>
      <Stack direction="row" sx={{ alignItems: 'center', gap: 1.5 }}>
        <AppIcon icon={complete ? 'verified' : 'emergency'} size={22} color={complete ? 'var(--bal-success)' : 'var(--bal-warning)'} />
        <Stack sx={{ flexGrow: 1, gap: 0.25, minWidth: 0 }}>
          <Typography variant="body1" sx={{ fontWeight: 500 }}>
            {t('emergency_section')}
          </Typography>
          {complete ? (
            <Stack direction="row" sx={{ alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
              <Typography variant="body2" sx={{ color: 'text.secondary' }}>
                {name}
              </Typography>
              <Typography
                component="a"
                href={`tel:${phone}`}
                dir="ltr"
                variant="body2"
                sx={{ color: 'var(--bal-primary)', textDecoration: 'none' }}
              >
                {phone}
              </Typography>
            </Stack>
          ) : (
            <Typography variant="body2" sx={{ color: 'text.secondary' }}>
              {t('emergency_hint')}
            </Typography>
          )}
        </Stack>
        <AppButton variant="text" color="primary" onClick={onEdit}>
          {t('edit')}
        </AppButton>
      </Stack>
    </Box>
  );
};

const SheetActions: FunctionComponent<{
  onCancel: () => void;
  onSave: () => void;
  saving: boolean;
  saveLabel: string;
  cancelLabel: string;
}> = ({ onCancel, onSave, saving, saveLabel, cancelLabel }) => {
  const tc = useTranslations('common');
  return (
    <Stack direction="row" sx={{ gap: 1, justifyContent: 'flex-end' }}>
      <AppButton variant="text" onClick={onCancel} disabled={saving}>
        {cancelLabel}
      </AppButton>
      <AppButton color="primary" variant="contained" onClick={onSave} disabled={saving}>
        {saving ? tc('saving') : saveLabel}
      </AppButton>
    </Stack>
  );
};

function ProfileSkeleton() {
  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: 520 }}>
      <Stack sx={{ alignItems: 'center', gap: 1 }}>
        <Skeleton variant="circular" width={56} height={56} />
        <Skeleton variant="text" width={140} />
        <Skeleton variant="text" width={100} />
      </Stack>
      <Stack sx={{ gap: 1 }}>
        {[0, 1, 2, 3, 4, 5].map((key) => (
          <Skeleton key={key} variant="rounded" height={56} />
        ))}
      </Stack>
    </Box>
  );
}
