import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';

export type Language = 'ru' | 'en';

const STORAGE_KEY = 'family-wishlist-language';
const FALLBACK_LANGUAGE: Language = 'ru';

const translations = {
  ru: {
    'app.name': 'Family Wishlist',
    'language.ru': 'Русский',
    'language.en': 'English',
    'language.switch': 'Язык',
    'common.loading': 'Загрузка...',
    'common.cancel': 'Отмена',
    'common.save': 'Сохранить',
    'common.saveChanges': 'Сохранить изменения',
    'common.backHome': 'На главную',
    'common.days.one': '{count} день',
    'common.days.few': '{count} дня',
    'common.days.many': '{count} дней',
    'footer.frontend': 'frontend v{version}',
    'footer.backend': 'backend v{version}',
    'header.active': 'Активные',
    'header.fulfilled': 'Исполненные',
    'header.archive': 'Архив',
    'header.trash': 'Корзина',
    'header.signedInAs': 'вошли как {name}',
    'header.profileSettings': 'Настройки профиля',
    'header.profile': 'Профиль',
    'header.friendWishes': 'Желания {name}',
    'header.logout': 'Выйти',
    'login.title': 'С возвращением',
    'login.description': 'Войдите, чтобы управлять списком желаний. Доступы задаются на сервере.',
    'login.username': 'Логин',
    'login.password': 'Пароль',
    'login.submit': 'Войти',
    'login.failed': 'Не удалось войти',
    'dashboard.title': 'Ваш список желаний',
    'dashboard.description': 'Добавляйте вещи, о которых мечтаете. Публичная страница доступна по адресу ',
    'dashboard.addWish': 'Добавить желание',
    'dashboard.emptyTitle': 'Желаний пока нет',
    'dashboard.emptyText': 'Начните с того, что вам действительно хочется получить.',
    'dashboard.addFirstWish': 'Добавить первое желание',
    'archive.title': 'Архив',
    'archive.description': 'Отложенные желания. Их видите только вы, и их можно вернуть в активный список.',
    'archive.emptyTitle': 'Архив пуст',
    'archive.emptyText': 'Архивированные желания появятся здесь.',
    'completed.title': 'Исполненные',
    'completed.description': 'Желания, которые уже исполнились. Из любого можно создать новое.',
    'completed.emptyTitle': 'Исполненных желаний пока нет',
    'completed.emptyText': 'Когда желание исполнится, отметьте его, и оно появится здесь.',
    'trash.title': 'Корзина',
    'trash.description': 'Удалённые желания хранятся {days}, затем удаляются навсегда.',
    'trash.emptyTitle': 'Корзина пуста',
    'trash.emptyText': 'Удалённые желания будут появляться здесь на {days}.',
    'trash.autoRemove': 'Автоудаление через {days}',
    'profile.title': 'Профиль',
    'profile.publicPage': 'Публичная страница доступна по адресу ',
    'profile.slug': 'Slug (публичный URL)',
    'profile.displayName': 'Отображаемое имя',
    'profile.bio': 'О себе',
    'profile.avatarUrl': 'Ссылка на аватар',
    'profile.avatar': 'Аватар',
    'profile.avatarHint': 'Можно вставить ссылку или загрузить фото до 2 MB.',
    'profile.uploadAvatar': 'Загрузить фото',
    'profile.avatarTooLarge': 'Фото должно быть не больше 2 MB',
    'profile.avatarUnsupported': 'Поддерживаются JPEG, PNG, WebP и GIF',
    'profile.saved': 'Профиль сохранён',
    'profile.avatarUploaded': 'Аватар обновлён',
    'profile.saveFailed': 'Не удалось сохранить',
    'public.loadingWishes': 'Загрузка желаний...',
    'public.notFoundTitle': 'Профиль не найден',
    'public.notFoundText': 'Проверьте ссылку и попробуйте ещё раз. Slug чувствителен к регистру.',
    'public.backToMine': 'Вернуться к моим желаниям',
    'public.wishlistTitle': 'Список желаний {name}',
    'public.emptyTitle': 'Желаний пока нет',
    'public.emptyText': 'Загляните позже!',
    'notFound.text': 'Не удалось найти эту страницу.',
    'protected.loading': 'Загрузка...',
    'wish.action.edit': 'Редактировать',
    'wish.action.complete': 'Отметить исполненным',
    'wish.action.archive': 'В архив',
    'wish.action.delete': 'Удалить',
    'wish.action.restore': 'Восстановить',
    'wish.action.duplicate': 'Создать копию как новое',
    'wish.actions': 'Действия',
    'wish.openLink': 'открыть ссылку',
    'wish.badge.new': 'новое',
    'wish.badge.fulfilled': 'исполнено',
    'wish.badge.archived': 'архив',
    'wish.badge.trash': 'корзина',
    'wishForm.addTitle': 'Добавить желание',
    'wishForm.editTitle': 'Редактировать желание',
    'wishForm.addDescription': 'Расскажите, чего хочется. По ссылке мы попробуем подтянуть картинку.',
    'wishForm.editDescription': 'Обновите детали желания.',
    'wishForm.title': 'Название',
    'wishForm.titlePlaceholder': 'Гейзерная кофеварка, размер 3',
    'wishForm.price': 'Цена (необязательно)',
    'wishForm.pricePlaceholder': 'например, 2490',
    'wishForm.currency': 'Валюта',
    'wishForm.link': 'Ссылка (необязательно)',
    'wishForm.linkHint': 'После сохранения попробуем подтянуть превью-картинку по ссылке.',
    'wishForm.comment': 'Комментарий (необязательно)',
    'wishForm.commentPlaceholder': 'Размер / цвет / заметки...',
    'wishForm.image': 'Картинка',
    'wishForm.uploadCustom': 'Загрузить свою',
    'wishForm.refreshFromLink': 'Обновить по ссылке',
    'wishForm.resetImage': 'Сбросить на стандартную',
    'wishForm.addSubmit': 'Добавить желание',
    'toast.genericError': 'Что-то пошло не так',
    'toast.wishAdded': 'Желание добавлено',
    'toast.saved': 'Сохранено',
    'toast.archived': 'Перемещено в архив',
    'toast.fulfilled': 'Отмечено исполненным',
    'toast.deleted': 'Перемещено в корзину (30 дней на восстановление)',
    'toast.restored': 'Восстановлено',
    'toast.duplicated': 'Новое желание создано из исполненного',
    'toast.imageUpdated': 'Картинка обновлена',
    'toast.imageRefreshed': 'Картинка обновлена по ссылке',
    'toast.imageFetchFailed': 'Не удалось получить картинку по ссылке',
    'toast.imageReset': 'Картинка сброшена на стандартную',
    'validation.invalid': 'Проверьте значение поля',
    'validation.slug': 'Slug: 3-32 символа, строчные латинские буквы, цифры и дефисы',
  },
  en: {
    'app.name': 'Family Wishlist',
    'language.ru': 'Русский',
    'language.en': 'English',
    'language.switch': 'Language',
    'common.loading': 'Loading...',
    'common.cancel': 'Cancel',
    'common.save': 'Save',
    'common.saveChanges': 'Save changes',
    'common.backHome': 'Back to home',
    'common.days.one': '{count} day',
    'common.days.few': '{count} days',
    'common.days.many': '{count} days',
    'footer.frontend': 'frontend v{version}',
    'footer.backend': 'backend v{version}',
    'header.active': 'Active',
    'header.fulfilled': 'Fulfilled',
    'header.archive': 'Archive',
    'header.trash': 'Trash',
    'header.signedInAs': 'signed in as {name}',
    'header.profileSettings': 'Profile settings',
    'header.profile': 'Profile',
    'header.friendWishes': "{name}'s wishes",
    'header.logout': 'Log out',
    'login.title': 'Welcome back',
    'login.description': 'Sign in to manage your wishlist. Credentials are set up via the server environment.',
    'login.username': 'Username',
    'login.password': 'Password',
    'login.submit': 'Sign in',
    'login.failed': 'Login failed',
    'dashboard.title': 'Your wishlist',
    'dashboard.description': 'Add things you dream of. Share your public page at ',
    'dashboard.addWish': 'Add wish',
    'dashboard.emptyTitle': 'No wishes yet',
    'dashboard.emptyText': "Start by adding something you'd love to receive.",
    'dashboard.addFirstWish': 'Add your first wish',
    'archive.title': 'Archive',
    'archive.description': 'Wishes you put aside. Only you see this. Restore them to your active list any time.',
    'archive.emptyTitle': 'Archive is empty',
    'archive.emptyText': 'Archived wishes will show up here.',
    'completed.title': 'Fulfilled',
    'completed.description': "Wishes you've received. You can create a new wish based on any of them.",
    'completed.emptyTitle': 'Nothing fulfilled yet',
    'completed.emptyText': 'When a wish comes true, mark it as fulfilled and it lands here.',
    'trash.title': 'Trash',
    'trash.description': 'Deleted wishes are kept for {days}, then permanently removed.',
    'trash.emptyTitle': 'Trash is empty',
    'trash.emptyText': 'Deleted wishes will appear here for {days}.',
    'trash.autoRemove': 'Auto-removes in {days}',
    'profile.title': 'Profile',
    'profile.publicPage': 'Your public page lives at ',
    'profile.slug': 'Slug (public URL)',
    'profile.displayName': 'Display name',
    'profile.bio': 'Bio',
    'profile.avatarUrl': 'Avatar URL',
    'profile.avatar': 'Avatar',
    'profile.avatarHint': 'Paste a link or upload a photo up to 2 MB.',
    'profile.uploadAvatar': 'Upload photo',
    'profile.avatarTooLarge': 'Avatar must be 2 MB or less',
    'profile.avatarUnsupported': 'JPEG, PNG, WebP and GIF are supported',
    'profile.saved': 'Profile saved',
    'profile.avatarUploaded': 'Avatar updated',
    'profile.saveFailed': 'Save failed',
    'public.loadingWishes': 'Loading wishes...',
    'public.notFoundTitle': 'Profile not found',
    'public.notFoundText': 'Check the link and try again. Slugs are case-sensitive.',
    'public.backToMine': 'Back to my wishlist',
    'public.wishlistTitle': "{name}'s wishlist",
    'public.emptyTitle': 'No wishes yet',
    'public.emptyText': 'Check back later!',
    'notFound.text': "We couldn't find that page.",
    'protected.loading': 'Loading...',
    'wish.action.edit': 'Edit',
    'wish.action.complete': 'Mark fulfilled',
    'wish.action.archive': 'Archive',
    'wish.action.delete': 'Delete',
    'wish.action.restore': 'Restore',
    'wish.action.duplicate': 'Create copy as new',
    'wish.actions': 'Actions',
    'wish.openLink': 'open link',
    'wish.badge.new': 'new',
    'wish.badge.fulfilled': 'fulfilled',
    'wish.badge.archived': 'archived',
    'wish.badge.trash': 'trash',
    'wishForm.addTitle': 'Add a wish',
    'wishForm.editTitle': 'Edit wish',
    'wishForm.addDescription': 'Tell us what you want. A link helps us grab a preview image automatically.',
    'wishForm.editDescription': 'Update the details of your wish.',
    'wishForm.title': 'Title',
    'wishForm.titlePlaceholder': 'Moka pot, size 3',
    'wishForm.price': 'Price (optional)',
    'wishForm.pricePlaceholder': 'e.g. 2490',
    'wishForm.currency': 'Currency',
    'wishForm.link': 'Link (optional)',
    'wishForm.linkHint': 'We will try to pull a preview image from the link after saving.',
    'wishForm.comment': 'Comment (optional)',
    'wishForm.commentPlaceholder': 'Size / color / notes...',
    'wishForm.image': 'Image',
    'wishForm.uploadCustom': 'Upload custom',
    'wishForm.refreshFromLink': 'Refresh from link',
    'wishForm.resetImage': 'Reset to default',
    'wishForm.addSubmit': 'Add wish',
    'toast.genericError': 'Something went wrong',
    'toast.wishAdded': 'Wish added',
    'toast.saved': 'Saved',
    'toast.archived': 'Moved to archive',
    'toast.fulfilled': 'Marked as fulfilled',
    'toast.deleted': 'Moved to trash (30 days to restore)',
    'toast.restored': 'Restored',
    'toast.duplicated': 'New wish created from the fulfilled one',
    'toast.imageUpdated': 'Image updated',
    'toast.imageRefreshed': 'Image refreshed from link',
    'toast.imageFetchFailed': 'Could not fetch image from link',
    'toast.imageReset': 'Reset to default image',
    'validation.invalid': 'Check this field',
    'validation.slug': 'Slug must be 3-32 chars, lowercase letters, digits, hyphens',
  },
} as const;

export type TranslationKey = keyof typeof translations.ru;

interface I18nContextValue {
  language: Language;
  locale: string;
  setLanguage: (language: Language) => void;
  t: (key: TranslationKey, vars?: Record<string, string | number>) => string;
  dayCount: (count: number) => string;
}

const I18nContext = createContext<I18nContextValue | null>(null);

function isLanguage(value: string | null): value is Language {
  return value === 'ru' || value === 'en';
}

function detectLanguage(): Language {
  if (typeof window === 'undefined') return FALLBACK_LANGUAGE;
  const saved = window.localStorage.getItem(STORAGE_KEY);
  if (isLanguage(saved)) return saved;
  const languages = navigator.languages.length ? navigator.languages : [navigator.language];
  for (const lang of languages) {
    const normalized = lang.toLowerCase();
    if (normalized.startsWith('ru')) return 'ru';
    if (normalized.startsWith('en')) return 'en';
  }
  return FALLBACK_LANGUAGE;
}

function interpolate(template: string, vars?: Record<string, string | number>): string {
  if (!vars) return template;
  return template.replace(/\{(\w+)\}/g, (_, key: string) => String(vars[key] ?? `{${key}}`));
}

function dayKey(language: Language, count: number): TranslationKey {
  if (language === 'en') return count === 1 ? 'common.days.one' : 'common.days.many';
  const mod10 = count % 10;
  const mod100 = count % 100;
  if (mod10 === 1 && mod100 !== 11) return 'common.days.one';
  if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return 'common.days.few';
  return 'common.days.many';
}

export function I18nProvider({ children }: { children: ReactNode }) {
  const [language, setLanguageState] = useState<Language>(() => detectLanguage());

  useEffect(() => {
    document.documentElement.lang = language;
    window.localStorage.setItem(STORAGE_KEY, language);
  }, [language]);

  const setLanguage = useCallback((next: Language) => setLanguageState(next), []);
  const t = useCallback(
    (key: TranslationKey, vars?: Record<string, string | number>) =>
      interpolate(translations[language][key] ?? translations[FALLBACK_LANGUAGE][key], vars),
    [language],
  );
  const dayCount = useCallback(
    (count: number) => t(dayKey(language, count), { count }),
    [language, t],
  );

  const value = useMemo<I18nContextValue>(
    () => ({
      language,
      locale: language === 'ru' ? 'ru-RU' : 'en-US',
      setLanguage,
      t,
      dayCount,
    }),
    [dayCount, language, setLanguage, t],
  );

  return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;
}

export function useI18n(): I18nContextValue {
  const value = useContext(I18nContext);
  if (!value) throw new Error('useI18n must be used within I18nProvider');
  return value;
}

export function translateValidation(t: I18nContextValue['t'], message: string | undefined): string {
  if (!message) return t('validation.invalid');
  if (message.includes('Slug must be')) return t('validation.slug');
  return t('validation.invalid');
}
