'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { Clock, Copy, Info, Loader2, LockKeyhole, Settings2, ShieldCheck, Trash2 } from 'lucide-react';
import ApiErrorAlert from '@/app/components/ApiErrorAlert';
import { useToast } from '@/app/components/ToastProvider';
import { UniversalDropdown, UniversalDropdownOption } from '@/app/components/profile/UniversalDropdown';
import { getResponseErrorTextWithRequestId } from '@/lib/api-client';
import { copyToClipboard } from '@/lib/utils';
import {
  encryptNotebookPlainText,
  generateNotebookSecret,
} from '@/lib/notebook/crypto';
import type { PlanFeatures } from '@/lib/plans/types';

type NotebookDestroyOption = 'after_reading' | '1h' | '24h' | '7d' | '30d' | 'forever';

type NotebookNote = {
  id: string;
  publicId: string;
  title: string | null;
  destroyMode: 'after_reading' | 'expires_at';
  expiresAt: string | null;
  readAt: string | null;
  destroyedAt: string | null;
  createdAt: string;
  passwordRequired: boolean;
};

type NotebookPlanState = {
  features?: PlanFeatures;
} | null;

type NotebookWorkspaceProps = {
  isAuthenticated: boolean;
  planState?: NotebookPlanState;
  unauthenticatedActiveNotesMessage?: string;
};

const STORED_LINKS_KEY = 'linksnap:notebook-links:v1';

const destroyOptions: Array<{ value: NotebookDestroyOption; label: string; description: string }> = [
  { value: 'after_reading', label: 'после прочтения', description: 'одноразовая записка' },
  { value: '1h', label: '1 час', description: 'читать можно до истечения срока' },
  { value: '24h', label: '24 часа', description: 'читать можно до истечения срока' },
  { value: '7d', label: '7 дней', description: 'читать можно до истечения срока' },
  { value: '30d', label: '30 дней', description: 'читать можно до истечения срока' },
  { value: 'forever', label: 'Навсегда', description: 'без срока уничтожения' },
];

function getStoredLinks(): Record<string, string> {
  if (typeof window === 'undefined') return {};

  try {
    const raw = window.localStorage.getItem(STORED_LINKS_KEY);
    if (!raw) return {};
    const parsed = JSON.parse(raw);
    return parsed && typeof parsed === 'object' ? parsed as Record<string, string> : {};
  } catch {
    return {};
  }
}

function setStoredLink(publicId: string, url: string) {
  if (typeof window === 'undefined') return;

  const next = {
    ...getStoredLinks(),
    [publicId]: url,
  };
  window.localStorage.setItem(STORED_LINKS_KEY, JSON.stringify(next));
}

function removeStoredLink(publicId: string) {
  if (typeof window === 'undefined') return;

  const next = getStoredLinks();
  delete next[publicId];
  window.localStorage.setItem(STORED_LINKS_KEY, JSON.stringify(next));
}

function getExpiresAtForOption(option: NotebookDestroyOption) {
  if (option === 'after_reading' || option === 'forever') return null;

  const now = Date.now();
  const durationMs =
    option === '1h'
      ? 60 * 60 * 1000
      : option === '24h'
        ? 24 * 60 * 60 * 1000
        : option === '7d'
          ? 7 * 24 * 60 * 60 * 1000
          : 30 * 24 * 60 * 60 * 1000;

  return new Date(now + durationMs).toISOString();
}

function formatDate(value: string | null) {
  if (!value) return 'без срока';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return 'без срока';

  return date.toLocaleString('ru-RU', {
    day: '2-digit',
    month: 'short',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function getNoteTitle(note: NotebookNote) {
  return note.title?.trim() || `Записка ${note.publicId}`;
}

export default function NotebookWorkspace({
  isAuthenticated,
  planState = null,
  unauthenticatedActiveNotesMessage = 'Вы не зарегистрированы, поэтому список активных записок недоступен.',
}: NotebookWorkspaceProps) {
  const toast = useToast();
  const canUseAdvancedNoteOptions = isAuthenticated && Boolean(planState?.features?.password && planState?.features?.expiresAt);

  const [notes, setNotes] = useState<NotebookNote[]>([]);
  const [storedLinks, setStoredLinks] = useState<Record<string, string>>({});
  const [text, setText] = useState('');
  const [title, setTitle] = useState('');
  const [password, setPassword] = useState('');
  const [destroyOption, setDestroyOption] = useState<NotebookDestroyOption>('after_reading');
  const [showParameters, setShowParameters] = useState(false);
  const [showDestroyMenu, setShowDestroyMenu] = useState(false);
  const [showPrivacy, setShowPrivacy] = useState(false);
  const [createdUrl, setCreatedUrl] = useState('');
  const [createdNoteRequiresPassword, setCreatedNoteRequiresPassword] = useState(false);
  const [isLoading, setIsLoading] = useState(isAuthenticated);
  const [isCreating, setIsCreating] = useState(false);
  const [deletingId, setDeletingId] = useState<string | null>(null);
  const [error, setError] = useState('');

  const selectedDestroyOption = useMemo(
    () => destroyOptions.find((option) => option.value === destroyOption) || destroyOptions[0],
    [destroyOption],
  );

  const loadNotes = useCallback(async () => {
    if (!isAuthenticated) {
      setNotes([]);
      setStoredLinks(getStoredLinks());
      setIsLoading(false);
      return;
    }

    setIsLoading(true);
    setError('');

    try {
      const response = await fetch('/api/notes', { cache: 'no-store' });
      if (!response.ok) {
        throw new Error(await getResponseErrorTextWithRequestId(response, 'Не удалось загрузить записки'));
      }
      const body = await response.json() as { notes?: NotebookNote[] };
      setNotes(body.notes || []);
      setStoredLinks(getStoredLinks());
    } catch (loadError) {
      setError(loadError instanceof Error ? loadError.message : 'Не удалось загрузить записки');
    } finally {
      setIsLoading(false);
    }
  }, [isAuthenticated]);

  useEffect(() => {
    void loadNotes();
  }, [loadNotes]);

  useEffect(() => {
    if (canUseAdvancedNoteOptions) return;

    setDestroyOption('after_reading');
    setPassword('');
    setTitle('');
    setShowDestroyMenu(false);
  }, [canUseAdvancedNoteOptions]);

  useEffect(() => {
    if (!createdUrl) return;

    const timeoutId = window.setTimeout(() => {
      setCreatedUrl('');
      setCreatedNoteRequiresPassword(false);
    }, 5_000);

    return () => window.clearTimeout(timeoutId);
  }, [createdUrl]);

  const handleCreate = useCallback(async (event: React.FormEvent) => {
    event.preventDefault();
    if (isCreating) return;

    const plainText = text.trim();
    const passwordValue = canUseAdvancedNoteOptions ? password.trim() : '';
    const titleValue = canUseAdvancedNoteOptions ? title.trim() : '';
    const effectiveDestroyOption = canUseAdvancedNoteOptions ? destroyOption : 'after_reading';
    if (!plainText) {
      setError('Введите текст записки');
      return;
    }

    setIsCreating(true);
    setError('');
    setCreatedUrl('');
    setCreatedNoteRequiresPassword(false);

    try {
      const secret = generateNotebookSecret();
      const encrypted = await encryptNotebookPlainText({
        plainText,
        secret,
        password: passwordValue,
      });
      const expiresAt = getExpiresAtForOption(effectiveDestroyOption);
      const response = await fetch('/api/notes', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          title: titleValue || null,
          ciphertext: encrypted.ciphertext,
          iv: encrypted.iv,
          salt: encrypted.salt,
          passwordRequired: Boolean(passwordValue),
          passwordVerifier: encrypted.passwordVerifier,
          destroyMode: effectiveDestroyOption === 'after_reading' ? 'after_reading' : 'expires_at',
          expiresAt,
        }),
      });

      if (!response.ok) {
        throw new Error(await getResponseErrorTextWithRequestId(response, 'Не удалось создать записку'));
      }

      const body = await response.json() as { note: NotebookNote };
      const url = `${window.location.origin}/notes/${body.note.publicId}#${secret}`;
      setStoredLink(body.note.publicId, url);
      setStoredLinks(getStoredLinks());
      setCreatedUrl(url);
      setCreatedNoteRequiresPassword(Boolean(passwordValue));
      setText('');
      setTitle('');
      setPassword('');
      setDestroyOption('after_reading');
      setShowParameters(false);
      setShowDestroyMenu(false);
      if (isAuthenticated) {
        setNotes((prev) => [body.note, ...prev]);
      }
      toast.success('Записка создана');
    } catch (createError) {
      setError(createError instanceof Error ? createError.message : 'Не удалось создать записку');
    } finally {
      setIsCreating(false);
    }
  }, [canUseAdvancedNoteOptions, destroyOption, isAuthenticated, isCreating, password, text, title, toast]);

  const handleCopy = useCallback(async (url: string) => {
    const copied = await copyToClipboard(url);
    if (copied) {
      toast.success('Ссылка скопирована');
    } else {
      toast.error('Не удалось скопировать ссылку');
    }
  }, [toast]);

  const handleDelete = useCallback(async (note: NotebookNote) => {
    if (deletingId || !isAuthenticated) return;

    setDeletingId(note.id);
    setError('');

    try {
      const response = await fetch(`/api/notes?id=${encodeURIComponent(note.id)}`, { method: 'DELETE' });
      if (!response.ok) {
        throw new Error(await getResponseErrorTextWithRequestId(response, 'Не удалось удалить записку'));
      }

      removeStoredLink(note.publicId);
      setStoredLinks(getStoredLinks());
      setNotes((prev) => prev.filter((item) => item.id !== note.id));
      toast.success('Записка удалена');
    } catch (deleteError) {
      setError(deleteError instanceof Error ? deleteError.message : 'Не удалось удалить записку');
    } finally {
      setDeletingId(null);
    }
  }, [deletingId, isAuthenticated, toast]);

  return (
    <div className="space-y-6">
      <div className="rounded-2xl border border-white/10 bg-gradient-to-br from-[#120D1D] to-[#0A0A0A] p-5 shadow-2xl md:p-7">
        <div className="mb-5">
          <h1 className="text-2xl font-semibold tracking-tight text-white md:text-3xl">Новая записка</h1>
        </div>

        <form onSubmit={handleCreate} className="space-y-4">
          <div>
            <label htmlFor="notebook-note-text" className="mb-2 block text-sm font-medium text-gray-300">
              Текст записки
            </label>
            <textarea
              id="notebook-note-text"
              value={text}
              onChange={(event) => setText(event.target.value)}
              rows={9}
              maxLength={120_000}
              placeholder="Напишите ваш текст здесь..."
              className="min-h-[220px] w-full resize-y rounded-2xl border border-violet-500/20 bg-black/40 px-4 py-3 font-mono text-sm leading-relaxed text-gray-100 shadow-[inset_0_0_28px_rgba(139,92,246,0.08)] outline-none transition-colors placeholder:text-gray-600 focus:border-violet-400/55 focus:bg-black/50"
            />
          </div>

          <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <button
              type="button"
              onClick={() => setShowParameters((value) => !value)}
              className="inline-flex h-11 items-center justify-center gap-2 rounded-xl border border-white/10 bg-white/[0.03] px-4 text-sm font-medium text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
            >
              <Settings2 className="h-4 w-4 text-violet-300" />
              {showParameters ? 'Скрыть параметры' : 'Открыть параметры'}
            </button>

            <button
              type="submit"
              disabled={isCreating}
              className="inline-flex h-11 items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-fuchsia-500 to-violet-600 px-6 text-sm font-semibold text-white transition-all duration-200 hover:opacity-95 disabled:cursor-not-allowed disabled:opacity-65"
            >
              {isCreating ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  Создание...
                </>
              ) : (
                'Создать записку'
              )}
            </button>
          </div>

          {showParameters ? (
            <div className="rounded-2xl border border-white/10 bg-white/[0.02] p-4">
              {!canUseAdvancedNoteOptions ? (
                <p className="mb-4 rounded-lg border border-amber-500/20 bg-amber-500/10 px-3 py-2 text-xs leading-relaxed text-amber-100">
                  Пароль, название ссылки и выбор времени уничтожения доступны начиная с тарифа Lite. В текущем режиме записка может быть только одноразовой: после прочтения.
                </p>
              ) : null}

              <div className="grid gap-4 lg:grid-cols-[minmax(0,1.1fr)_minmax(240px,0.9fr)]">
                <div>
                  <label className="mb-2 flex items-center gap-2 text-sm font-medium text-gray-300">
                    <Clock className="h-4 w-4 text-violet-300" />
                    Записка уничтожится
                  </label>
                  <UniversalDropdown
                    open={showDestroyMenu}
                    onOpenChange={setShowDestroyMenu}
                    label={selectedDestroyOption.label}
                    active={showDestroyMenu || destroyOption !== 'after_reading'}
                    triggerClassName="h-11 w-full justify-start bg-black/40 px-3"
                    widthClassName="w-full min-w-[240px]"
                  >
                    {destroyOptions.map((option) => (
                      <UniversalDropdownOption
                        key={option.value}
                        selected={destroyOption === option.value}
                        onSelect={() => {
                          if (!canUseAdvancedNoteOptions && option.value !== 'after_reading') return;
                          setDestroyOption(option.value);
                          setShowDestroyMenu(false);
                        }}
                        disabled={!canUseAdvancedNoteOptions && option.value !== 'after_reading'}
                        label={option.label}
                        rightSlot={<span className="text-[11px] text-gray-500">{option.description}</span>}
                      />
                    ))}
                  </UniversalDropdown>
                </div>

                <div>
                  <label htmlFor="notebook-password" className="mb-2 flex items-center gap-2 text-sm font-medium text-gray-300">
                    <LockKeyhole className="h-4 w-4 text-violet-300" />
                    Секретный пароль
                  </label>
                  <input
                    id="notebook-password"
                    type="password"
                    value={password}
                    onChange={(event) => setPassword(event.target.value)}
                    disabled={!canUseAdvancedNoteOptions}
                    placeholder={canUseAdvancedNoteOptions ? 'Необязательно' : 'Недоступно на текущем тарифе'}
                    maxLength={128}
                    className="h-11 w-full rounded-lg border border-white/10 bg-black/40 px-3 text-sm text-white outline-none transition-colors placeholder:text-gray-500 focus:border-violet-500/40 disabled:cursor-not-allowed disabled:opacity-65"
                  />
                </div>
              </div>

              <div className="mt-4">
                <label htmlFor="notebook-title" className="mb-2 block text-sm font-medium text-gray-300">
                  Название ссылки для записки
                </label>
                <input
                  id="notebook-title"
                  value={title}
                  onChange={(event) => setTitle(event.target.value)}
                  disabled={!canUseAdvancedNoteOptions}
                  placeholder={canUseAdvancedNoteOptions ? 'Необязательно' : 'Недоступно на текущем тарифе'}
                  maxLength={160}
                  className="h-11 w-full rounded-lg border border-white/10 bg-black/40 px-3 text-sm text-white outline-none transition-colors placeholder:text-gray-500 focus:border-violet-500/40 disabled:cursor-not-allowed disabled:opacity-65"
                />
              </div>
            </div>
          ) : null}

          <ApiErrorAlert message={error} />
        </form>
      </div>

      {createdUrl ? (
        <div className="rounded-2xl border border-emerald-500/20 bg-emerald-500/10 p-4">
          <div className="mb-3 flex items-center gap-2 text-sm font-medium text-emerald-100">
            <ShieldCheck className="h-4 w-4" />
            Ссылка на записку готова
          </div>
          <div className="flex flex-col gap-3 md:flex-row">
            <input
              value={createdUrl}
              readOnly
              className="h-11 min-w-0 flex-1 rounded-lg border border-emerald-500/20 bg-black/35 px-3 font-mono text-xs text-emerald-50 outline-none"
            />
            <button
              type="button"
              onClick={() => void handleCopy(createdUrl)}
              className="inline-flex h-11 items-center justify-center gap-2 rounded-lg border border-emerald-400/30 bg-emerald-500/15 px-4 text-sm font-medium text-emerald-50 transition-colors hover:bg-emerald-500/25"
            >
              <Copy className="h-4 w-4" />
              Скопировать
            </button>
          </div>
          {createdNoteRequiresPassword ? (
            <p className="mt-2 text-xs text-emerald-200/75">Пароль нужно передать отдельно от ссылки.</p>
          ) : null}
        </div>
      ) : null}

      <div className="rounded-2xl border border-white/10 bg-black/35 p-5">
        <div className="mb-4 flex items-center justify-between gap-3">
          <div>
            <h2 className="text-lg font-semibold text-white">Активные записки</h2>
            <p className="text-sm text-gray-500">Содержимое не хранится в профиле и не показывается в списке.</p>
          </div>
          {isAuthenticated ? (
            <button
              type="button"
              onClick={() => void loadNotes()}
              className="inline-flex h-9 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] px-3 text-sm text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
            >
              Обновить
            </button>
          ) : null}
        </div>

        {!isAuthenticated ? (
          <div className="rounded-xl border border-white/5 bg-white/[0.02] px-4 py-8 text-center text-sm text-gray-500">
            {unauthenticatedActiveNotesMessage}
          </div>
        ) : isLoading ? (
          <div className="flex min-h-[160px] items-center justify-center text-sm text-gray-500">
            <Loader2 className="mr-2 h-4 w-4 animate-spin" />
            Загрузка записок...
          </div>
        ) : notes.length === 0 ? (
          <div className="rounded-xl border border-white/5 bg-white/[0.02] px-4 py-8 text-center text-sm text-gray-500">
            Пока нет активных записок
          </div>
        ) : (
          <div className="space-y-2">
            {notes.map((note) => {
              const storedUrl = storedLinks[note.publicId];
              return (
                <div
                  key={note.id}
                  className="grid gap-3 rounded-xl border border-white/10 bg-white/[0.02] p-4 md:grid-cols-[minmax(0,1fr)_auto] md:items-center"
                >
                  <div className="min-w-0">
                    <div className="mb-1 flex flex-wrap items-center gap-2">
                      <p className="truncate text-sm font-medium text-white">{getNoteTitle(note)}</p>
                      {note.passwordRequired ? (
                        <span className="inline-flex items-center gap-1 rounded-md border border-violet-500/20 bg-violet-500/10 px-2 py-0.5 text-[11px] text-violet-200">
                          <LockKeyhole className="h-3 w-3" />
                          пароль
                        </span>
                      ) : null}
                    </div>
                    <div className="flex flex-wrap items-center gap-3 text-xs text-gray-500">
                      <span className="inline-flex items-center gap-1">
                        <Clock className="h-3.5 w-3.5" />
                        {note.destroyMode === 'after_reading' ? 'после прочтения' : note.expiresAt ? `до ${formatDate(note.expiresAt)}` : 'навсегда'}
                      </span>
                      <span className="font-mono">/{note.publicId}</span>
                    </div>
                  </div>

                  <div className="flex items-center gap-2">
                    <button
                      type="button"
                      disabled={!storedUrl}
                      onClick={() => storedUrl ? void handleCopy(storedUrl) : undefined}
                      title={storedUrl ? 'Скопировать ссылку' : 'Полная ссылка с ключом доступна только в браузере, где была создана'}
                      className="inline-flex h-9 items-center justify-center gap-2 rounded-lg border border-white/10 bg-white/[0.03] px-3 text-sm text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white disabled:cursor-not-allowed disabled:opacity-45"
                    >
                      <Copy className="h-4 w-4" />
                      Ссылка
                    </button>
                    <button
                      type="button"
                      disabled={deletingId === note.id}
                      onClick={() => void handleDelete(note)}
                      className="inline-flex h-9 w-9 items-center justify-center rounded-lg border border-red-500/20 bg-red-500/10 text-red-200 transition-colors hover:bg-red-500/20 disabled:cursor-not-allowed disabled:opacity-60"
                      aria-label="Удалить записку"
                    >
                      {deletingId === note.id ? <Loader2 className="h-4 w-4 animate-spin" /> : <Trash2 className="h-4 w-4" />}
                    </button>
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>

      <div className="text-center">
        <button
          type="button"
          onClick={() => setShowPrivacy((value) => !value)}
          className="inline-flex items-center justify-center gap-2 text-xs text-gray-600 transition-colors hover:text-gray-300"
        >
          <ShieldCheck className="h-3.5 w-3.5" />
          О конфиденциальности
        </button>
        {showPrivacy ? (
          <div className="mx-auto mt-3 max-w-2xl rounded-xl border border-white/10 bg-white/[0.02] p-3 text-left text-xs leading-relaxed text-gray-500">
            <p className="mb-2 flex items-center gap-2 text-gray-400">
              <Info className="h-3.5 w-3.5 text-violet-300" />
              Текст шифруется в браузере до отправки на сервер.
            </p>
            <p>
              Сервер хранит зашифрованный текст, ключ остаётся в части ссылки после #.
              Одноразовые записки уничтожаются после раскрытия, временные доступны только до выбранного срока.
            </p>
          </div>
        ) : null}
      </div>
    </div>
  );
}
