import 'dart:async';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:path/path.dart' as p;
import '../l10n/app_localizations.dart';
import '../models/document.dart';
import '../models/note.dart';
import '../providers/document_provider.dart';
import '../providers/note_provider.dart';
import '../providers/notebook_container_provider.dart';
import '../providers/ocr_provider.dart';
import '../providers/search_provider.dart';
import '../editor/canvas/pen_editor_screen.dart';
import '../editor/canvas/office_document_screen.dart';
import '../services/pptx_service.dart';
import '../services/vault_service.dart';
import '../editor/canvas/pen_note_screen.dart';
import '../editor/canvas/pen_slide_screen.dart';
import 'notebook_screen.dart';
import 'search_screen.dart';
import 'settings_screen.dart';

// Relative date helper — localized.
String _formatDate(BuildContext context, DateTime d) {
  final l = AppLocalizations.of(context);
  final now = DateTime.now();
  final diff = now.difference(d);
  if (diff.inSeconds < 60) return l.relativeJustNow;
  if (diff.inMinutes < 60) return l.relativeMinutesAgo(diff.inMinutes);
  if (diff.inHours < 24) return l.relativeHoursAgo(diff.inHours);
  if (diff.inDays == 1 || (diff.inDays == 0 && now.day != d.day)) {
    return l.relativeYesterday;
  }
  return '${d.month}/${d.day}/${d.year} ${d.hour}:${d.minute.toString().padLeft(2, '0')}';
}

class HomeScreen extends ConsumerWidget {
  const HomeScreen({super.key, this.embeddedInShell = false});

  /// When true, chrome (settings/search) is owned by [AppShell].
  final bool embeddedInShell;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final notesAsync = ref.watch(noteListProvider);
    final l = AppLocalizations.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(embeddedInShell ? l.libraryTab : l.appTitle),
        centerTitle: !embeddedInShell,
        actions: [
          if (!embeddedInShell) ...[
            IconButton(
              icon: const Icon(Icons.settings),
              tooltip: l.settings,
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(builder: (_) => const SettingsScreen()),
                );
              },
            ),
            IconButton(
              icon: const Icon(Icons.search),
              tooltip: l.search,
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(builder: (_) => const SearchScreen()),
                );
              },
            ),
          ],
          IconButton(
            icon: const Icon(Icons.file_open),
            tooltip: l.importFile,
            onPressed: () => _importFile(context, ref),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () => _createAndOpenNote(context, ref),
        icon: const Icon(Icons.add),
        label: Text(l.createNotebook),
      ),
      body: notesAsync.when(
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (e, _) => Center(child: Text('Error: $e')),
        data: (notes) {
          final documentsAsync = ref.watch(documentListProvider);
          final documents = documentsAsync.valueOrNull ?? [];
          final containersAsync = ref.watch(notebookContainerListProvider);
          final containers = containersAsync.valueOrNull ?? [];

          if (notes.isEmpty && documents.isEmpty && containers.isEmpty) {
            return _buildEmptyState(context, ref);
          }
          return RefreshIndicator(
            onRefresh: () async {
              await Future.wait([
                ref.read(noteListProvider.notifier).loadNotes(),
                ref.read(documentListProvider.notifier).loadDocuments(),
                ref
                    .read(notebookContainerListProvider.notifier)
                    .loadContainers(),
              ]);
            },
            child: CustomScrollView(
              slivers: [
                if (containers.isNotEmpty) ...[
                  SliverToBoxAdapter(
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
                      child: Text(
                        l.notebooksSection,
                        style: Theme.of(context).textTheme.titleMedium
                            ?.copyWith(fontWeight: FontWeight.bold),
                      ),
                    ),
                  ),
                  SliverList(
                    delegate: SliverChildBuilderDelegate(
                      (context, index) =>
                          _ContainerTile(container: containers[index]),
                      childCount: containers.length,
                    ),
                  ),
                ],
                SliverToBoxAdapter(
                  child: Padding(
                    padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
                    child: Text(
                      l.notesSection,
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                            fontWeight: FontWeight.bold,
                          ),
                    ),
                  ),
                ),
                if (notes.isNotEmpty)
                  SliverList(
                    delegate: SliverChildBuilderDelegate(
                      (context, index) => _NoteTile(note: notes[index]),
                      childCount: notes.length,
                    ),
                  )
                else
                  // [M2] Per-section empty hint when documents exist but notes don't
                  SliverToBoxAdapter(
                    child: Padding(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 16,
                        vertical: 12,
                      ),
                      child: Center(
                        child: Text(
                          l.noNotesYetHint,
                          style: Theme.of(context).textTheme.bodyMedium
                              ?.copyWith(
                                color: Theme.of(
                                  context,
                                ).colorScheme.onSurfaceVariant,
                              ),
                        ),
                      ),
                    ),
                  ),
                SliverToBoxAdapter(
                  child: Padding(
                    padding: const EdgeInsets.fromLTRB(16, 16, 16, 4),
                    child: Text(
                      l.documentsSection,
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                            fontWeight: FontWeight.bold,
                          ),
                    ),
                  ),
                ),
                if (documents.isNotEmpty)
                  // continue existing document list below — marker for patch
                  SliverList(
                    delegate: SliverChildBuilderDelegate(
                      (context, index) =>
                          _DocumentTile(document: documents[index]),
                      childCount: documents.length,
                    ),
                  )
                else
                  SliverToBoxAdapter(
                    child: Padding(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 16,
                        vertical: 12,
                      ),
                      child: Center(
                        child: Text(
                          l.noDocumentsYet,
                          style: Theme.of(context).textTheme.bodyMedium
                              ?.copyWith(
                                color: Theme.of(
                                  context,
                                ).colorScheme.onSurfaceVariant,
                              ),
                        ),
                      ),
                    ),
                  ),
                const SliverToBoxAdapter(child: SizedBox(height: 80)),
              ],
            ),
          );
        },
      ),
    );
  }

  /// "Create notebook" (OneNote style): prompt a title (defaulting to
  /// Untitled), create the notebook container FOLDER + `notebook.json` (with
  /// one blank ink page) via `VaultService.createNotebookContainer`, then open
  /// [NotebookScreen] on it.
  Future<void> _createAndOpenNote(BuildContext context, WidgetRef ref) async {
    final title = await _promptNotebookTitle(context);
    if (title == null) return; // cancelled
    final l = context.mounted ? AppLocalizations.of(context) : null;
    final resolved = title.trim().isEmpty
        ? (l?.untitledNote ?? 'Untitled')
        : title.trim();
    final container = await ref
        .read(notebookContainerListProvider.notifier)
        .createContainer(resolved);
    if (context.mounted) {
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (_) => NotebookScreen(
            folderPath: container.folderPath,
            title: container.title,
          ),
        ),
      );
    }
  }

  /// Ask for a notebook title. Returns the entered string (possibly empty →
  /// caller defaults it), or null if the user cancelled.
  Future<String?> _promptNotebookTitle(BuildContext context) {
    final l = AppLocalizations.of(context);
    final controller = TextEditingController(text: l.untitledNote);
    return showDialog<String>(
      context: context,
      builder: (ctx) => AlertDialog(
        title: Text(l.newNotebookTitle),
        content: TextField(
          controller: controller,
          autofocus: true,
          decoration: InputDecoration(hintText: l.notebookTitleHint),
          onSubmitted: (v) => Navigator.of(ctx).pop(v),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(),
            child: Text(l.cancel),
          ),
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(controller.text),
            child: Text(l.create),
          ),
        ],
      ),
    );
  }

  /// Single top-level "Import file" action (sibling of "Create notebook"):
  /// pick a pdf/docx/pptx/ppt, copy it into a new vault notebook folder, then
  /// open the IN-VAULT copy in the right editor (routed by extension).
  Future<void> _importFile(BuildContext context, WidgetRef ref) async {
    final l = AppLocalizations.of(context);
    final result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: VaultService.importableExtensions.toList(),
    );
    final picked = result?.files;
    if (picked == null || picked.isEmpty) return;
    final pickedPath = picked.first.path;
    if (pickedPath == null) return;

    final messenger = context.mounted ? ScaffoldMessenger.of(context) : null;
    messenger?.showSnackBar(SnackBar(content: Text(l.processingImport)));

    try {
      final vault = await ref.read(vaultServiceProvider.future);
      final vaultPath = await vault.createNotebook(pickedPath);
      // Refresh the documents list so the new notebook shows on return.
      await ref.read(documentListProvider.notifier).loadDocuments();
      // For a PDF, index its document body (embedded text layer, or background
      // OCR of a rasterized/scanned PDF) into the sidecar so search covers it.
      // Fire-and-forget: import returns and opens the editor immediately.
      _indexPdfInBackground(ref, vaultPath);
      if (!context.mounted) return;
      await _openVaultFile(context, ref, vaultPath);
    } catch (e) {
      messenger?.showSnackBar(SnackBar(content: Text(l.importFailed('$e'))));
    }
  }

  /// Kick off background document-body indexing for an in-vault PDF (no-op for
  /// other types). Runs detached from the import await chain so the editor opens
  /// immediately; on completion it bumps the search-index epoch so the newly
  /// indexed text is searchable. Idempotency and graceful OCR degradation live in
  /// [PdfTextIndexer]; failures here are swallowed (search just misses the body).
  void _indexPdfInBackground(WidgetRef ref, String vaultPath) {
    final ext = p.extension(vaultPath).replaceFirst('.', '').toLowerCase();
    if (ext != 'pdf') return;
    final indexer = ref.read(pdfTextIndexerProvider);
    unawaited(() async {
      final indexed = await indexer.indexPdf(vaultPath);
      if (indexed != null && indexed.isNotEmpty) {
        // Force the next search to re-scan the vault (picks up the new pageText).
        final epoch = ref.read(searchIndexEpochProvider.notifier);
        epoch.state = epoch.state + 1;
      }
    }());
  }

  /// Route an in-vault [filePath] to the correct editor by extension:
  /// pdf → [PenEditorScreen]; pptx/docx → native [OfficeDocumentScreen];
  /// legacy .ppt may still use image fallback.
  Future<void> _openVaultFile(
    BuildContext context,
    WidgetRef ref,
    String filePath,
  ) async {
    final l = AppLocalizations.of(context);
    final ext = p.extension(filePath).replaceFirst('.', '').toLowerCase();

    switch (ext) {
      case 'pdf':
        Navigator.of(context).push(
          MaterialPageRoute(
            builder: (_) => PenEditorScreen(pdfPath: filePath),
          ),
        );
      case 'pptx':
      case 'docx':
        Navigator.of(context).push(
          MaterialPageRoute(
            builder: (_) => OfficeDocumentScreen(filePath: filePath),
          ),
        );
      case 'ppt':
        // Legacy binary PPT — try native-ish image path for now.
        await _openPresentation(context, filePath);
      default:
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(l.unsupportedFileType(ext))),
        );
    }
  }

  Future<void> _openPresentation(
    BuildContext context,
    String filePath,
  ) async {
    final l = AppLocalizations.of(context);
    final pptxService = PptxService();
    if (context.mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(l.processingPresentation)),
      );
    }
    final slideImages = await pptxService.convertToImages(filePath);
    final extractedText = await pptxService.extractText(filePath);
    if (!context.mounted) return;
    if (slideImages.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(l.couldNotOpenPresentation)),
      );
      return;
    }
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (_) => PenSlideScreen(
          filePath: filePath,
          slideImagePaths: slideImages,
          extractedText: extractedText.isEmpty ? null : extractedText,
        ),
      ),
    );
  }

  Widget _buildEmptyState(BuildContext context, WidgetRef ref) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            Icons.edit_note,
            size: 80,
            color: Theme.of(context).colorScheme.primary,
          ),
          const SizedBox(height: 24),
          Text(
            AppLocalizations.of(context).emptyLibraryTitle,
            style: Theme.of(
              context,
            ).textTheme.headlineSmall?.copyWith(fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 8),
          Text(
            AppLocalizations.of(context).emptyLibraryBody,
            style: Theme.of(context).textTheme.bodyLarge?.copyWith(
              color: Theme.of(context).colorScheme.onSurfaceVariant,
            ),
          ),
          const SizedBox(height: 32),
          FilledButton.icon(
            onPressed: () => _createAndOpenNote(context, ref),
            icon: const Icon(Icons.add),
            label: Text(AppLocalizations.of(context).createNotebook),
          ),
          const SizedBox(height: 12),
          OutlinedButton.icon(
            onPressed: () => _importFile(context, ref),
            icon: const Icon(Icons.file_open),
            label: Text(AppLocalizations.of(context).importFile),
          ),
        ],
      ),
    );
  }
}

/// Simple tile for a OneNote-style notebook container on the home screen.
/// Tapping opens [NotebookScreen] on the container's folder.
class _ContainerTile extends StatelessWidget {
  const _ContainerTile({required this.container});

  final VaultContainer container;

  @override
  Widget build(BuildContext context) {
    final l = AppLocalizations.of(context);
    final dateStr = _formatDate(context, container.modified);
    return ListTile(
      leading: Icon(
        Icons.menu_book,
        color: Theme.of(context).colorScheme.primary,
      ),
      title: Text(
        container.title,
        maxLines: 1,
        overflow: TextOverflow.ellipsis,
      ),
      subtitle: Text(
        '${l.memberCount(container.memberCount)} · $dateStr',
        style: Theme.of(context).textTheme.bodySmall,
      ),
      onTap: () {
        Navigator.of(context).push(
          MaterialPageRoute(
            builder: (_) => NotebookScreen(
              folderPath: container.folderPath,
              title: container.title,
            ),
          ),
        );
      },
    );
  }
}

class _NoteTile extends ConsumerStatefulWidget {
  final Note note;
  const _NoteTile({required this.note});

  @override
  ConsumerState<_NoteTile> createState() => _NoteTileState();
}

class _NoteTileState extends ConsumerState<_NoteTile> {
  bool _hovering = false;

  @override
  Widget build(BuildContext context) {
    final note = widget.note;
    // [M1] Use relative date helper
    final dateStr = _formatDate(context, note.updatedAt);

    final ocrStatusMap = ref.watch(ocrStatusProvider);
    final ocrStatus = ocrStatusMap[note.id] ?? OcrStatus.none;

    final subtleColor = Theme.of(context).colorScheme.onSurfaceVariant;

    // [H2] Right-click context menu via GestureDetector + MouseRegion for hover
    return GestureDetector(
      onSecondaryTapDown: (details) =>
          _showContextMenu(context, details.globalPosition),
      child: MouseRegion(
        onEnter: (_) => setState(() => _hovering = true),
        onExit: (_) => setState(() => _hovering = false),
        child: ListTile(
          title: Row(
            children: [
              Expanded(
                child: Text(
                  note.title.isEmpty ? 'Untitled' : note.title,
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ),
              _OcrStatusBadge(status: ocrStatus),
            ],
          ),
          subtitle: Padding(
            padding: const EdgeInsets.only(top: 4),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // Stroke count is no longer cached in the vault scan (strokes
                // load lazily in the editor), so the tile shows only the date.
                Text(
                  dateStr,
                  style: Theme.of(context).textTheme.bodySmall,
                ),
                if (note.tags.isNotEmpty)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Wrap(
                      spacing: 4,
                      children: note.tags
                          .map(
                            (t) => Chip(
                              label: Text(
                                t,
                                style: const TextStyle(fontSize: 11),
                              ),
                              visualDensity: VisualDensity.compact,
                              padding: EdgeInsets.zero,
                              materialTapTargetSize:
                                  MaterialTapTargetSize.shrinkWrap,
                            ),
                          )
                          .toList(),
                    ),
                  ),
              ],
            ),
          ),
          // [H2] Trailing delete button — always visible with subdued color, brighter on hover
          trailing: IconButton(
            icon: Icon(
              Icons.delete_outline,
              color: _hovering
                  ? Theme.of(context).colorScheme.error
                  : subtleColor.withValues(alpha: 0.4),
            ),
            tooltip: 'Delete note',
            onPressed: () => _confirmDelete(context),
          ),
          onTap: () {
            Navigator.of(context).push(
              MaterialPageRoute(builder: (_) => PenNoteScreen(note: note)),
            );
          },
          onLongPress: () => _confirmDelete(context),
        ),
      ),
    );
  }

  void _showContextMenu(BuildContext context, Offset position) async {
    final result = await showMenu<String>(
      context: context,
      position: RelativeRect.fromLTRB(
        position.dx,
        position.dy,
        position.dx + 1,
        position.dy + 1,
      ),
      items: [
        PopupMenuItem(
          value: 'open',
          child: Row(
            children: const [
              Icon(Icons.edit_outlined),
              SizedBox(width: 8),
              Text('Open'),
            ],
          ),
        ),
        PopupMenuItem(
          value: 'delete',
          child: Row(
            children: [
              Icon(
                Icons.delete_outline,
                color: Theme.of(context).colorScheme.error,
              ),
              const SizedBox(width: 8),
              Text(
                'Delete',
                style: TextStyle(color: Theme.of(context).colorScheme.error),
              ),
            ],
          ),
        ),
      ],
    );
    if (!mounted) return;
    if (result == 'open') {
      Navigator.of(this.context).push(
        MaterialPageRoute(builder: (_) => PenNoteScreen(note: widget.note)),
      );
    } else if (result == 'delete') {
      _confirmDelete(this.context);
    }
  }

  void _confirmDelete(BuildContext context) {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Delete note?'),
        content: Text(
          'Delete "${widget.note.title.isEmpty ? 'Untitled' : widget.note.title}"?',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(ctx),
            child: const Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              ref.read(noteListProvider.notifier).deleteNote(widget.note.id);
              Navigator.pop(ctx);
            },
            child: const Text('Delete'),
          ),
        ],
      ),
    );
  }
}

class _DocumentTile extends ConsumerStatefulWidget {
  final Document document;
  const _DocumentTile({required this.document});

  @override
  ConsumerState<_DocumentTile> createState() => _DocumentTileState();
}

class _DocumentTileState extends ConsumerState<_DocumentTile> {
  bool _hovering = false;

  @override
  Widget build(BuildContext context) {
    final document = widget.document;
    // [M1] Use relative date helper
    final dateStr = _formatDate(context, document.updatedAt);
    final isPdf = document.docType == 'pdf';

    final subtleColor = Theme.of(context).colorScheme.onSurfaceVariant;

    // [H2] Right-click context menu + MouseRegion + trailing action buttons
    return GestureDetector(
      onSecondaryTapDown: (details) =>
          _showContextMenu(context, details.globalPosition),
      child: MouseRegion(
        onEnter: (_) => setState(() => _hovering = true),
        onExit: (_) => setState(() => _hovering = false),
        child: ListTile(
          leading: Icon(
            isPdf ? Icons.picture_as_pdf : Icons.slideshow,
            color: isPdf ? Colors.red : Colors.orange,
          ),
          title: Text(
            document.filename,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
          subtitle: Text(
            '${document.docType.toUpperCase()} · ${document.pageCount} pages · $dateStr',
            style: Theme.of(context).textTheme.bodySmall,
          ),
          // [H2] Trailing remove button. Split view is now reached only by
          // tapping a scratch-link anchor inside the PDF editor, so the
          // standalone split-view entry was removed.
          trailing: IconButton(
            icon: Icon(
              Icons.delete_outline,
              color: _hovering
                  ? Theme.of(context).colorScheme.error
                  : subtleColor.withValues(alpha: 0.4),
            ),
            tooltip: 'Remove document',
            onPressed: () => _confirmDelete(context),
          ),
          // [L2] Routing bug fix: route by docType
          onTap: () => _openDocument(context),
          onLongPress: () => _showDocumentMenu(context),
        ),
      ),
    );
  }

  // Route by docType: pdf → PenEditorScreen; pptx/docx → native OfficeDocumentScreen.
  Future<void> _openDocument(BuildContext context) async {
    final document = widget.document;
    final l = AppLocalizations.of(context);

    if (document.docType == 'pdf') {
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (_) => PenEditorScreen(pdfPath: document.filePath),
        ),
      );
      return;
    }

    if (document.docType == 'docx' || document.docType == 'pptx') {
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (_) => OfficeDocumentScreen(filePath: document.filePath),
        ),
      );
      return;
    }

    {
      // Legacy .ppt: convert to images then push PenSlideScreen
      if (mounted) {
        ScaffoldMessenger.of(this.context).showSnackBar(
          SnackBar(content: Text(l.processingPresentation)),
        );
      }
      final pptxService = PptxService();
      final slideImages = await pptxService.convertToImages(document.filePath);
      final extractedText = await pptxService.extractText(document.filePath);
      if (!mounted) return;
      if (slideImages.isEmpty) {
        ScaffoldMessenger.of(this.context).showSnackBar(
          SnackBar(content: Text(l.couldNotOpenPresentation)),
        );
        return;
      }
      Navigator.of(this.context).push(
        MaterialPageRoute(
          builder: (_) => PenSlideScreen(
            filePath: document.filePath,
            slideImagePaths: slideImages,
            extractedText: extractedText.isEmpty ? null : extractedText,
          ),
        ),
      );
    }
  }

  void _showContextMenu(BuildContext context, Offset position) async {
    final result = await showMenu<String>(
      context: context,
      position: RelativeRect.fromLTRB(
        position.dx,
        position.dy,
        position.dx + 1,
        position.dy + 1,
      ),
      items: [
        PopupMenuItem(
          value: 'open',
          child: Row(
            children: const [
              Icon(Icons.open_in_new),
              SizedBox(width: 8),
              Text('Open'),
            ],
          ),
        ),
        PopupMenuItem(
          value: 'remove',
          child: Row(
            children: [
              Icon(
                Icons.delete_outline,
                color: Theme.of(context).colorScheme.error,
              ),
              const SizedBox(width: 8),
              Text(
                'Remove',
                style: TextStyle(color: Theme.of(context).colorScheme.error),
              ),
            ],
          ),
        ),
      ],
    );
    if (!mounted) return;
    if (result == 'open') {
      _openDocument(this.context);
    } else if (result == 'remove') {
      _confirmDelete(this.context);
    }
  }

  void _showDocumentMenu(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (ctx) {
        return SafeArea(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              ListTile(
                leading: const Icon(Icons.delete_outline, color: Colors.red),
                title: const Text(
                  'Remove document',
                  style: TextStyle(color: Colors.red),
                ),
                onTap: () {
                  Navigator.of(ctx).pop();
                  _confirmDelete(context);
                },
              ),
            ],
          ),
        );
      },
    );
  }

  void _confirmDelete(BuildContext context) {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Remove document?'),
        content: Text(
          'Remove "${widget.document.filename}" from recent documents?',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(ctx),
            child: const Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              ref
                  .read(documentListProvider.notifier)
                  .removeDocument(widget.document.id);
              Navigator.pop(ctx);
            },
            child: const Text('Remove'),
          ),
        ],
      ),
    );
  }
}

// [M3] OCR status badge with semantic theme colors and tooltips
class _OcrStatusBadge extends StatelessWidget {
  final OcrStatus status;
  const _OcrStatusBadge({required this.status});

  @override
  Widget build(BuildContext context) {
    switch (status) {
      case OcrStatus.none:
        return const SizedBox.shrink();
      case OcrStatus.processing:
        return Tooltip(
          message: 'Processing OCR…',
          child: const SizedBox(
            width: 16,
            height: 16,
            child: CircularProgressIndicator(strokeWidth: 1.5),
          ),
        );
      case OcrStatus.done:
        return Tooltip(
          message: 'OCR complete',
          child: Icon(
            Icons.check_circle,
            size: 16,
            color: Theme.of(context).colorScheme.primary,
          ),
        );
      case OcrStatus.failed:
        return Tooltip(
          message: 'OCR failed',
          child: Icon(
            Icons.error_outline,
            size: 16,
            color: Theme.of(context).colorScheme.error,
          ),
        );
    }
  }
}
