'use client';

import { useCallback, useEffect, useState, useMemo, useRef, type FormEvent } from 'react';
import { loadComponent } from '@/lib/material-components';
import { LoadingSpinner } from '@/components/common/LoadingSpinner';
import { ErrorDisplay } from '@/components/common/ErrorDisplay';
import { createMaterial, updateMaterial, shareMaterial, getMaterialById, getMaterials, type Material } from '@/api/materials';
import { getStudents, type Student } from '@/api/students';
import { useAuth } from '@/contexts/AuthContext';

// Иконки по типу материала
const MATERIAL_ICONS: Record<string, string> = {
  image: 'image',
  video: 'videocam',
  audio: 'audiotrack',
  document: 'description',
  presentation: 'slideshow',
  archive: 'folder_zip',
  other: 'insert_drive_file',
};

// Определить тип для иконки по material_type, MIME и расширению файла
function getMaterialTypeForIcon(material: any): string {
  const type = material?.material_type;
  if (type && type !== 'other' && MATERIAL_ICONS[type]) return type;
  const mime = (material?.file_type || '').toLowerCase();
  const name = material?.file_name || material?.file || '';
  if (mime.startsWith('image/') || /\.(jpe?g|png|gif|webp|bmp|svg)(\?|$)/i.test(name)) return 'image';
  if (mime.startsWith('video/') || /\.(mp4|webm|ogg|mov|avi)(\?|$)/i.test(name)) return 'video';
  if (mime.startsWith('audio/') || /\.(mp3|wav|ogg|m4a)(\?|$)/i.test(name)) return 'audio';
  if (mime.includes('pdf') || /\.pdf(\?|$)/i.test(name) || mime.includes('document') || /\.(docx?|odt)(\?|$)/i.test(name)) return 'document';
  if (mime.includes('presentation') || mime.includes('powerpoint') || /\.(pptx?|odp)(\?|$)/i.test(name)) return 'presentation';
  if (mime.includes('zip') || mime.includes('rar') || mime.includes('archive') || /\.(zip|rar|7z|tar|gz)(\?|$)/i.test(name)) return 'archive';
  return 'other';
}

function getMaterialIcon(material: any): string {
  const type = getMaterialTypeForIcon(material);
  return MATERIAL_ICONS[type] || MATERIAL_ICONS.other;
}

// Базовый URL медиа (тот же хост, что и API)
function getMediaBaseUrl(): string {
  if (typeof window === 'undefined') return '';
  const protocol = window.location.protocol;
  const hostname = window.location.hostname;
  return `${protocol}//${hostname}:8123`;
}

// Получить URL медиа для превью: собираем на фронте, чтобы хост совпадал с API
function getMediaUrl(material: any): string | null {
  if (!material) return null;
  const base = getMediaBaseUrl();
  if (material.file) {
    const f = String(material.file).trim();
    if (f.startsWith('http')) return f;
    // Бэкенд отдаёт путь вида /media/materials/... или materials/...
    const path = f.startsWith('/') ? f : `/${f}`;
    return `${base}${path}`;
  }
  if (material.file_url) return material.file_url;
  return material.url || null;
}

const IMAGE_MIME_PREFIX = 'image/';
const IMAGE_EXT = /\.(jpe?g|png|gif|webp|bmp|svg)(\?|$)/i;
const VIDEO_MIME_PREFIX = 'video/';
const VIDEO_EXT = /\.(mp4|webm|ogg|mov|avi)(\?|$)/i;

// Сократить строку до 8 символов (с многоточием при обрезке)
function truncateTo8(s: string): string {
  const t = (s || '').trim();
  if (t.length <= 8) return t;
  return t.slice(0, 8) + '…';
}

// Ключ категории типа файла (для фильтра)
type FileTypeCategory = 'image' | 'video' | 'audio' | 'document' | 'presentation' | 'archive' | 'other';

function getFileTypeCategory(material: any): FileTypeCategory {
  const name = (material?.file_name || material?.file || '').toLowerCase();
  const mime = (material?.file_type || '').toLowerCase();
  const ext = name.match(/\.([a-z0-9]+)(\?|$)/i)?.[1]?.toLowerCase() || '';
  if (mime.startsWith('image/') || ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'].includes(ext)) return 'image';
  if (mime.startsWith('video/') || ['mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv'].includes(ext)) return 'video';
  if (mime.startsWith('audio/') || ['mp3', 'wav', 'ogg', 'm4a', 'flac'].includes(ext)) return 'audio';
  if (mime.includes('pdf') || mime.includes('document') || ['pdf', 'doc', 'docx', 'odt', 'txt', 'rtf'].includes(ext)) return 'document';
  if (mime.includes('presentation') || mime.includes('powerpoint') || ['ppt', 'pptx', 'odp'].includes(ext)) return 'presentation';
  if (mime.includes('zip') || mime.includes('rar') || ['zip', 'rar', '7z', 'tar', 'gz'].includes(ext)) return 'archive';
  return 'other';
}

// Подпись типа файла для отображения: Картинка, Документ, Аудио, Видео и т.д.
const FILE_TYPE_LABELS: Record<FileTypeCategory, string> = {
  image: 'Картинка',
  video: 'Видео',
  audio: 'Аудио',
  document: 'Документ',
  presentation: 'Презентация',
  archive: 'Архив',
  other: 'Файл',
};

function getFileTypeLabel(material: any): string {
  return FILE_TYPE_LABELS[getFileTypeCategory(material)];
}

// Расширение файла для сообщения «Не удалось открыть файл .xxx»
function getFileExtension(material: any): string {
  const name = (material?.file_name || material?.file || '').toLowerCase();
  const m = name.match(/\.([a-z0-9]+)(\?|$)/i);
  return m ? `.${m[1]}` : '';
}

// Типы, которые браузер не может отобразить — вместо iframe показываем модальное сообщение
const BROWSER_CANNOT_DISPLAY = [
  'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'odt', 'ods', 'odp',
  'zip', 'rar', '7z', 'tar', 'gz', 'exe', 'dmg', 'msi',
];
function cannotDisplayInBrowser(material: any): boolean {
  const ext = getFileExtension(material).replace(/^\./, '').toLowerCase();
  return BROWSER_CANNOT_DISPLAY.includes(ext);
}

function isImageMaterial(material: any): boolean {
  if (material.material_type === 'image') return true;
  const mime = (material.file_type || '').toLowerCase();
  if (mime.startsWith(IMAGE_MIME_PREFIX)) return true;
  const name = material.file_name || material.file || '';
  return IMAGE_EXT.test(name);
}

function isVideoMaterial(material: any): boolean {
  if (material.material_type === 'video') return true;
  const mime = (material.file_type || '').toLowerCase();
  if (mime.startsWith(VIDEO_MIME_PREFIX)) return true;
  const name = material.file_name || material.file || '';
  return VIDEO_EXT.test(name);
}

const PDF_EXT = /\.pdf(\?|$)/i;
const TEXT_EXT = /\.(txt|md|py|php|js|ts|jsx|tsx|vue|json|html|htm|css|scss|less|xml|csv|rtf|log|yml|yaml|env|sql|sh|bat|cmd|ini|cfg|conf)(\?|$)/i;

function isPdfMaterial(material: any): boolean {
  const mime = (material?.file_type || '').toLowerCase();
  if (mime.includes('pdf')) return true;
  const name = (material?.file_name || material?.file || '').toLowerCase();
  return PDF_EXT.test(name);
}

function isTextPreviewMaterial(material: any): boolean {
  const mime = (material?.file_type || '').toLowerCase();
  if (mime.startsWith('text/') || mime.includes('json') || mime.includes('javascript') || mime.includes('xml')) return true;
  const name = (material?.file_name || material?.file || '').toLowerCase();
  return TEXT_EXT.test(name);
}

const FILE_TYPE_CHIPS: { value: FileTypeCategory | null; label: string }[] = [
  { value: 'image', label: 'Картинка' },
  { value: 'document', label: 'Документ' },
  { value: 'audio', label: 'Аудио' },
  { value: 'video', label: 'Видео' },
  { value: 'presentation', label: 'Презентация' },
  { value: 'archive', label: 'Архив' },
  { value: 'other', label: 'Файл' },
];

const SEARCH_DEBOUNCE_MS = 400;

const TEXT_PREVIEW_MAX_CHARS = 1200;
const TEXT_PREVIEW_LINES = 18;

function MaterialTextPreview({ url }: { url: string }) {
  const [text, setText] = useState<string | null>(null);
  const [failed, setFailed] = useState(false);
  useEffect(() => {
    let cancelled = false;
    setFailed(false);
    setText(null);
    fetch(url)
      .then((r) => {
        if (!r.ok) throw new Error('fetch failed');
        return r.text();
      })
      .then((t) => {
        if (!cancelled) setText(t.slice(0, TEXT_PREVIEW_MAX_CHARS));
      })
      .catch(() => {
        if (!cancelled) setFailed(true);
      });
    return () => { cancelled = true; };
  }, [url]);
  if (failed) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%' }}>
        <span className="material-symbols-outlined" style={{ fontSize: 48, color: 'var(--md-sys-color-primary)' }}>description</span>
      </div>
    );
  }
  if (text === null) {
    return (
      <div style={{ padding: 16, fontSize: 13, color: 'var(--md-sys-color-on-surface-variant)' }}>Загрузка…</div>
    );
  }
  const lines = text.split(/\r?\n/).slice(0, TEXT_PREVIEW_LINES);
  const display = lines.join('\n') + (text.length >= TEXT_PREVIEW_MAX_CHARS ? '\n…' : '');
  return (
    <pre
      style={{
        margin: 0,
        padding: '12px 14px',
        fontSize: 11,
        lineHeight: 1.45,
        fontFamily: 'ui-monospace, monospace',
        color: 'var(--md-sys-color-on-surface)',
        whiteSpace: 'pre-wrap',
        wordBreak: 'break-word',
        overflow: 'hidden',
        display: '-webkit-box',
        WebkitLineClamp: TEXT_PREVIEW_LINES,
        WebkitBoxOrient: 'vertical',
        textAlign: 'left',
        height: '100%',
        boxSizing: 'border-box',
      }}
    >
      {display || ' (пусто)'}
    </pre>
  );
}

const TEXT_FULL_MAX_CHARS = 500000;

function MaterialTextPreviewFull({ url }: { url: string }) {
  const [text, setText] = useState<string | null>(null);
  const [failed, setFailed] = useState(false);
  useEffect(() => {
    let cancelled = false;
    setFailed(false);
    setText(null);
    fetch(url)
      .then((r) => {
        if (!r.ok) throw new Error('fetch failed');
        return r.text();
      })
      .then((t) => {
        if (!cancelled) setText(t.length > TEXT_FULL_MAX_CHARS ? t.slice(0, TEXT_FULL_MAX_CHARS) + '\n\n… (файл обрезан)' : t);
      })
      .catch(() => {
        if (!cancelled) setFailed(true);
      });
    return () => { cancelled = true; };
  }, [url]);
  if (failed) {
    return (
      <div style={{ padding: 24, textAlign: 'center', color: 'var(--md-sys-color-on-surface-variant)' }}>
        Не удалось загрузить содержимое
      </div>
    );
  }
  if (text === null) {
    return (
      <div style={{ padding: 24, fontSize: 14, color: 'var(--md-sys-color-on-surface-variant)' }}>Загрузка…</div>
    );
  }
  return (
    <pre
      style={{
        margin: 0,
        padding: 16,
        fontSize: 13,
        lineHeight: 1.5,
        fontFamily: 'ui-monospace, monospace',
        color: 'var(--md-sys-color-on-surface)',
        whiteSpace: 'pre-wrap',
        wordBreak: 'break-word',
        textAlign: 'left',
        minWidth: 0,
      }}
    >
      {text || ' (пусто)'}
    </pre>
  );
}

export default function MaterialsPage() {
  const { user } = useAuth();
  const isClient = user?.role === 'client';

  const [componentsLoaded, setComponentsLoaded] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [searchQueryDebounced, setSearchQueryDebounced] = useState('');
  const [fileTypeFilter, setFileTypeFilter] = useState<FileTypeCategory | null>(null);
  const [mentorFilter, setMentorFilter] = useState<number | null>(null);
  const [openMenuId, setOpenMenuId] = useState<number | null>(null);
  
  // Состояние для редактирования материала
  const [editingMaterial, setEditingMaterial] = useState<Material | null>(null);
  const [editFormData, setEditFormData] = useState({ title: '', description: '' });
  const [editFile, setEditFile] = useState<File | null>(null);
  const [editLoading, setEditLoading] = useState(false);
  const [editError, setEditError] = useState<string | null>(null);
  
  // Состояние для выбора учеников
  const [students, setStudents] = useState<Student[]>([]);
  const [studentsLoading, setStudentsLoading] = useState(false);
  const [selectedStudentIds, setSelectedStudentIds] = useState<string[]>([]);
  const [studentSearch, setStudentSearch] = useState('');
  
  // Состояние для просмотра материала
  const [previewMaterial, setPreviewMaterial] = useState<any | null>(null);

  // Панель «Добавить материал» (выдвижная справа)
  const [addPanelOpen, setAddPanelOpen] = useState(false);
  const [addTitle, setAddTitle] = useState('');
  const [addDescription, setAddDescription] = useState('');
  const [addFile, setAddFile] = useState<File | null>(null);
  const [addFilePreviewUrl, setAddFilePreviewUrl] = useState<string | null>(null);
  const [addShareStudentIds, setAddShareStudentIds] = useState<string[]>([]);
  const [addStudentSearch, setAddStudentSearch] = useState('');
  const [addLoading, setAddLoading] = useState(false);
  const [addError, setAddError] = useState<string | null>(null);
  const [addStudentsLoaded, setAddStudentsLoaded] = useState(false);
  const [addStudentsList, setAddStudentsList] = useState<Student[]>([]);
  const [addStudentSelectOpen, setAddStudentSelectOpen] = useState(false);
  const addStudentSelectRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    Promise.all([
      loadComponent('elevated-card'),
      loadComponent('filled-text-field'),
      loadComponent('filled-button'),
      loadComponent('icon'),
    ]).then(() => {
      setComponentsLoaded(true);
    });
  }, []);

  // Debounce поиска — уменьшаем количество запросов при вводе
  useEffect(() => {
    const timer = setTimeout(() => {
      setSearchQueryDebounced(searchQuery);
    }, SEARCH_DEBOUNCE_MS);
    return () => clearTimeout(timer);
  }, [searchQuery]);

  // Список материалов с подгрузкой по скроллу: первые 10, затем страницами
  const PAGE_SIZE = 10;
  const [materialsList, setMaterialsList] = useState<any[]>([]);
  const [materialsPage, setMaterialsPage] = useState(1);
  const [materialsHasMore, setMaterialsHasMore] = useState(true);
  const [materialsLoading, setMaterialsLoading] = useState(true);
  const [materialsLoadingMore, setMaterialsLoadingMore] = useState(false);
  const [materialsError, setMaterialsError] = useState<Error | null>(null);
  const loadMoreSentinelRef = useRef<HTMLDivElement>(null);

  const searchForRef = useRef<string>('');
  const loadMaterialsPage = useCallback(async (page: number, append: boolean) => {
    const search = searchQueryDebounced.trim() || undefined;
    searchForRef.current = search ?? '';
    const isFirst = page === 1;
    if (isFirst) {
      setMaterialsLoading(true);
    } else {
      setMaterialsLoadingMore(true);
    }
    setMaterialsError(null);
    try {
      const data = await getMaterials({
        page,
        page_size: PAGE_SIZE,
        search,
      });
      if (searchForRef.current !== (search ?? '')) return;
      const list = data.results || [];
      setMaterialsList((prev) => {
        if (!append) return list;
        const prevIds = new Set(prev.map((m: any) => m.id));
        const newItems = list.filter((m: any) => !prevIds.has(m.id));
        return newItems.length === 0 ? prev : [...prev, ...newItems];
      });
      setMaterialsHasMore(!!data.next);
      setMaterialsPage(page);
    } catch (err: any) {
      if (searchForRef.current !== (search ?? '')) return;
      setMaterialsError(err instanceof Error ? err : new Error(err?.message || 'Ошибка загрузки'));
    } finally {
      if (searchForRef.current === (search ?? '')) {
        setMaterialsLoading(false);
        setMaterialsLoadingMore(false);
      }
    }
  }, [searchQueryDebounced]);

  // Первая загрузка и сброс при смене поиска
  useEffect(() => {
    setMaterialsList([]);
    setMaterialsPage(1);
    setMaterialsHasMore(true);
    loadMaterialsPage(1, false);
  }, [searchQueryDebounced]);

  // Подгрузка по скроллу (IntersectionObserver)
  useEffect(() => {
    if (!materialsHasMore || materialsLoadingMore || materialsLoading) return;
    const el = loadMoreSentinelRef.current;
    if (!el) return;
    const observer = new IntersectionObserver(
      (entries) => {
        if (!entries[0]?.isIntersecting) return;
        loadMaterialsPage(materialsPage + 1, true);
      },
      { rootMargin: '200px', threshold: 0.1 }
    );
    observer.observe(el);
    return () => observer.disconnect();
  }, [materialsHasMore, materialsLoadingMore, materialsLoading, materialsPage, loadMaterialsPage]);

  const refetch = useCallback(() => {
    setMaterialsList([]);
    setMaterialsPage(1);
    setMaterialsHasMore(true);
    loadMaterialsPage(1, false);
  }, [loadMaterialsPage]);

  const mutate = useCallback((updater: (prev: any[]) => any[]) => {
    setMaterialsList(updater);
  }, []);

  const materials = materialsList;
  
  // Определяем какие категории имеют файлы
  const availableCategories = useMemo(() => {
    const categories = new Set<FileTypeCategory>();
    materials.forEach((m: any) => {
      categories.add(getFileTypeCategory(m));
    });
    return categories;
  }, [materials]);

  // Фильтруем чипы - показываем только те, для которых есть файлы
  const visibleChips = useMemo(() => {
    return FILE_TYPE_CHIPS.filter(({ value }) => value && availableCategories.has(value));
  }, [availableCategories]);

  // Уникальные менторы (владельцы материалов) — для чипов у студента
  const mentorChips = useMemo(() => {
    const seen = new Set<number>();
    const list: { id: number; name: string }[] = [];
    materials.forEach((m: any) => {
      const owner = m.owner;
      if (!owner?.id) return;
      if (seen.has(owner.id)) return;
      seen.add(owner.id);
      const name = [owner.first_name, owner.last_name].filter(Boolean).join(' ') || owner.email || `Ментор ${owner.id}`;
      list.push({ id: owner.id, name: name.trim() || 'Без имени' });
    });
    return list.sort((a, b) => a.name.localeCompare(b.name));
  }, [materials]);

  const filteredMaterials = useMemo(
    () =>
      materials.filter((m: any) => {
        const matchesType = !fileTypeFilter || getFileTypeCategory(m) === fileTypeFilter;
        const matchesMentor = !mentorFilter || (m.owner?.id === mentorFilter);
        return matchesType && matchesMentor;
      }),
    [materials, fileTypeFilter, mentorFilter]
  );

  // Закрытие выпадающего списка учеников по клику снаружи
  useEffect(() => {
    if (!addStudentSelectOpen) return;
    const handle = (e: MouseEvent) => {
      if (addStudentSelectRef.current && !addStudentSelectRef.current.contains(e.target as Node)) {
        setAddStudentSelectOpen(false);
      }
    };
    document.addEventListener('mousedown', handle);
    return () => document.removeEventListener('mousedown', handle);
  }, [addStudentSelectOpen]);

  // Загрузка списка учеников при открытии панели добавления
  useEffect(() => {
    if (!addPanelOpen) return;
    setAddStudentsLoaded(false);
    getStudents({ page_size: 1000 })
      .then((res) => {
        setAddStudentsList(res.results || []);
      })
      .catch(() => setAddStudentsList([]))
      .finally(() => setAddStudentsLoaded(true));
  }, [addPanelOpen]);

  const closeAddPanel = () => {
    if (addLoading) return;
    setAddPanelOpen(false);
    setAddTitle('');
    setAddDescription('');
    setAddFile(null);
    if (addFilePreviewUrl) {
      URL.revokeObjectURL(addFilePreviewUrl);
      setAddFilePreviewUrl(null);
    }
    setAddShareStudentIds([]);
    setAddStudentSearch('');
    setAddError(null);
  };

  // Превью выбранного файла: object URL для изображений
  useEffect(() => {
    if (!addFile) {
      if (addFilePreviewUrl) {
        URL.revokeObjectURL(addFilePreviewUrl);
        setAddFilePreviewUrl(null);
      }
      return;
    }
    if (addFile.type.startsWith('image/')) {
      const url = URL.createObjectURL(addFile);
      setAddFilePreviewUrl(url);
      return () => {
        URL.revokeObjectURL(url);
        setAddFilePreviewUrl(null);
      };
    }
    if (addFilePreviewUrl) {
      URL.revokeObjectURL(addFilePreviewUrl);
      setAddFilePreviewUrl(null);
    }
  }, [addFile]);

  const handleAddSubmit = async (e: FormEvent) => {
    e.preventDefault();
    setAddError(null);
    if (!addTitle.trim()) {
      setAddError('Укажите название материала');
      return;
    }
    if (!addFile) {
      setAddError('Выберите файл для загрузки');
      return;
    }
    setAddLoading(true);
    try {
      const created = await createMaterial({
        title: addTitle.trim(),
        description: addDescription.trim() || undefined,
        file: addFile,
      });
      if (addShareStudentIds.length > 0) {
        try {
          await shareMaterial(created.id, addShareStudentIds);
        } catch {
          // материал уже создан
        }
      }
      refetch();
      closeAddPanel();
    } catch (err: any) {
      setAddError(err?.message || 'Ошибка при создании материала');
    } finally {
      setAddLoading(false);
    }
  };

  if (!componentsLoaded) {
    return (
      <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50vh' }}>
        <div>Загрузка...</div>
      </div>
    );
  }

  return (
    <div style={{ padding: '24px' }} data-tour="materials-root">
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'space-between',
          marginBottom: '16px',
          gap: 16,
        }}
      >
        <div style={{ flex: 1, minWidth: 0 }} />
        {!isClient && (
          <button
            type="button"
            data-tour="materials-add"
            onClick={() => setAddPanelOpen(true)}
            style={{
              display: 'inline-flex',
              alignItems: 'center',
              gap: 8,
              padding: '10px 16px',
              fontSize: 14,
              fontWeight: 500,
              color: 'var(--md-sys-color-on-primary)',
              background: 'var(--md-sys-color-primary)',
              border: 'none',
              borderRadius: 8,
              cursor: 'pointer',
              whiteSpace: 'nowrap',
            }}
          >
            <span className="material-symbols-outlined" style={{ fontSize: 20 }}>add</span>
            Добавить материал
          </button>
        )}
      </div>
      <div
        style={{
          marginBottom: '24px',
          position: 'relative',
          width: '100%',
          cursor: 'text',
        }}
        onClick={(e) => {
          const input = (e.currentTarget as HTMLElement).querySelector('input');
          input?.focus();
        }}
      >
        <input
          type="text"
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          placeholder="Поиск по названию, описанию или имени файла..."
          style={{
            width: '100%',
            padding: '12px 16px 12px 44px',
            fontSize: 16,
            border: '1px solid var(--md-sys-color-outline)',
            borderRadius: 12,
            background: 'var(--md-sys-color-surface)',
            color: 'var(--md-sys-color-on-surface)',
            outline: 'none',
            boxSizing: 'border-box',
          }}
        />
        <md-icon
          style={{
            position: 'absolute',
            left: 14,
            top: '50%',
            transform: 'translateY(-50%)',
            fontSize: 20,
            color: 'var(--md-sys-color-on-surface-variant)',
            pointerEvents: 'none',
          }}
        >
          search
        </md-icon>
      </div>

      {/* Чипы «Ментор» — только для студента: фильтр по тому, кто дал материал */}
      {isClient && mentorChips.length > 0 && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', marginBottom: '16px' }}>
          <button
            type="button"
            onClick={() => setMentorFilter(null)}
            style={{
              display: 'inline-flex',
              alignItems: 'center',
              justifyContent: 'center',
              height: '32px',
              padding: '0 16px',
              borderRadius: '8px',
              fontSize: '14px',
              fontWeight: 500,
              cursor: 'pointer',
              transition: 'all 0.2s ease',
              border: !mentorFilter ? 'none' : '1px solid var(--md-sys-color-outline)',
              background: !mentorFilter ? 'var(--md-sys-color-primary)' : 'transparent',
              color: !mentorFilter ? 'var(--md-sys-color-on-primary)' : 'var(--md-sys-color-on-surface)',
            }}
          >
            Все менторы
          </button>
          {mentorChips.map(({ id, name }) => {
            const isSelected = mentorFilter === id;
            return (
              <button
                key={id}
                type="button"
                onClick={() => {
                  if (mentorFilter === id) {
                    setMentorFilter(null);
                  } else {
                    setMentorFilter(id);
                  }
                }}
                style={{
                  display: 'inline-flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  height: '32px',
                  padding: '0 16px',
                  borderRadius: '8px',
                  fontSize: '14px',
                  fontWeight: 500,
                  cursor: 'pointer',
                  transition: 'all 0.2s ease',
                  border: isSelected ? 'none' : '1px solid var(--md-sys-color-outline)',
                  background: isSelected ? 'var(--md-sys-color-primary)' : 'transparent',
                  color: isSelected ? 'var(--md-sys-color-on-primary)' : 'var(--md-sys-color-on-surface)',
                }}
              >
                {name}
              </button>
            );
          })}
        </div>
      )}

      {/* Кастомные чипы типов файлов - показываем только если есть файлы */}
      {visibleChips.length > 0 && (
        <div style={{ 
          display: 'flex', 
          flexWrap: 'wrap', 
          gap: '8px', 
          marginBottom: '24px' 
        }}>
          {visibleChips.map(({ value, label }) => {
            const isSelected = fileTypeFilter === value;
            return (
              <button
                key={value ?? 'all'}
                type="button"
                onClick={() => {
                  if (fileTypeFilter === value) {
                    setFileTypeFilter(null);
                  } else {
                    setFileTypeFilter(value);
                  }
                }}
                style={{
                  display: 'inline-flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  height: '32px',
                  padding: '0 16px',
                  borderRadius: '8px',
                  fontSize: '14px',
                  fontWeight: 500,
                  cursor: 'pointer',
                  transition: 'all 0.2s ease',
                  border: isSelected ? 'none' : '1px solid var(--md-sys-color-outline)',
                  background: isSelected ? 'var(--md-sys-color-primary)' : 'transparent',
                  color: isSelected ? 'var(--md-sys-color-on-primary)' : 'var(--md-sys-color-on-surface)',
                }}
              >
                {label}
              </button>
            );
          })}
        </div>
      )}

      {materialsError && materialsError.message !== 'canceled' && (
        <ErrorDisplay error={materialsError} onRetry={refetch} />
      )}

      {/* Прогресс поиска — тонкая полоска под полем поиска */}
      {materialsLoading && (
        <div
          style={{
            height: 3,
            background: 'var(--md-sys-color-outline-variant)',
            borderRadius: 2,
            marginBottom: 24,
            overflow: 'hidden',
          }}
        >
          <div
            style={{
              height: '100%',
              width: '40%',
              background: 'var(--md-sys-color-primary)',
              borderRadius: 2,
              animation: 'searchProgress 1.2s ease-in-out infinite',
            }}
          />
        </div>
      )}

      {materialsLoading && materialsList.length === 0 ? (
        <LoadingSpinner size="large" />
      ) : filteredMaterials.length === 0 ? (
        <md-elevated-card style={{ padding: '40px', borderRadius: '20px', textAlign: 'center' }}>
          <md-icon style={{ fontSize: '64px', color: 'var(--md-sys-color-on-surface-variant)', marginBottom: '16px' }}>
            folder
          </md-icon>
          <p style={{ fontSize: '16px', color: 'var(--md-sys-color-on-surface-variant)' }}>
            {searchQuery ? 'Материалы не найдены' : 'Нет материалов'}
          </p>
        </md-elevated-card>
      ) : (
        <div
          className="materials-cards-grid"
          style={{
            display: 'grid',
            gridTemplateColumns: 'repeat(auto-fill, minmax(min(340px, 100%), 1fr))',
            gap: '24px',
            opacity: materialsLoading ? 0.7 : 1,
            transition: 'opacity 0.2s ease',
          }}
        >
          {filteredMaterials.map((material: any) => {
            const mediaUrl = getMediaUrl(material);
            const isImage = isImageMaterial(material) && mediaUrl;
            const isVideo = isVideoMaterial(material) && mediaUrl;
            const isPdf = isPdfMaterial(material) && mediaUrl;
            const isText = isTextPreviewMaterial(material) && mediaUrl;
            const iconName = getMaterialIcon(material);
            const ownerName = material.owner
              ? [material.owner.first_name, material.owner.last_name].filter(Boolean).join(' ') || material.owner.email
              : '';

            return (
              <md-elevated-card
                key={material.id}
                className="ios26-panel"
                style={{
                  borderRadius: 'var(--ios26-radius-md)',
                  overflow: 'hidden',
                  display: 'flex',
                  flexDirection: 'column',
                  transition: 'transform 0.2s, box-shadow 0.25s ease',
                  background: 'var(--ios26-glass)',
                  backdropFilter: 'var(--ios26-blur)',
                  WebkitBackdropFilter: 'var(--ios26-blur)',
                  border: '1px solid var(--ios26-glass-border)',
                  boxShadow: 'var(--ios26-shadow)',
                }}
                onMouseEnter={(e: any) => {
                  e.currentTarget.style.transform = 'translateY(-4px)';
                  e.currentTarget.style.boxShadow = 'var(--ios26-shadow-hover)';
                }}
                onMouseLeave={(e: any) => {
                  e.currentTarget.style.transform = 'translateY(0)';
                  e.currentTarget.style.boxShadow = 'var(--ios26-shadow)';
                }}
              >
                {/* Шапка карточки: заголовок; меню Редактировать/Удалить только для ментора */}
                <div
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: '8px',
                    padding: '16px 16px 0',
                    position: 'relative',
                  }}
                >
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 16, fontWeight: 600, color: 'var(--md-sys-color-on-surface)' }}>
                      {truncateTo8(material.title || material.file_name || 'Без названия')}
                    </div>
                  </div>
                  {!isClient && (
                  <div style={{ position: 'relative' }}>
                    <button
                      type="button"
                      onClick={(e) => {
                        e.stopPropagation();
                        setOpenMenuId((prev) => (prev === material.id ? null : material.id));
                      }}
                      style={{
                        background: 'none',
                        border: 'none',
                        padding: 8,
                        cursor: 'pointer',
                        color: 'var(--md-sys-color-on-surface-variant)',
                      }}
                      aria-label="Меню"
                    >
                      <md-icon>more_vert</md-icon>
                    </button>
                    {openMenuId === material.id && (
                      <>
                        <div
                          role="button"
                          tabIndex={0}
                          style={{ position: 'fixed', inset: 0, zIndex: 10 }}
                          onClick={() => setOpenMenuId(null)}
                          onKeyDown={(e) => e.key === 'Escape' && setOpenMenuId(null)}
                          aria-label="Закрыть меню"
                        />
                        <div
                          style={{
                            position: 'absolute',
                            right: 0,
                            top: '100%',
                            marginTop: 4,
                            zIndex: 11,
                            minWidth: 160,
                            padding: '8px 0',
                            background: 'var(--md-sys-color-surface-container-high)',
                            borderRadius: 12,
                            boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
                          }}
                        >
                          <button
                            type="button"
                            onClick={async () => {
                              setOpenMenuId(null);
                              // Открываем sidebar редактирования
                              setEditingMaterial(material);
                              setEditFormData({
                                title: material.title || '',
                                description: material.description || '',
                              });
                              setEditFile(null);
                              setEditError(null);
                              setStudentSearch('');
                              
                              // Загружаем список студентов
                              setStudentsLoading(true);
                              try {
                                const studentsData = await getStudents({ page_size: 1000 });
                                setStudents(studentsData.results || []);
                                
                                // Загружаем полные данные материала для получения shared_with
                                const fullMaterial = await getMaterialById(material.id);
                                const sharedIds = fullMaterial.shared_with?.map((u) => String(u.id)) || [];
                                setSelectedStudentIds(sharedIds);
                              } catch (err) {
                                console.error('Ошибка загрузки данных:', err);
                              } finally {
                                setStudentsLoading(false);
                              }
                            }}
                            style={{
                              display: 'block',
                              width: '100%',
                              padding: '10px 16px',
                              border: 'none',
                              background: 'none',
                              textAlign: 'left',
                              fontSize: 14,
                              color: 'var(--md-sys-color-on-surface)',
                              cursor: 'pointer',
                            }}
                          >
                            Редактировать
                          </button>
                          <button
                            type="button"
                            onClick={() => {
                              setOpenMenuId(null);
                              // TODO: удалить материал (подтверждение + API)
                            }}
                            style={{
                              display: 'block',
                              width: '100%',
                              padding: '10px 16px',
                              border: 'none',
                              background: 'none',
                              textAlign: 'left',
                              fontSize: 14,
                              color: 'var(--md-sys-color-error)',
                              cursor: 'pointer',
                            }}
                          >
                            Удалить
                          </button>
                        </div>
                      </>
                    )}
                  </div>
                  )}
                </div>

                {/* Превью: фото, видео, PDF, текст или иконка — максимальная область */}
                <div
                  style={{
                    width: '100%',
                    aspectRatio: '4/3',
                    minHeight: 200,
                    background: 'var(--md-sys-color-surface-container-low)',
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    marginTop: 12,
                    position: 'relative',
                    overflow: 'hidden',
                  }}
                >
                  {isImage && (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img
                      src={mediaUrl}
                      alt={material.title}
                      style={{
                        width: '100%',
                        height: '100%',
                        objectFit: 'cover',
                        display: 'block',
                      }}
                    />
                  )}
                  {isVideo && (
                    <>
                      <video
                        src={mediaUrl}
                        preload="metadata"
                        muted
                        playsInline
                        style={{
                          width: '100%',
                          height: '100%',
                          objectFit: 'cover',
                          display: 'block',
                        }}
                      />
                      <div
                        style={{
                          position: 'absolute',
                          inset: 0,
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'center',
                          background: 'rgba(0,0,0,0.25)',
                        }}
                      >
                        <md-icon style={{ fontSize: 64, color: 'rgba(255,255,255,0.95)' }}>play_circle_filled</md-icon>
                      </div>
                    </>
                  )}
                  {isPdf && !isImage && !isVideo && (
                    <div
                      style={{
                        position: 'absolute',
                        inset: 0,
                        overflow: 'hidden',
                      }}
                    >
                      <iframe
                        src={`${mediaUrl}#toolbar=0&view=FitH`}
                        title={material.title || 'PDF'}
                        style={{
                          position: 'absolute',
                          top: 0,
                          left: 0,
                          width: 'calc(100% + 20px)',
                          height: '100%',
                          border: 'none',
                          background: 'var(--md-sys-color-surface-container-low)',
                          pointerEvents: 'none',
                        }}
                      />
                      {/* Невидимый слой поверх — блокирует скролл и клики по iframe */}
                      <div
                        style={{
                          position: 'absolute',
                          inset: 0,
                          zIndex: 1,
                          cursor: 'default',
                        }}
                        aria-hidden
                      />
                    </div>
                  )}
                  {isText && !isImage && !isVideo && !isPdf && (
                    <div style={{ width: '100%', height: '100%', overflow: 'hidden', background: 'var(--md-sys-color-surface)' }}>
                      <MaterialTextPreview url={mediaUrl} />
                    </div>
                  )}
                  {!isImage && !isVideo && !isPdf && !isText && (
                    <span
                      className="material-symbols-outlined"
                      style={{
                        fontSize: 64,
                        color: 'var(--md-sys-color-primary)',
                        fontVariationSettings: "'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 48",
                      }}
                      aria-hidden
                    >
                      {iconName}
                    </span>
                  )}
                </div>

                {/* Контент: тип файла + дата, описание */}
                <div style={{ padding: '16px', flex: 1, display: 'flex', flexDirection: 'column', gap: 8 }}>
                  <div style={{ fontSize: 13, color: 'var(--md-sys-color-on-surface-variant)' }}>
                    {getFileTypeLabel(material)}
                    {material.created_at && ` · ${new Date(material.created_at).toLocaleDateString('ru-RU')}`}
                  </div>
                  {material.description && (
                    <p
                      style={{
                        fontSize: 14,
                        color: 'var(--md-sys-color-on-surface-variant)',
                        margin: 0,
                        display: '-webkit-box',
                        WebkitLineClamp: 3,
                        WebkitBoxOrient: 'vertical',
                        overflow: 'hidden',
                        lineHeight: 1.4,
                      }}
                    >
                      {material.description}
                    </p>
                  )}

                  {/* Кнопки: вторичная и основная */}
                  <div style={{ display: 'flex', gap: 8, marginTop: 'auto', paddingTop: 8 }}>
                    <button
                      type="button"
                      onClick={() => setPreviewMaterial({ ...material, mediaUrl })}
                      style={{
                        flex: 1,
                        padding: '10px 16px',
                        borderRadius: 20,
                        border: '1px solid var(--md-sys-color-primary)',
                        background: 'transparent',
                        color: 'var(--md-sys-color-primary)',
                        fontSize: 14,
                        fontWeight: 500,
                        cursor: 'pointer',
                      }}
                    >
                      Открыть
                    </button>
                    <button
                      type="button"
                      onClick={() => {
                        if (mediaUrl) {
                          const a = document.createElement('a');
                          a.href = mediaUrl;
                          a.download = material.file_name || material.title || 'file';
                          a.click();
                        }
                      }}
                      style={{
                        flex: 1,
                        padding: '10px 16px',
                        borderRadius: 20,
                        border: 'none',
                        background: 'var(--md-sys-color-primary)',
                        color: 'var(--md-sys-color-on-primary)',
                        fontSize: 14,
                        fontWeight: 500,
                        cursor: 'pointer',
                      }}
                    >
                      Скачать
                    </button>
                  </div>
                </div>
              </md-elevated-card>
            );
          })}
          {/* Сентинель для подгрузки по скроллу */}
          {materialsHasMore && (
            <div
              ref={loadMoreSentinelRef}
              style={{
                gridColumn: '1 / -1',
                display: 'flex',
                justifyContent: 'center',
                padding: '24px 0',
                minHeight: 40,
              }}
            >
              {materialsLoadingMore && (
                <LoadingSpinner size="small" />
              )}
            </div>
          )}
        </div>
      )}

      {/* Модальное окно просмотра материала */}
      {previewMaterial && (
        <div
          style={{
            position: 'fixed',
            inset: 0,
            background: 'rgba(0, 0, 0, 0.8)',
            zIndex: 200,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            padding: 16,
          }}
          onClick={() => setPreviewMaterial(null)}
        >
          <div
            style={{
              background: 'var(--md-sys-color-surface)',
              borderRadius: 20,
              maxWidth: '90vw',
              maxHeight: '90vh',
              width: '100%',
              display: 'flex',
              flexDirection: 'column',
              overflow: 'hidden',
            }}
            onClick={(e) => e.stopPropagation()}
          >
            {/* Header */}
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                padding: '16px 20px',
                borderBottom: '1px solid var(--md-sys-color-outline-variant)',
              }}
            >
              <div style={{ flex: 1, minWidth: 0 }}>
                <h2 style={{ margin: 0, fontSize: 18, fontWeight: 600, color: 'var(--md-sys-color-on-surface)' }}>
                  {previewMaterial.title || 'Без названия'}
                </h2>
                {previewMaterial.description && (
                  <p style={{ margin: '4px 0 0', fontSize: 14, color: 'var(--md-sys-color-on-surface-variant)' }}>
                    {previewMaterial.description}
                  </p>
                )}
              </div>
              <button
                type="button"
                onClick={() => setPreviewMaterial(null)}
                style={{
                  background: 'none',
                  border: 'none',
                  padding: 8,
                  cursor: 'pointer',
                  color: 'var(--md-sys-color-on-surface-variant)',
                  marginLeft: 16,
                }}
              >
                <md-icon>close</md-icon>
              </button>
            </div>

            {/* Content — скролл и органы управления по умолчанию */}
            <div
              style={{
                flex: 1,
                display: 'flex',
                alignItems: 'stretch',
                justifyContent: 'stretch',
                padding: 20,
                overflow: 'auto',
                background: 'var(--md-sys-color-surface-container-low)',
                minHeight: 300,
              }}
            >
              {(() => {
                const url = previewMaterial.mediaUrl;
                const isImage = (previewMaterial.file_type || '').toLowerCase().startsWith('image/') ||
                  /\.(jpe?g|png|gif|webp|bmp|svg)(\?|$)/i.test((previewMaterial.file_name || previewMaterial.file || '').toLowerCase());
                const isVideo = (previewMaterial.file_type || '').toLowerCase().startsWith('video/') ||
                  /\.(mp4|webm|ogg|mov|avi|mkv)(\?|$)/i.test((previewMaterial.file_name || previewMaterial.file || '').toLowerCase());
                const isAudio = (previewMaterial.file_type || '').toLowerCase().startsWith('audio/') ||
                  /\.(mp3|wav|ogg|m4a|flac)(\?|$)/i.test((previewMaterial.file_name || previewMaterial.file || '').toLowerCase());
                const isPdf = isPdfMaterial(previewMaterial);
                const isText = isTextPreviewMaterial(previewMaterial);

                // Изображение
                if (url && isImage) {
                  return (
                    <img
                      src={url}
                      alt={previewMaterial.title}
                      style={{
                        maxWidth: '100%',
                        width: 'auto',
                        height: 'auto',
                        maxHeight: 'none',
                        objectFit: 'contain',
                        borderRadius: 12,
                        alignSelf: 'center',
                      }}
                    />
                  );
                }

                // Видео — с управлением по умолчанию
                if (url && isVideo) {
                  return (
                    <video
                      controls
                      autoPlay
                      src={url}
                      style={{
                        maxWidth: '100%',
                        maxHeight: '75vh',
                        width: 'auto',
                        borderRadius: 12,
                        alignSelf: 'center',
                      }}
                    >
                      Ваш браузер не поддерживает воспроизведение видео.
                    </video>
                  );
                }

                // Аудио
                if (url && isAudio) {
                  return (
                    <div style={{ width: '100%', maxWidth: 500, textAlign: 'center', alignSelf: 'center' }}>
                      <md-icon style={{ fontSize: 80, color: 'var(--md-sys-color-primary)', marginBottom: 20 }}>
                        audiotrack
                      </md-icon>
                      <audio
                        controls
                        autoPlay
                        src={url}
                        style={{ width: '100%' }}
                      >
                        Ваш браузер не поддерживает воспроизведение аудио.
                      </audio>
                    </div>
                  );
                }

                // PDF — iframe с содержимым, скролл и панель по умолчанию
                if (url && isPdf) {
                  return (
                    <iframe
                      src={url}
                      title={previewMaterial.title || 'PDF'}
                      style={{
                        width: '100%',
                        minHeight: '70vh',
                        border: 'none',
                        borderRadius: 12,
                        background: '#fff',
                        flex: 1,
                      }}
                    />
                  );
                }

                // Текстовые файлы — полное содержимое со скроллом
                if (url && isText) {
                  return (
                    <div style={{ width: '100%', overflow: 'auto', background: 'var(--md-sys-color-surface)', borderRadius: 12 }}>
                      <MaterialTextPreviewFull url={url} />
                    </div>
                  );
                }

                // Файлы, которые браузер не может отобразить (офис, архивы и т.д.) —
                // не открываем в iframe (это вызывает скачивание), а показываем сообщение
                if (url && cannotDisplayInBrowser(previewMaterial)) {
                  const fileName = (previewMaterial.file_name || previewMaterial.file || 'файл').split('/').pop() || 'файл';
                  return (
                    <div style={{
                      width: '100%',
                      flex: 1,
                      minHeight: 300,
                      display: 'flex',
                      flexDirection: 'column',
                      alignItems: 'center',
                      justifyContent: 'center',
                      textAlign: 'center',
                      color: 'var(--md-sys-color-on-surface)',
                      padding: 32,
                      background: 'var(--md-sys-color-surface-container-high)',
                      borderRadius: 16,
                    }}>
                      <span className="material-symbols-outlined" style={{ fontSize: 64, color: 'var(--md-sys-color-error)', marginBottom: 16 }}>error_outline</span>
                      <p style={{ fontSize: 18, fontWeight: 600, margin: '0 0 8px' }}>
                        Не удалось открыть {fileName}
                      </p>
                      <p style={{ fontSize: 14, color: 'var(--md-sys-color-on-surface-variant)', margin: 0 }}>
                        Этот формат нельзя просмотреть в браузере. Используйте кнопку «Скачать» ниже.
                      </p>
                    </div>
                  );
                }

                // Остальное — иконка и сообщение
                const fileName = (previewMaterial.file_name || previewMaterial.file || 'файл').split('/').pop() || 'файл';
                return (
                  <div style={{
                    width: '100%',
                    flex: 1,
                    minHeight: 300,
                    display: 'flex',
                    flexDirection: 'column',
                    alignItems: 'center',
                    justifyContent: 'center',
                    textAlign: 'center',
                    color: 'var(--md-sys-color-on-surface)',
                    padding: 32,
                    background: 'var(--md-sys-color-surface-container-high)',
                    borderRadius: 16,
                  }}>
                    <span className="material-symbols-outlined" style={{ fontSize: 64, color: 'var(--md-sys-color-error)', marginBottom: 16 }}>error_outline</span>
                    <p style={{ fontSize: 18, fontWeight: 600, margin: '0 0 8px' }}>
                      Не удалось открыть {fileName}
                    </p>
                    <p style={{ fontSize: 14, color: 'var(--md-sys-color-on-surface-variant)', margin: 0 }}>
                      Этот формат нельзя просмотреть в браузере. Используйте кнопку «Скачать» ниже.
                    </p>
                  </div>
                );
              })()}
            </div>

            {/* Footer */}
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                padding: '16px 20px',
                borderTop: '1px solid var(--md-sys-color-outline-variant)',
              }}
            >
              <div style={{ fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)' }}>
                {previewMaterial.file_name && (
                  <span style={{ marginRight: 16 }}>{previewMaterial.file_name}</span>
                )}
                {previewMaterial.file_size && (
                  <span>{(previewMaterial.file_size / (1024 * 1024)).toFixed(2)} МБ</span>
                )}
              </div>
              <div style={{ display: 'flex', gap: 8 }}>
                {previewMaterial.mediaUrl && (
                  <button
                    type="button"
                    onClick={() => {
                      const a = document.createElement('a');
                      a.href = previewMaterial.mediaUrl;
                      a.download = previewMaterial.file_name || previewMaterial.title || 'file';
                      a.click();
                    }}
                    style={{
                      padding: '10px 20px',
                      borderRadius: 12,
                      border: 'none',
                      background: 'var(--md-sys-color-primary)',
                      color: 'var(--md-sys-color-on-primary)',
                      fontSize: 14,
                      fontWeight: 500,
                      cursor: 'pointer',
                    }}
                  >
                    Скачать
                  </button>
                )}
                <button
                  type="button"
                  onClick={() => setPreviewMaterial(null)}
                  style={{
                    padding: '10px 20px',
                    borderRadius: 12,
                    border: '1px solid var(--md-sys-color-outline)',
                    background: 'transparent',
                    color: 'var(--md-sys-color-on-surface)',
                    fontSize: 14,
                    fontWeight: 500,
                    cursor: 'pointer',
                  }}
                >
                  Закрыть
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Sidebar для редактирования материала */}
      {editingMaterial && (
        <>
          {/* Overlay */}
          <div
            style={{
              position: 'fixed',
              inset: 0,
              background: 'rgba(0, 0, 0, 0.5)',
              zIndex: 100,
            }}
            onClick={() => !editLoading && setEditingMaterial(null)}
          />
          
          {/* Sidebar */}
          <div
            className="students-side-panel"
            style={{
              position: 'fixed',
              top: 0,
              right: 0,
              bottom: 0,
              width: '100%',
              maxWidth: 'min(400px, 100vw)',
              background: 'var(--md-sys-color-surface)',
              boxShadow: '-4px 0 20px rgba(0, 0, 0, 0.15)',
              zIndex: 101,
              display: 'flex',
              flexDirection: 'column',
              animation: 'slideInRight 0.3s ease',
            }}
          >
            {/* Header */}
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                padding: '16px 20px',
                borderBottom: '1px solid var(--md-sys-color-outline-variant)',
              }}
            >
              <h2 style={{ margin: 0, fontSize: 20, fontWeight: 600, color: 'var(--md-sys-color-on-surface)' }}>
                Редактировать
              </h2>
              <button
                type="button"
                onClick={() => !editLoading && setEditingMaterial(null)}
                style={{
                  background: 'none',
                  border: 'none',
                  padding: 8,
                  cursor: editLoading ? 'not-allowed' : 'pointer',
                  color: 'var(--md-sys-color-on-surface-variant)',
                  opacity: editLoading ? 0.5 : 1,
                }}
              >
                <md-icon>close</md-icon>
              </button>
            </div>

            {/* Form */}
            <form
              onSubmit={async (e) => {
                e.preventDefault();
                if (!editingMaterial) return;
                
                setEditLoading(true);
                setEditError(null);
                
                try {
                  const updatedMaterial = await updateMaterial(editingMaterial.id, {
                    title: editFormData.title,
                    description: editFormData.description,
                    file: editFile || undefined,
                  });
                  
                  // Синхронизируем список учеников с доступом
                  try {
                    await shareMaterial(editingMaterial.id, selectedStudentIds);
                  } catch (shareErr) {
                    console.error('Ошибка выдачи доступа:', shareErr);
                  }
                  
                  // Локально обновляем материал в списке без перезагрузки всей страницы
                  mutate((prev: any[]) =>
                    prev.map((m: any) =>
                      m.id === editingMaterial.id ? { ...m, ...updatedMaterial } : m
                    )
                  );
                  
                  setEditingMaterial(null);
                } catch (err: any) {
                  console.error('Ошибка обновления материала:', err);
                  setEditError(err.message || 'Не удалось обновить материал');
                } finally {
                  setEditLoading(false);
                }
              }}
              style={{
                flex: 1,
                display: 'flex',
                flexDirection: 'column',
                padding: '20px',
                gap: '16px',
                overflowY: 'auto',
              }}
            >
              {/* Название */}
              <div>
                <label
                  style={{
                    display: 'block',
                    marginBottom: 8,
                    fontSize: 14,
                    fontWeight: 500,
                    color: 'var(--md-sys-color-on-surface)',
                  }}
                >
                  Название *
                </label>
                <input
                  type="text"
                  required
                  value={editFormData.title}
                  onChange={(e) => setEditFormData({ ...editFormData, title: e.target.value })}
                  disabled={editLoading}
                  style={{
                    width: '100%',
                    padding: '12px 16px',
                    fontSize: 16,
                    border: '1px solid var(--md-sys-color-outline)',
                    borderRadius: 12,
                    background: 'var(--md-sys-color-surface)',
                    color: 'var(--md-sys-color-on-surface)',
                    outline: 'none',
                  }}
                  placeholder="Название материала"
                />
              </div>

              {/* Описание */}
              <div>
                <label
                  style={{
                    display: 'block',
                    marginBottom: 8,
                    fontSize: 14,
                    fontWeight: 500,
                    color: 'var(--md-sys-color-on-surface)',
                  }}
                >
                  Описание
                </label>
                <textarea
                  value={editFormData.description}
                  onChange={(e) => setEditFormData({ ...editFormData, description: e.target.value })}
                  disabled={editLoading}
                  rows={4}
                  style={{
                    width: '100%',
                    padding: '12px 16px',
                    fontSize: 16,
                    border: '1px solid var(--md-sys-color-outline)',
                    borderRadius: 12,
                    background: 'var(--md-sys-color-surface)',
                    color: 'var(--md-sys-color-on-surface)',
                    outline: 'none',
                    resize: 'vertical',
                  }}
                  placeholder="Описание материала..."
                />
              </div>

              {/* Новый файл */}
              <div>
                <label
                  style={{
                    display: 'block',
                    marginBottom: 8,
                    fontSize: 14,
                    fontWeight: 500,
                    color: 'var(--md-sys-color-on-surface)',
                  }}
                >
                  Новый файл (опционально)
                </label>
                <input
                  type="file"
                  id="edit-file-input"
                  onChange={(e) => {
                    const file = e.target.files?.[0];
                    if (file) {
                      const maxSize = 10 * 1024 * 1024; // 10 MB
                      if (file.size > maxSize) {
                        setEditError(`Файл слишком большой. Максимум 10 МБ.`);
                        return;
                      }
                      setEditFile(file);
                      setEditError(null);
                    }
                  }}
                  disabled={editLoading}
                  style={{ display: 'none' }}
                />
                <label
                  htmlFor="edit-file-input"
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    gap: 8,
                    padding: '12px 16px',
                    border: '1px dashed var(--md-sys-color-outline)',
                    borderRadius: 12,
                    cursor: editLoading ? 'not-allowed' : 'pointer',
                    color: 'var(--md-sys-color-on-surface-variant)',
                    fontSize: 14,
                    opacity: editLoading ? 0.5 : 1,
                  }}
                >
                  <md-icon>upload_file</md-icon>
                  {editFile ? editFile.name : 'Выбрать файл'}
                </label>
                {editingMaterial.file_name && !editFile && (
                  <p style={{ marginTop: 8, fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)' }}>
                    Текущий файл: {editingMaterial.file_name}
                  </p>
                )}
                {editFile && (
                  <p style={{ marginTop: 8, fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)' }}>
                    Размер: {(editFile.size / (1024 * 1024)).toFixed(2)} МБ
                  </p>
                )}
              </div>

              {/* Доступ для учеников */}
              <div>
                <label
                  style={{
                    display: 'block',
                    marginBottom: 8,
                    fontSize: 14,
                    fontWeight: 500,
                    color: 'var(--md-sys-color-on-surface)',
                  }}
                >
                  Ученики с доступом
                </label>
                {studentsLoading ? (
                  <div style={{ padding: '12px', color: 'var(--md-sys-color-on-surface-variant)', fontSize: 14 }}>
                    Загрузка списка учеников...
                  </div>
                ) : students.length === 0 ? (
                  <div style={{ padding: '12px', color: 'var(--md-sys-color-on-surface-variant)', fontSize: 14 }}>
                    У вас пока нет учеников
                  </div>
                ) : (
                  <div
                    style={{
                      border: '1px solid var(--md-sys-color-outline)',
                      borderRadius: 12,
                      overflow: 'hidden',
                    }}
                  >
                    {/* Поиск */}
                    <div style={{ padding: '8px 12px', borderBottom: '1px solid var(--md-sys-color-outline-variant)' }}>
                      <input
                        type="text"
                        value={studentSearch}
                        onChange={(e) => setStudentSearch(e.target.value)}
                        placeholder="Найти ученика..."
                        style={{
                          width: '100%',
                          padding: '8px 12px',
                          fontSize: 14,
                          border: '1px solid var(--md-sys-color-outline-variant)',
                          borderRadius: 8,
                          background: 'var(--md-sys-color-surface)',
                          color: 'var(--md-sys-color-on-surface)',
                          outline: 'none',
                        }}
                      />
                    </div>
                    {/* Список учеников */}
                    <div style={{ maxHeight: 200, overflowY: 'auto', padding: '8px 0' }}>
                      {students
                        .filter((student) => {
                          if (!studentSearch.trim()) return true;
                          const query = studentSearch.toLowerCase();
                          const fullName = `${student.user.first_name} ${student.user.last_name}`.toLowerCase();
                          const email = student.user.email.toLowerCase();
                          return fullName.includes(query) || email.includes(query);
                        })
                        .map((student) => {
                          const fullName = `${student.user.first_name} ${student.user.last_name}`.trim();
                          const id = String(student.user.id);
                          const checked = selectedStudentIds.includes(id);
                          return (
                            <label
                              key={student.id}
                              style={{
                                display: 'flex',
                                alignItems: 'center',
                                gap: 12,
                                padding: '8px 12px',
                                cursor: editLoading ? 'not-allowed' : 'pointer',
                                opacity: editLoading ? 0.5 : 1,
                              }}
                            >
                              <input
                                type="checkbox"
                                checked={checked}
                                disabled={editLoading}
                                onChange={(e) => {
                                  setSelectedStudentIds((prev) =>
                                    e.target.checked
                                      ? [...prev, id]
                                      : prev.filter((x) => x !== id)
                                  );
                                }}
                                style={{
                                  width: 18,
                                  height: 18,
                                  accentColor: 'var(--md-sys-color-primary)',
                                }}
                              />
                              <div style={{ flex: 1, minWidth: 0 }}>
                                <div style={{ fontSize: 14, color: 'var(--md-sys-color-on-surface)' }}>
                                  {fullName || student.user.email}
                                </div>
                                {fullName && (
                                  <div style={{ fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)' }}>
                                    {student.user.email}
                                  </div>
                                )}
                              </div>
                            </label>
                          );
                        })}
                    </div>
                  </div>
                )}
                {selectedStudentIds.length > 0 && (
                  <p style={{ marginTop: 8, fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)' }}>
                    Выбрано: {selectedStudentIds.length} {selectedStudentIds.length === 1 ? 'ученик' : selectedStudentIds.length < 5 ? 'ученика' : 'учеников'}
                  </p>
                )}
              </div>

              {/* Ошибка */}
              {editError && (
                <div
                  style={{
                    padding: '12px 16px',
                    background: 'var(--md-sys-color-error-container)',
                    color: 'var(--md-sys-color-on-error-container)',
                    borderRadius: 12,
                    fontSize: 14,
                  }}
                >
                  {editError}
                </div>
              )}

              {/* Spacer */}
              <div style={{ flex: 1 }} />

              {/* Кнопки */}
              <div style={{ display: 'flex', gap: 12 }}>
                <button
                  type="button"
                  onClick={() => !editLoading && setEditingMaterial(null)}
                  disabled={editLoading}
                  style={{
                    flex: 1,
                    padding: '14px 20px',
                    borderRadius: 12,
                    border: '1px solid var(--md-sys-color-outline)',
                    background: 'transparent',
                    color: 'var(--md-sys-color-on-surface)',
                    fontSize: 14,
                    fontWeight: 500,
                    cursor: editLoading ? 'not-allowed' : 'pointer',
                    opacity: editLoading ? 0.5 : 1,
                  }}
                >
                  Отмена
                </button>
                <button
                  type="submit"
                  disabled={editLoading}
                  style={{
                    flex: 1,
                    padding: '14px 20px',
                    borderRadius: 12,
                    border: 'none',
                    background: 'var(--md-sys-color-primary)',
                    color: 'var(--md-sys-color-on-primary)',
                    fontSize: 14,
                    fontWeight: 500,
                    cursor: editLoading ? 'not-allowed' : 'pointer',
                    opacity: editLoading ? 0.7 : 1,
                  }}
                >
                  {editLoading ? 'Сохранение...' : 'Сохранить'}
                </button>
              </div>
            </form>
          </div>

          {/* CSS анимация */}
          <style>{`
            @keyframes slideInRight {
              from {
                transform: translateX(100%);
              }
              to {
                transform: translateX(0);
              }
            }
          `}</style>
        </>
      )}

      {/* Панель «Добавить материал» — выдвижная справа */}
      {addPanelOpen && (
        <>
          <div
            role="presentation"
            onClick={closeAddPanel}
            style={{
              position: 'fixed',
              inset: 0,
              background: 'rgba(0,0,0,0.4)',
              zIndex: 9998,
              animation: 'fadeIn 0.2s ease-out',
            }}
          />
          <div
            className="students-side-panel"
            style={{
              position: 'fixed',
              top: 0,
              right: 0,
              bottom: 0,
              width: 'min(400px, 100vw)',
              background: 'var(--md-sys-color-surface)',
              boxShadow: '-4px 0 24px rgba(0,0,0,0.15)',
              zIndex: 9999,
              display: 'flex',
              flexDirection: 'column',
              animation: 'slideInRight 0.3s ease-out',
            }}
          >
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                padding: '16px 20px',
                borderBottom: '1px solid var(--md-sys-color-outline-variant)',
              }}
            >
              <h2 style={{ margin: 0, fontSize: 18, fontWeight: 600, color: 'var(--md-sys-color-on-surface)' }}>
                Добавить материал
              </h2>
              <button
                type="button"
                onClick={closeAddPanel}
                disabled={addLoading}
                aria-label="Закрыть"
                style={{
                  padding: 8,
                  border: 'none',
                  background: 'transparent',
                  color: 'var(--md-sys-color-on-surface-variant)',
                  cursor: addLoading ? 'not-allowed' : 'pointer',
                  borderRadius: 8,
                }}
              >
                <span className="material-symbols-outlined" style={{ fontSize: 24 }}>close</span>
              </button>
            </div>
            <form onSubmit={handleAddSubmit} style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0, overflow: 'hidden' }}>
              <div style={{ flex: 1, overflowY: 'auto', padding: '20px' }}>
                <div style={{ marginBottom: 16 }}>
                  <label htmlFor="add-title" style={{ display: 'block', fontSize: 14, fontWeight: 500, color: 'var(--md-sys-color-on-surface)', marginBottom: 6 }}>
                    Название *
                  </label>
                  <input
                    id="add-title"
                    type="text"
                    value={addTitle}
                    onChange={(e) => setAddTitle(e.target.value)}
                    placeholder="Название материала"
                    disabled={addLoading}
                    required
                    style={{
                      width: '100%',
                      padding: '12px 14px',
                      fontSize: 14,
                      border: '1px solid var(--md-sys-color-outline)',
                      borderRadius: 12,
                      background: 'var(--md-sys-color-surface)',
                      color: 'var(--md-sys-color-on-surface)',
                      outline: 'none',
                      boxSizing: 'border-box',
                    }}
                  />
                </div>
                <div style={{ marginBottom: 16 }}>
                  <label htmlFor="add-description" style={{ display: 'block', fontSize: 14, fontWeight: 500, color: 'var(--md-sys-color-on-surface)', marginBottom: 6 }}>
                    Описание
                  </label>
                  <textarea
                    id="add-description"
                    value={addDescription}
                    onChange={(e) => setAddDescription(e.target.value)}
                    placeholder="Описание материала..."
                    disabled={addLoading}
                    rows={3}
                    style={{
                      width: '100%',
                      padding: '12px 14px',
                      fontSize: 14,
                      border: '1px solid var(--md-sys-color-outline)',
                      borderRadius: 12,
                      background: 'var(--md-sys-color-surface)',
                      color: 'var(--md-sys-color-on-surface)',
                      outline: 'none',
                      boxSizing: 'border-box',
                      resize: 'vertical',
                    }}
                  />
                </div>
                <div style={{ marginBottom: 16 }}>
                  <label style={{ display: 'block', fontSize: 14, fontWeight: 500, color: 'var(--md-sys-color-on-surface)', marginBottom: 6 }}>
                    Файл (до 10 МБ) *
                  </label>
                  <input
                    id="add-file"
                    type="file"
                    onChange={(e) => setAddFile(e.target.files?.[0] ?? null)}
                    disabled={addLoading}
                    style={{ display: 'none' }}
                  />
                  <label
                    htmlFor="add-file"
                    style={{
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      gap: 8,
                      padding: '14px',
                      border: '1px dashed var(--md-sys-color-outline)',
                      borderRadius: 12,
                      background: 'var(--md-sys-color-surface-container-high)',
                      color: 'var(--md-sys-color-on-surface-variant)',
                      fontSize: 14,
                      cursor: addLoading ? 'not-allowed' : 'pointer',
                    }}
                  >
                    <span className="material-symbols-outlined" style={{ fontSize: 22 }}>upload_file</span>
                    {addFile ? addFile.name : 'Выберите файл'}
                  </label>
                  {addFile && (
                    <div
                      style={{
                        marginTop: 10,
                        borderRadius: 12,
                        overflow: 'hidden',
                        border: '1px solid var(--md-sys-color-outline-variant)',
                        background: 'var(--md-sys-color-surface-container-high)',
                      }}
                    >
                      {addFile.type.startsWith('image/') && addFilePreviewUrl ? (
                        <img
                          src={addFilePreviewUrl}
                          alt=""
                          style={{
                            display: 'block',
                            width: '100%',
                            maxHeight: 200,
                            objectFit: 'contain',
                            background: 'var(--md-sys-color-surface-container)',
                          }}
                        />
                      ) : (
                        <div
                          style={{
                            display: 'flex',
                            alignItems: 'center',
                            gap: 12,
                            padding: '14px 16px',
                          }}
                        >
                          <span
                            className="material-symbols-outlined"
                            style={{ fontSize: 40, color: 'var(--md-sys-color-primary)' }}
                          >
                            description
                          </span>
                          <div style={{ flex: 1, minWidth: 0 }}>
                            <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--md-sys-color-on-surface)' }}>
                              {addFile.name}
                            </div>
                            <div style={{ fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)', marginTop: 2 }}>
                              {addFile.size < 1024
                                ? `${addFile.size} Б`
                                : addFile.size < 1024 * 1024
                                  ? `${(addFile.size / 1024).toFixed(1)} КБ`
                                  : `${(addFile.size / (1024 * 1024)).toFixed(2)} МБ`}
                            </div>
                          </div>
                        </div>
                      )}
                    </div>
                  )}
                </div>
                <div style={{ marginBottom: 16 }} ref={addStudentSelectRef}>
                  <label style={{ display: 'block', fontSize: 14, fontWeight: 500, color: 'var(--md-sys-color-on-surface)', marginBottom: 6 }}>
                    Ученики, которым доступен материал
                  </label>
                  {!addStudentsLoaded ? (
                    <div style={{ fontSize: 13, color: 'var(--md-sys-color-on-surface-variant)', padding: '12px 0' }}>Загрузка...</div>
                  ) : addStudentsList.length === 0 ? (
                    <div style={{ fontSize: 13, color: 'var(--md-sys-color-on-surface-variant)', padding: '12px 0' }}>Нет учеников</div>
                  ) : (
                    <>
                      <button
                        type="button"
                        onClick={() => setAddStudentSelectOpen((o) => !o)}
                        disabled={addLoading}
                        style={{
                          width: '100%',
                          display: 'flex',
                          alignItems: 'center',
                          gap: 10,
                          padding: '12px 14px',
                          fontSize: 14,
                          textAlign: 'left',
                          border: '1px solid var(--md-sys-color-outline)',
                          borderRadius: 12,
                          background: 'var(--md-sys-color-surface-container-high)',
                          color: 'var(--md-sys-color-on-surface)',
                          cursor: addLoading ? 'not-allowed' : 'pointer',
                          boxSizing: 'border-box',
                          minHeight: 48,
                        }}
                      >
                        {addShareStudentIds.length > 0 ? (
                          <>
                            <div style={{ display: 'flex', alignItems: 'center', marginRight: 4 }}>
                              {addStudentsList
                                .filter((s) => addShareStudentIds.includes(String(s.user?.id ?? s.id)))
                                .slice(0, 4)
                                .map((s, idx) => {
                                  const id = String(s.user?.id ?? s.id);
                                  const avatarUrl = s.user?.avatar_url || s.user?.avatar || null;
                                  const name = `${s.user?.first_name || ''} ${s.user?.last_name || ''}`.trim() || s.user?.email || '';
                                  const initial = name ? name[0].toUpperCase() : '?';
                                  return (
                                    <div
                                      key={id}
                                      style={{
                                        width: 28,
                                        height: 28,
                                        borderRadius: '50%',
                                        overflow: 'hidden',
                                        marginLeft: idx === 0 ? 0 : -8,
                                        border: '2px solid var(--md-sys-color-surface-container-high)',
                                        background: 'var(--md-sys-color-primary-container)',
                                        color: 'var(--md-sys-color-on-primary-container)',
                                        fontSize: 12,
                                        fontWeight: 600,
                                        display: 'flex',
                                        alignItems: 'center',
                                        justifyContent: 'center',
                                        flexShrink: 0,
                                      }}
                                      title={name}
                                    >
                                      {avatarUrl ? (
                                        <img src={avatarUrl} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                                      ) : (
                                        initial
                                      )}
                                    </div>
                                  );
                                })}
                            </div>
                            <span style={{ color: 'var(--md-sys-color-on-surface-variant)', fontSize: 13 }}>
                              Выбрано: {addShareStudentIds.length}
                            </span>
                          </>
                        ) : (
                          <>
                            <span className="material-symbols-outlined" style={{ fontSize: 20, color: 'var(--md-sys-color-on-surface-variant)' }}>group</span>
                            <span style={{ color: 'var(--md-sys-color-on-surface-variant)' }}>Выбрать учеников</span>
                          </>
                        )}
                        <span
                          className="material-symbols-outlined"
                          style={{
                            marginLeft: 'auto',
                            fontSize: 20,
                            color: 'var(--md-sys-color-on-surface-variant)',
                            transform: addStudentSelectOpen ? 'rotate(180deg)' : 'none',
                            transition: 'transform 0.2s ease',
                          }}
                        >
                          expand_more
                        </span>
                      </button>
                      {addStudentSelectOpen && (
                        <div
                          style={{
                            marginTop: 6,
                            border: '1px solid var(--md-sys-color-outline-variant)',
                            borderRadius: 12,
                            overflow: 'hidden',
                            background: 'var(--md-sys-color-surface)',
                            boxShadow: '0 8px 24px rgba(0,0,0,0.12)',
                          }}
                        >
                          <div style={{ padding: 8, borderBottom: '1px solid var(--md-sys-color-outline-variant)', position: 'relative' }}>
                            <span
                              className="material-symbols-outlined"
                              style={{
                                position: 'absolute',
                                left: 20,
                                top: '50%',
                                transform: 'translateY(-50%)',
                                fontSize: 18,
                                color: 'var(--md-sys-color-on-surface-variant)',
                                pointerEvents: 'none',
                              }}
                            >
                              search
                            </span>
                            <input
                              type="text"
                              value={addStudentSearch}
                              onChange={(e) => setAddStudentSearch(e.target.value)}
                              placeholder="Поиск по имени или email..."
                              style={{
                                width: '100%',
                                padding: '10px 12px 10px 40px',
                                fontSize: 14,
                                border: '1px solid var(--md-sys-color-outline)',
                                borderRadius: 8,
                                background: 'var(--md-sys-color-surface-container-high)',
                                color: 'var(--md-sys-color-on-surface)',
                                outline: 'none',
                                boxSizing: 'border-box',
                              }}
                            />
                          </div>
                          <div style={{ maxHeight: 220, overflowY: 'auto', padding: 4 }}>
                            {addStudentsList
                              .filter((s) => {
                                if (!addStudentSearch.trim()) return true;
                                const q = addStudentSearch.toLowerCase();
                                const name = `${s.user?.first_name || ''} ${s.user?.last_name || ''}`.trim().toLowerCase();
                                const email = (s.user?.email || '').toLowerCase();
                                return name.includes(q) || email.includes(q);
                              })
                              .map((s) => {
                                const id = String(s.user?.id ?? s.id);
                                const name = `${s.user?.first_name || ''} ${s.user?.last_name || ''}`.trim() || s.user?.email || '';
                                const email = s.user?.email || '';
                                const avatarUrl = s.user?.avatar_url || s.user?.avatar || null;
                                const initial = name ? name[0].toUpperCase() : '?';
                                const checked = addShareStudentIds.includes(id);
                                return (
                                  <label
                                    key={id}
                                    style={{
                                      display: 'flex',
                                      alignItems: 'center',
                                      gap: 12,
                                      padding: '10px 12px',
                                      cursor: addLoading ? 'default' : 'pointer',
                                      borderRadius: 8,
                                      background: checked ? 'var(--md-sys-color-primary-container)' : 'transparent',
                                    }}
                                  >
                                    <div
                                      style={{
                                        width: 40,
                                        height: 40,
                                        borderRadius: '50%',
                                        overflow: 'hidden',
                                        flexShrink: 0,
                                        background: 'var(--md-sys-color-surface-container-high)',
                                        display: 'flex',
                                        alignItems: 'center',
                                        justifyContent: 'center',
                                        fontSize: 16,
                                        fontWeight: 600,
                                        color: 'var(--md-sys-color-on-surface-variant)',
                                      }}
                                    >
                                      {avatarUrl ? (
                                        <img src={avatarUrl} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                                      ) : (
                                        initial
                                      )}
                                    </div>
                                    <div style={{ flex: 1, minWidth: 0 }}>
                                      <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--md-sys-color-on-surface)' }}>{name}</div>
                                      {email && (
                                        <div style={{ fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)', marginTop: 2 }}>{email}</div>
                                      )}
                                    </div>
                                    <input
                                      type="checkbox"
                                      checked={checked}
                                      disabled={addLoading}
                                      onChange={(e) => {
                                        setAddShareStudentIds((prev) =>
                                          e.target.checked ? [...prev, id] : prev.filter((x) => x !== id)
                                        );
                                      }}
                                      style={{ width: 20, height: 20, accentColor: 'var(--md-sys-color-primary)', flexShrink: 0 }}
                                    />
                                  </label>
                                );
                              })}
                          </div>
                        </div>
                      )}
                    </>
                  )}
                </div>
                {addError && (
                  <div
                    style={{
                      padding: '12px 14px',
                      background: 'var(--md-sys-color-error-container)',
                      color: 'var(--md-sys-color-on-error-container)',
                      borderRadius: 12,
                      fontSize: 14,
                      marginBottom: 16,
                    }}
                  >
                    {addError}
                  </div>
                )}
              </div>
              <div style={{ padding: '16px 20px', borderTop: '1px solid var(--md-sys-color-outline-variant)', display: 'flex', gap: 12 }}>
                <button
                  type="button"
                  onClick={closeAddPanel}
                  disabled={addLoading}
                  style={{
                    padding: '12px 20px',
                    borderRadius: 12,
                    border: '1px solid var(--md-sys-color-outline)',
                    background: 'transparent',
                    color: 'var(--md-sys-color-on-surface)',
                    fontSize: 14,
                    fontWeight: 500,
                    cursor: addLoading ? 'not-allowed' : 'pointer',
                  }}
                >
                  Отмена
                </button>
                <button
                  type="submit"
                  disabled={addLoading}
                  style={{
                    flex: 1,
                    padding: '12px 20px',
                    borderRadius: 12,
                    border: 'none',
                    background: 'var(--md-sys-color-primary)',
                    color: 'var(--md-sys-color-on-primary)',
                    fontSize: 14,
                    fontWeight: 500,
                    cursor: addLoading ? 'not-allowed' : 'pointer',
                  }}
                >
                  {addLoading ? 'Загрузка...' : 'Загрузить'}
                </button>
              </div>
            </form>
          </div>
          <style>{`
            @keyframes fadeIn {
              from { opacity: 0; }
              to { opacity: 1; }
            }
            @keyframes slideInRight {
              from { transform: translateX(100%); }
              to { transform: translateX(0); }
            }
          `}</style>
        </>
      )}
    </div>
  );
}
