'use client';
import { FunctionComponent, useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { useSnackbar } from 'notistack';
import { Box, Divider, MenuItem, Skeleton, Stack, TextField, Typography } from '@mui/material';
import {
  AppButton,
  AppIcon,
  ConfirmDialog,
  ErrorState,
  FormDialogShell,
  PhoneNumberField,
  ProfileSummary,
} 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}
    />
  );
}

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 initialFirstName = initial?.firstName ?? nameFallback.firstName ?? '';
  const initialLastName = initial?.lastName ?? nameFallback.lastName ?? '';
  const initialLanguage = initial?.preferredLanguage ?? 'fa';
  const initialEmergencyName = initial?.defaultEmergencyContactName ?? '';
  const initialEmergencyPhone = digitsOnly(initial?.defaultEmergencyContactPhone ?? '');

  const [firstName, setFirstName] = useState(initialFirstName);
  const [lastName, setLastName] = useState(initialLastName);
  const [language, setLanguage] = useState(initialLanguage);
  const [emergencyName, setEmergencyName] = useState(initialEmergencyName);
  const [emergencyPhone, setEmergencyPhone] = useState(initialEmergencyPhone);

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

  const [nameError, setNameError] = useState(false);
  const [phoneError, setPhoneError] = useState(false);

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

  // Every sheet saves the FULL profile object (the wire upsert has no PATCH semantics) — `patch`
  // carries just the fields that sheet owns, the rest come from the shared draft state so editing
  // one section never blanks another (the bug the old flat form was one refactor away from).
  const save = (
    patch: Partial<Record<'firstName' | 'lastName' | 'preferredLanguage', string | null>>,
    onDone: () => void,
  ) => {
    upsert.mutate(
      {
        defaultEmergencyContactName: emergencyName.trim(),
        defaultEmergencyContactPhone: emergencyPhone,
        firstName: firstName.trim() || null,
        lastName: lastName.trim() || null,
        preferredLanguage: language,
        ...patch,
      },
      {
        onSuccess: () => {
          enqueueSnackbar(t('saved'), { variant: 'success' });
          onDone();
        },
      },
    );
  };

  const savePersonal = () =>
    save({ firstName: firstName.trim() || null, lastName: lastName.trim() || null }, () => setPersonalSheetOpen(false));
  const saveLanguage = () => save({ preferredLanguage: language }, () => setLanguageSheetOpen(false));
  const saveEmergency = () => {
    const nameInvalid = emergencyName.trim().length === 0;
    const phoneInvalid = !isIranianMobile(emergencyPhone);
    setNameError(nameInvalid);
    setPhoneError(phoneInvalid);
    if (nameInvalid || phoneInvalid) return;
    save({}, () => setEmergencySheetOpen(false));
  };

  const personalDirty = firstName !== initialFirstName || lastName !== initialLastName;
  const languageDirty = language !== initialLanguage;
  const emergencyDirty = emergencyName !== initialEmergencyName || emergencyPhone !== initialEmergencyPhone;

  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 (
    <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={emergencyName}
          phone={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 }}>
          <TextField label={t('first_name')} value={firstName} onChange={(e) => setFirstName(e.target.value)} fullWidth />
          <TextField label={t('last_name')} value={lastName} onChange={(e) => setLastName(e.target.value)} 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 />
          <TextField
            select
            label={t('language')}
            value={language}
            onChange={(e) => setLanguage(e.target.value)}
            helperText={t('language_hint')}
          >
            <MenuItem value="fa">{t('language_fa')}</MenuItem>
            <MenuItem value="en">{t('language_en')}</MenuItem>
          </TextField>
          <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>
          <TextField
            label={t('emergency_name')}
            value={emergencyName}
            onChange={(e) => {
              setEmergencyName(e.target.value);
              if (nameError) setNameError(false);
            }}
            error={nameError}
            fullWidth
          />
          <PhoneNumberField
            label={t('emergency_phone')}
            value={emergencyPhone}
            onChange={(v) => {
              setEmergencyPhone(v);
              if (phoneError) setPhoneError(false);
            }}
            error={phoneError}
            helperText={phoneError ? t('emergency_phone_invalid') : undefined}
            fullWidth
          />
          <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>
  );
};

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>
  );
}
