'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';
import { useTranslations } from 'next-intl';
import { Link, useRouter } from '@/i18n/navigation';
import { useSearchParams } from 'next/navigation';
import { ChevronDown, Lock } from 'lucide-react';
import { useAuth } from '@/lib/hooks/useAuth';
import { authApi } from '@/lib/api/auth';
import { accountApi } from '@/lib/api/account';
import { Button } from '@/components/ui/shared/Button';
import { Input } from '@/components/ui/shared/Input';
import { Toast } from '@/components/ui/shared/Toast';
import { Checkbox } from '@/components/ui/shared/Checkbox';
import { DialogCloseButton } from '@/components/ui/shared/DialogCloseButton';
import { getUserFacingError } from '@/components/shared/formatApiError';
import { OwnerWorkingHoursDialog } from '@/components/ui/settings/OwnerWorkingHoursDialog';

type PasswordForm = {
  currentPassword: string;
  newPassword: string;
  confirmPassword: string;
};

export function AccountSettingsPage() {
  const t = useTranslations('settings');
  const tErrors = useTranslations('errors');
  const tAuth = useTranslations('auth');
  const tCommon = useTranslations('common');
  const tValidation = useTranslations('validation');
  const { user, currentOrganization, isAuthReady, refreshSession } = useAuth();
  const router = useRouter();
  const searchParams = useSearchParams();
  const isResetFlow = searchParams.get('reset') === '1';

  const isOwner = Boolean(currentOrganization?.isOwner);
  const orgType = currentOrganization?.type;
  const showClinicParticipation = isOwner && orgType === 'CLINIC';
  const showLabParticipation = isOwner && orgType === 'LAB';

  const [error, setError] = useState<string | null>(null);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [passwordExpanded, setPasswordExpanded] = useState(isResetFlow);

  const [participationLoading, setParticipationLoading] = useState(false);
  const [participatesInTreatments, setParticipatesInTreatments] = useState(false);
  const [participatesInTasks, setParticipatesInTasks] = useState(false);
  const [workingHoursOpen, setWorkingHoursOpen] = useState(false);
  const [revokeConfirmOpen, setRevokeConfirmOpen] = useState(false);
  const [pendingRevokeType, setPendingRevokeType] = useState<'CLINIC' | 'LAB' | null>(null);

  const passwordSchema = useMemo(
    () =>
      z
        .object({
          currentPassword: z.string(),
          newPassword: z
            .string()
            .min(8, tValidation('passwordMinLength'))
            .regex(/[A-Z]/, tValidation('passwordUppercase'))
            .regex(/[0-9]/, tValidation('passwordNumber')),
          confirmPassword: z.string(),
        })
        .refine((data) => data.newPassword === data.confirmPassword, {
          message: tValidation('passwordsDoNotMatch'),
          path: ['confirmPassword'],
        })
        .superRefine((data, ctx) => {
          if (!isResetFlow && !data.currentPassword.trim()) {
            ctx.addIssue({
              code: z.ZodIssueCode.custom,
              message: tValidation('passwordRequired'),
              path: ['currentPassword'],
            });
          }
        }),
    [isResetFlow, tValidation],
  );

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm<PasswordForm>({
    resolver: zodResolver(passwordSchema),
    defaultValues: {
      currentPassword: '',
      newPassword: '',
      confirmPassword: '',
    },
  });

  const loadParticipation = useCallback(async () => {
    if (!isOwner) return;
    try {
      const res = await accountApi.getParticipation();
      setParticipatesInTreatments(res.data.participatesInTreatments);
      setParticipatesInTasks(res.data.participatesInTasks);
    } catch {
      /* non-owners or missing org context */
    }
  }, [isOwner]);

  useEffect(() => {
    if (isAuthReady && !user) {
      router.replace('/login');
    }
  }, [isAuthReady, user, router]);

  useEffect(() => {
    if (isResetFlow) {
      setPasswordExpanded(true);
    }
  }, [isResetFlow]);

  useEffect(() => {
    void loadParticipation();
  }, [loadParticipation, currentOrganization?.id]);

  const syncSessionAfterParticipationChange = useCallback(async () => {
    await refreshSession();
  }, [refreshSession]);

  const enableClinicParticipation = useCallback(
    async (options: {
      skipHours: boolean;
      hoursPayload?: {
        autoRepeatWeekly: boolean;
        blocks: { dayOfWeek: number; startMinute: number; endMinute: number; sortOrder?: number }[];
      };
    }) => {
      await accountApi.updateParticipation(true);
      if (!options.skipHours && options.hoursPayload) {
        await accountApi.upsertMyWorkingHours(options.hoursPayload);
      }
      setParticipatesInTreatments(true);
      await syncSessionAfterParticipationChange();
      setSuccessMessage(t('participateEnabledTreatments'));
    },
    [syncSessionAfterParticipationChange, t],
  );

  const enableLabParticipation = async () => {
    setParticipationLoading(true);
    setError(null);
    try {
      await accountApi.updateParticipation(true);
      setParticipatesInTasks(true);
      await syncSessionAfterParticipationChange();
      setSuccessMessage(t('participateEnabledTasks'));
    } catch (err: unknown) {
      setError(getUserFacingError(err, tErrors, t('participateUpdateFailed')));
      setParticipatesInTasks(false);
    } finally {
      setParticipationLoading(false);
    }
  };

  const confirmRevokeParticipation = async () => {
    if (!pendingRevokeType) return;
    setParticipationLoading(true);
    setError(null);
    try {
      await accountApi.updateParticipation(false);
      if (pendingRevokeType === 'CLINIC') {
        setParticipatesInTreatments(false);
      } else {
        setParticipatesInTasks(false);
      }
      await syncSessionAfterParticipationChange();
      setSuccessMessage(
        pendingRevokeType === 'CLINIC'
          ? t('participateDisabledTreatments')
          : t('participateDisabledTasks'),
      );
      setRevokeConfirmOpen(false);
      setPendingRevokeType(null);
    } catch (err: unknown) {
      setError(getUserFacingError(err, tErrors, t('participateUpdateFailed')));
    } finally {
      setParticipationLoading(false);
    }
  };

  const handleClinicParticipationChange = (checked: boolean) => {
    setError(null);
    if (checked) {
      setWorkingHoursOpen(true);
      return;
    }
    setPendingRevokeType('CLINIC');
    setRevokeConfirmOpen(true);
  };

  const handleWorkingHoursClose = useCallback(() => {
    setWorkingHoursOpen(false);
  }, []);

  const handleWorkingHoursComplete = useCallback(
    async (options: {
      skipHours: boolean;
      hoursPayload?: {
        autoRepeatWeekly: boolean;
        blocks: { dayOfWeek: number; startMinute: number; endMinute: number; sortOrder?: number }[];
      };
    }) => {
      setParticipationLoading(true);
      setError(null);
      try {
        await enableClinicParticipation(options);
      } catch (err: unknown) {
        setError(getUserFacingError(err, tErrors, t('participateUpdateFailed')));
        throw err;
      } finally {
        setParticipationLoading(false);
      }
    },
    [enableClinicParticipation, t],
  );

  const handleLabParticipationChange = (checked: boolean) => {
    setError(null);
    if (checked) {
      void enableLabParticipation();
      return;
    }
    setPendingRevokeType('LAB');
    setRevokeConfirmOpen(true);
  };

  const onSubmit = async (data: PasswordForm) => {
    try {
      setError(null);
      setSuccessMessage(null);
      setIsSubmitting(true);

      await authApi.changePassword({
        ...(isResetFlow ? {} : { currentPassword: data.currentPassword }),
        newPassword: data.newPassword,
      });

      reset();
      setSuccessMessage(t('passwordChanged'));
      router.replace('/login');
    } catch (err: unknown) {
      setError(getUserFacingError(err, tErrors, t('passwordChangeFailed')));
    } finally {
      setIsSubmitting(false);
    }
  };

  const passwordToggleLabels = {
    show: tAuth('showPassword'),
    hide: tAuth('hidePassword'),
  };

  if (!isAuthReady || !user) {
    return (
      <p className="text-text-secondary text-sm">{tCommon('loadingEllipsis')}</p>
    );
  }

  return (
    <div className="space-y-6">
      <div>
        <Link href="/today" className="text-sm text-primary hover:opacity-90">
          {tCommon('backToApp')}
        </Link>
        <h1 className="text-xl sm:text-2xl font-semibold text-text-primary mt-4">{t('accountTitle')}</h1>
        <p className="text-text-secondary text-sm mt-2">{t('accountSubtitle')}</p>
      </div>

      {(showClinicParticipation || showLabParticipation) && (
        <div className="surface-card p-4 sm:p-6 max-w-lg space-y-4">
          <div>
            <h2 className="text-lg font-medium text-text-primary">{t('participationSectionTitle')}</h2>
            <p className="text-sm text-text-secondary mt-1">{t('participationSectionSubtitle')}</p>
          </div>

          {showClinicParticipation && (
            <Checkbox
              checked={participatesInTreatments}
              onChange={handleClinicParticipationChange}
              disabled={participationLoading}
              label={t('participateInTreatments')}
            />
          )}

          {showLabParticipation && (
            <Checkbox
              checked={participatesInTasks}
              onChange={handleLabParticipationChange}
              disabled={participationLoading}
              label={t('participateInTasks')}
            />
          )}
        </div>
      )}

      <div className="surface-card max-w-lg overflow-hidden">
        <button
          type="button"
          className="w-full flex items-center justify-between gap-3 p-4 sm:p-6 text-left hover:bg-background-card/40 transition-colors"
          onClick={() => setPasswordExpanded((open) => !open)}
          aria-expanded={passwordExpanded}
        >
          <div className="flex items-center gap-3 min-w-0">
            <Lock className="h-5 w-5 icon-flat shrink-0" />
            <div>
              <p className="text-base font-medium text-text-primary">{t('changePasswordOption')}</p>
              <p className="text-sm text-text-secondary truncate">
                {user.email}
                {user.mobile ? ` · ${user.mobile}` : ''}
              </p>
            </div>
          </div>
          <ChevronDown
            className={`h-5 w-5 text-text-muted shrink-0 transition-transform ${
              passwordExpanded ? 'rotate-180' : ''
            }`}
          />
        </button>

        {passwordExpanded && (
          <div className="border-t border-border px-4 sm:px-6 pb-4 sm:pb-6 pt-4">
            <h2 className="text-lg font-medium text-text-primary mb-1">
              {isResetFlow ? t('resetPasswordTitle') : t('changePasswordTitle')}
            </h2>
            {isResetFlow && (
              <p className="text-sm text-text-secondary mb-4">{t('resetPasswordSubtitle')}</p>
            )}

            <form className="space-y-5" onSubmit={handleSubmit(onSubmit)}>
              {!isResetFlow && (
                <Input
                  label={t('currentPassword')}
                  {...register('currentPassword')}
                  type="password"
                  placeholder={tAuth('passwordPlaceholder')}
                  error={errors.currentPassword?.message}
                  icon={<Lock className="h-5 w-5 icon-flat" />}
                  passwordToggleLabels={passwordToggleLabels}
                />
              )}

              <Input
                label={t('newPassword')}
                {...register('newPassword')}
                type="password"
                placeholder={tAuth('passwordPlaceholder')}
                error={errors.newPassword?.message}
                icon={<Lock className="h-5 w-5 icon-flat" />}
                passwordToggleLabels={passwordToggleLabels}
              />

              <Input
                label={t('confirmNewPassword')}
                {...register('confirmPassword')}
                type="password"
                placeholder={tAuth('passwordPlaceholder')}
                error={errors.confirmPassword?.message}
                icon={<Lock className="h-5 w-5 icon-flat" />}
                passwordToggleLabels={passwordToggleLabels}
              />

              {error && (
                <div className="p-3 bg-red-950/30 border border-red-600/40 rounded-[var(--radius-md)]">
                  <p className="text-sm text-red-600">{error}</p>
                </div>
              )}

              <Button type="submit" variant="primary" isLoading={isSubmitting}>
                {isResetFlow ? t('setNewPassword') : t('updatePassword')}
              </Button>
            </form>
          </div>
        )}
      </div>

      {error && !passwordExpanded && (
        <div className="max-w-lg p-3 bg-red-950/30 border border-red-600/40 rounded-[var(--radius-md)]">
          <p className="text-sm text-red-600">{error}</p>
        </div>
      )}

      <OwnerWorkingHoursDialog
        open={workingHoursOpen}
        onClose={handleWorkingHoursClose}
        onComplete={handleWorkingHoursComplete}
      />

      {revokeConfirmOpen && (
        <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-0 sm:p-4 bg-black/55">
          <div
            className="surface-card w-full sm:max-w-md max-h-[90dvh] overflow-y-auto p-4 sm:p-5 space-y-4 shadow-xl rounded-t-[var(--radius-lg)] sm:rounded-[var(--radius-lg)]"
            role="dialog"
            aria-modal="true"
            aria-labelledby="revoke-participation-title"
          >
            <div className="flex items-start justify-between gap-2">
              <h2 id="revoke-participation-title" className="text-lg font-semibold text-text-primary pr-2">
                {t('participateConfirmRevokeTitle')}
              </h2>
              <DialogCloseButton
                onClick={() => {
                  if (participationLoading) return;
                  setRevokeConfirmOpen(false);
                  setPendingRevokeType(null);
                }}
              />
            </div>
            <p className="text-sm text-text-secondary">
              {pendingRevokeType === 'CLINIC'
                ? t('participateConfirmRevokeBodyTreatments')
                : t('participateConfirmRevokeBodyTasks')}
            </p>
            <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-1">
              <Button
                type="button"
                variant="outline"
                disabled={participationLoading}
                onClick={() => {
                  setRevokeConfirmOpen(false);
                  setPendingRevokeType(null);
                }}
              >
                {tCommon('cancel')}
              </Button>
              <Button
                type="button"
                variant="primary"
                isLoading={participationLoading}
                onClick={() => confirmRevokeParticipation()}
              >
                {t('participateConfirmRevokeConfirm')}
              </Button>
            </div>
          </div>
        </div>
      )}

      {successMessage && (
        <Toast variant="success">{successMessage}</Toast>
      )}
    </div>
  );
}
