import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:image_picker/image_picker.dart';

import 'package:hl_lieferservice/domain/entity/delivery.dart';
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
import 'package:hl_lieferservice/widget/attachment_image.dart';

/// Step 2 — Notizen & Fotos.
///
/// Die UI trennt bewusst in **zwei Sektionen**, weil es zwei
/// unterschiedliche Dinge sind:
/// * **Notizen** (Text): anlegen / bearbeiten / löschen über den
///   `TourBloc` (Backend-Endpoints vorhanden).
/// * **Fotos** (Bild-Notizen): `image_picker` → Upload über
///   `TourBloc.UploadDeliveryNoteImage`. Das Backend schiebt das Bild nach
///   DOCUframe und legt eine Notiz mit der Referenz an. Fotos werden als
///   Thumbnail angezeigt (Tap → formatfüllend) und können nur gelöscht,
///   nicht inline bearbeitet werden.
///
/// Datenmodell: beides sind `DeliveryNote`s. Unterschieden wird über
/// `imageAttachment != null` (Foto) bzw. `text != null` (Notiz).
class StepNotes extends StatelessWidget {
  const StepNotes({super.key, required this.delivery, required this.details});

  final Delivery delivery;
  final TourDetails details;

  void _openAddNoteDialog(BuildContext context) {
    final tourBloc = context.read<TourBloc>();
    showDialog<void>(
      context: context,
      builder: (_) => _NoteEditorDialog(
        title: 'Notiz hinzufügen',
        onSubmit: (text) => tourBloc.add(
          AddDeliveryNote(deliveryId: delivery.id, text: text),
        ),
      ),
    );
  }

  Future<void> _pickImage(BuildContext context) async {
    // Bloc vor dem await greifen — danach kein context-Zugriff über den
    // async-Gap.
    final tourBloc = context.read<TourBloc>();
    final picker = ImagePicker();
    // Bild schon on-device runterskalieren + JPEG-komprimieren: Foto-Notizen
    // brauchen keine 12-MP-Originale. Spart Upload-/Speicher-/Report-Größe
    // (ein 4080×3060-Foto ~2,9 MB → ~200–400 KB). 1600 px / Q82 deckt sich mit
    // dem Backend-Report-Renderer.
    final file = await picker.pickImage(
      source: ImageSource.camera,
      maxWidth: 1600,
      maxHeight: 1600,
      imageQuality: 82,
    );
    if (file == null) return;
    final bytes = await file.readAsBytes();
    tourBloc.add(
      UploadDeliveryNoteImage(
        deliveryId: delivery.id,
        filename: file.name,
        mime: file.mimeType ?? _mimeFromName(file.name),
        bytes: bytes,
      ),
    );
  }

  /// Grober MIME-Fallback, wenn der Picker keinen Typ liefert (Kamera gibt
  /// meist JPEG). Reicht für das `Content-Type` des Multipart-Felds.
  String _mimeFromName(String name) {
    final lower = name.toLowerCase();
    if (lower.endsWith('.png')) return 'image/png';
    if (lower.endsWith('.heic')) return 'image/heic';
    if (lower.endsWith('.webp')) return 'image/webp';
    return 'image/jpeg';
  }

  @override
  Widget build(BuildContext context) {
    final notes = details.notesOf(delivery.id);
    // Notizen & Fotos sind nur bei aktiver Lieferung änderbar. Ist die
    // Lieferung beendet (abgeschlossen/abgebrochen/pausiert), bleiben sie
    // sichtbar, aber read-only: kein FAB, keine Aktions-Menüs, kein Löschen.
    final active = delivery.state == DeliveryState.active;
    // Sauber in Text-Notizen und Fotos aufteilen — getrennte Sektionen.
    final textNotes =
        notes.where((n) => n.imageAttachment == null).toList(growable: false);
    final photoNotes =
        notes.where((n) => n.imageAttachment != null).toList(growable: false);
    return Stack(
      children: [
        ListView(
          padding: const EdgeInsets.fromLTRB(16, 16, 16, 100),
          children: [
            if (!active) ...[
              const _ReadOnlyBanner(),
              const SizedBox(height: 16),
            ],
            _SectionHeader(text: 'Notizen (${textNotes.length})'),
            const SizedBox(height: 8),
            if (textNotes.isEmpty)
              const _EmptyHint(
                icon: Icons.notes,
                text: 'Noch keine Notizen erfasst.',
              )
            else
              for (final n in textNotes)
                _NoteCard(note: n, deliveryId: delivery.id, active: active),
            const SizedBox(height: 24),
            _SectionHeader(text: 'Fotos (${photoNotes.length})'),
            const SizedBox(height: 8),
            if (photoNotes.isEmpty)
              const _EmptyHint(
                icon: Icons.photo_camera_outlined,
                text: 'Noch keine Fotos aufgenommen.',
              )
            else
              for (final n in photoNotes)
                _PhotoCard(note: n, deliveryId: delivery.id, active: active),
          ],
        ),
        // FAB nur bei aktiver Lieferung — sonst ist Hinzufügen gesperrt.
        if (active)
          Align(
            alignment: Alignment.bottomRight,
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: _AddMenu(
                onAddNote: () => _openAddNoteDialog(context),
                onAddImage: () => _pickImage(context),
              ),
            ),
          ),
      ],
    );
  }
}

/// Hinweis-Balken oben in der Notiz-Sektion, wenn die Lieferung nicht mehr
/// aktiv ist — Notizen/Fotos sind dann reine Anzeige.
class _ReadOnlyBanner extends StatelessWidget {
  const _ReadOnlyBanner();

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
      decoration: BoxDecoration(
        color: theme.colorScheme.surfaceContainerHighest,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Row(
        children: [
          Icon(Icons.lock_outline,
              size: 18, color: theme.colorScheme.onSurfaceVariant),
          const SizedBox(width: 8),
          Expanded(
            child: Text(
              'Lieferung beendet — Notizen & Fotos können nicht mehr '
              'hinzugefügt, geändert oder gelöscht werden.',
              style: theme.textTheme.bodySmall?.copyWith(
                color: theme.colorScheme.onSurfaceVariant,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _SectionHeader extends StatelessWidget {
  const _SectionHeader({required this.text});
  final String text;

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: Theme.of(context).textTheme.titleMedium?.copyWith(
            fontWeight: FontWeight.w700,
          ),
    );
  }
}

class _EmptyHint extends StatelessWidget {
  const _EmptyHint({required this.icon, required this.text});
  final IconData icon;
  final String text;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Card(
      margin: EdgeInsets.zero,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          children: [
            Icon(icon, color: theme.colorScheme.onSurfaceVariant),
            const SizedBox(width: 12),
            Text(
              text,
              style: TextStyle(
                color: theme.colorScheme.onSurfaceVariant,
                fontStyle: FontStyle.italic,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

enum _NoteAction { edit, delete }

/// Geteiltes Zeitformat für Notiz- und Foto-Karten.
String _formatNoteTime(DateTime t) =>
    '${t.day.toString().padLeft(2, "0")}.${t.month.toString().padLeft(2, "0")}.${t.year} '
    '${t.hour.toString().padLeft(2, "0")}:${t.minute.toString().padLeft(2, "0")}';

/// Geteilter Lösch-Bestätigungsdialog. Wording variiert je nachdem, ob eine
/// Text-Notiz oder ein Foto entfernt wird; gefeuert wird in beiden Fällen
/// dasselbe `DeleteDeliveryNote`-Event (Foto ist intern auch eine Notiz).
Future<void> _confirmDeleteNote(
  BuildContext context, {
  required String deliveryId,
  required String noteId,
  required bool isPhoto,
}) async {
  final tourBloc = context.read<TourBloc>();
  final confirmed = await showDialog<bool>(
    context: context,
    builder: (ctx) => AlertDialog(
      title: Text(isPhoto ? 'Foto löschen?' : 'Notiz löschen?'),
      content: Text(
        isPhoto
            ? 'Das Foto wird dauerhaft entfernt.'
            : 'Die Notiz wird dauerhaft entfernt.',
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(ctx).pop(false),
          child: const Text('Abbrechen'),
        ),
        FilledButton(
          style: FilledButton.styleFrom(
            backgroundColor: Theme.of(ctx).colorScheme.error,
            foregroundColor: Theme.of(ctx).colorScheme.onError,
          ),
          onPressed: () => Navigator.of(ctx).pop(true),
          child: const Text('Löschen'),
        ),
      ],
    ),
  );
  if (confirmed != true) return;
  tourBloc.add(DeleteDeliveryNote(deliveryId: deliveryId, noteId: noteId));
}

/// Karte einer **Text-Notiz**. Normale Notizen sind bearbeitbar und löschbar.
/// **System-verwaltete** Grund-Notizen (Mengen-Gutschrift via
/// `creditDeliveryItemId` oder Betrags-Gutschrift via `isAmountCreditNote`)
/// dürfen vom Fahrer nicht manuell geändert/gelöscht werden — sie werden
/// automatisch mit der jeweiligen Gutschrift angelegt und wieder entfernt.
class _NoteCard extends StatelessWidget {
  const _NoteCard({
    required this.note,
    required this.deliveryId,
    required this.active,
  });
  final DeliveryNote note;
  final String deliveryId;

  /// Nur bei aktiver Lieferung darf bearbeitet/gelöscht werden.
  final bool active;

  void _openEditDialog(BuildContext context) {
    final tourBloc = context.read<TourBloc>();
    showDialog<void>(
      context: context,
      builder: (_) => _NoteEditorDialog(
        title: 'Notiz bearbeiten',
        initialText: note.text,
        onSubmit: (text) => tourBloc.add(
          UpdateDeliveryNote(
            deliveryId: deliveryId,
            noteId: note.id,
            text: text,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    // System-verwaltete Grund-Notiz: kein manuelles Bearbeiten/Löschen.
    final isSystemManaged =
        note.creditDeliveryItemId != null || note.isAmountCreditNote;
    // Aktions-Menü nur bei aktiver Lieferung UND nicht-System-Notiz.
    final canEdit = active && !isSystemManaged;
    return Card(
      margin: const EdgeInsets.only(bottom: 8),
      child: Padding(
        padding: const EdgeInsets.fromLTRB(12, 12, 4, 12),
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: Padding(
                padding: const EdgeInsets.only(top: 4),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      note.text ?? '',
                      style: const TextStyle(fontSize: 14),
                    ),
                    const SizedBox(height: 6),
                    Text(
                      'Personalnr. ${note.authorPersonalnummer} '
                      '· ${_formatNoteTime(note.createdAt)}',
                      style: TextStyle(
                        fontSize: 11,
                        color: theme.colorScheme.onSurfaceVariant,
                      ),
                    ),
                  ],
                ),
              ),
            ),
            if (!canEdit)
              Padding(
                padding: const EdgeInsets.only(right: 8, top: 6),
                child: Tooltip(
                  message: isSystemManaged
                      ? 'Automatisch verwaltet – wird mit der Gutschrift '
                          'angelegt und beim Zurücknehmen wieder entfernt.'
                      : 'Lieferung beendet – Notiz nicht mehr änderbar.',
                  child: Icon(
                    Icons.lock_outline,
                    size: 18,
                    color: theme.colorScheme.onSurfaceVariant,
                  ),
                ),
              )
            else
              PopupMenuButton<_NoteAction>(
                icon: const Icon(Icons.more_vert),
                tooltip: 'Notiz-Aktionen',
                onSelected: (action) {
                  switch (action) {
                    case _NoteAction.edit:
                      _openEditDialog(context);
                    case _NoteAction.delete:
                      _confirmDeleteNote(
                        context,
                        deliveryId: deliveryId,
                        noteId: note.id,
                        isPhoto: false,
                      );
                  }
                },
                itemBuilder: (context) => [
                  const PopupMenuItem(
                    value: _NoteAction.edit,
                    child: Row(
                      children: [
                        Icon(Icons.edit_outlined),
                        SizedBox(width: 12),
                        Text('Bearbeiten'),
                      ],
                    ),
                  ),
                  PopupMenuItem(
                    value: _NoteAction.delete,
                    child: Row(
                      children: [
                        Icon(Icons.delete_outline,
                            color: theme.colorScheme.error),
                        const SizedBox(width: 12),
                        Text(
                          'Löschen',
                          style: TextStyle(color: theme.colorScheme.error),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
          ],
        ),
      ),
    );
  }
}

/// Karte eines **Fotos** — Thumbnail (Tap → formatfüllend) plus Metazeile
/// mit Lösch-Button. Kein Inline-Edit (ein Foto bearbeitet man nicht).
class _PhotoCard extends StatelessWidget {
  const _PhotoCard({
    required this.note,
    required this.deliveryId,
    required this.active,
  });
  final DeliveryNote note;
  final String deliveryId;

  /// Nur bei aktiver Lieferung darf das Foto gelöscht werden.
  final bool active;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Card(
      margin: const EdgeInsets.only(bottom: 8),
      clipBehavior: Clip.antiAlias,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _NoteImageThumb(
            attachmentId: note.imageAttachment!,
            deleted: note.imageAttachmentDeleted,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(12, 8, 4, 8),
            child: Row(
              children: [
                Icon(
                  Icons.photo_camera_outlined,
                  size: 16,
                  color: theme.colorScheme.onSurfaceVariant,
                ),
                const SizedBox(width: 6),
                Expanded(
                  child: Text(
                    'Personalnr. ${note.authorPersonalnummer} '
                    '· ${_formatNoteTime(note.createdAt)}',
                    style: TextStyle(
                      fontSize: 11,
                      color: theme.colorScheme.onSurfaceVariant,
                    ),
                  ),
                ),
                if (active)
                  IconButton(
                    icon: Icon(
                      Icons.delete_outline,
                      color: theme.colorScheme.error,
                    ),
                    tooltip: 'Foto löschen',
                    onPressed: () => _confirmDeleteNote(
                      context,
                      deliveryId: deliveryId,
                      noteId: note.id,
                      isPhoto: true,
                    ),
                  )
                else
                  Padding(
                    padding: const EdgeInsets.only(right: 8),
                    child: Tooltip(
                      message: 'Lieferung beendet – Foto nicht mehr löschbar.',
                      child: Icon(
                        Icons.lock_outline,
                        size: 18,
                        color: theme.colorScheme.onSurfaceVariant,
                      ),
                    ),
                  ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

/// Thumbnail einer Bild-Notiz; Tap öffnet das Bild formatfüllend mit
/// Zoom/Pan.
class _NoteImageThumb extends StatelessWidget {
  const _NoteImageThumb({required this.attachmentId, this.deleted = false});

  final String attachmentId;

  /// Lokale Bilddatei nach Report-Upload gelöscht → Hinweis statt Vorschau.
  final bool deleted;

  void _openFull(BuildContext context) {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (_) => Scaffold(
          backgroundColor: Colors.black,
          appBar: AppBar(
            backgroundColor: Colors.black,
            foregroundColor: Colors.white,
          ),
          body: Center(
            child: InteractiveViewer(
              minScale: 0.5,
              maxScale: 5,
              child: AttachmentImage(
                attachmentId: attachmentId,
                width: 2048,
                height: 2048,
                quality: 90,
                fit: BoxFit.contain,
                deleted: deleted,
              ),
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    // Kein eigenes Clipping — die umgebende `_PhotoCard` clippt bereits
    // (Clip.antiAlias), sonst gäbe es doppelt gerundete Ecken.
    return GestureDetector(
      // Gelöschtes Bild → kein Vollbild öffnen (es gibt nichts zu laden).
      onTap: deleted ? null : () => _openFull(context),
      child: SizedBox(
        height: 160,
        width: double.infinity,
        child: AttachmentImage(
          attachmentId: attachmentId,
          width: 600,
          height: 600,
          deleted: deleted,
        ),
      ),
    );
  }
}

// ─── Add-Menu (FAB) ─────────────────────────────────────────────────────

enum _AddAction { note, image }

class _AddMenu extends StatelessWidget {
  const _AddMenu({required this.onAddNote, required this.onAddImage});

  final VoidCallback onAddNote;
  final VoidCallback onAddImage;

  @override
  Widget build(BuildContext context) {
    return PopupMenuButton<_AddAction>(
      tooltip: 'Hinzufügen',
      onSelected: (action) {
        switch (action) {
          case _AddAction.note:
            onAddNote();
          case _AddAction.image:
            onAddImage();
        }
      },
      itemBuilder: (context) => const [
        PopupMenuItem(
          value: _AddAction.note,
          child: Row(
            children: [
              Icon(Icons.edit_note),
              SizedBox(width: 12),
              Text('Notiz schreiben'),
            ],
          ),
        ),
        PopupMenuItem(
          value: _AddAction.image,
          child: Row(
            children: [
              Icon(Icons.camera_alt_outlined),
              SizedBox(width: 12),
              Text('Foto aufnehmen'),
            ],
          ),
        ),
      ],
      child: FloatingActionButton.extended(
        onPressed: null, // PopupMenuButton fängt den Tap
        icon: const Icon(Icons.add),
        label: const Text('Hinzufügen'),
      ),
    );
  }
}

// ─── Notiz-Dialog (Text) ────────────────────────────────────────────────

/// Editor-Dialog für Text-Notizen — geteilt zwischen „Hinzufügen" und
/// „Bearbeiten". Liefert den getrimmten Text per [onSubmit]; der Aufrufer
/// entscheidet, ob daraus ein `AddDeliveryNote` oder `UpdateDeliveryNote`
/// wird.
class _NoteEditorDialog extends StatefulWidget {
  const _NoteEditorDialog({
    required this.title,
    required this.onSubmit,
    this.initialText,
  });

  final String title;
  final void Function(String text) onSubmit;
  final String? initialText;

  @override
  State<_NoteEditorDialog> createState() => _NoteEditorDialogState();
}

class _NoteEditorDialogState extends State<_NoteEditorDialog> {
  late final TextEditingController _controller =
      TextEditingController(text: widget.initialText ?? '');
  bool _empty = true;

  @override
  void initState() {
    super.initState();
    _empty = _controller.text.trim().isEmpty;
    _controller.addListener(() {
      setState(() => _empty = _controller.text.trim().isEmpty);
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _save() {
    final text = _controller.text.trim();
    if (text.isEmpty) return;
    widget.onSubmit(text);
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Dialog(
      insetPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
      child: ConstrainedBox(
        constraints: BoxConstraints(
          maxHeight: MediaQuery.of(context).size.height * 0.55,
        ),
        child: Padding(
          padding: const EdgeInsets.all(20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Row(
                children: [
                  Expanded(
                    child: Text(
                      widget.title,
                      style: Theme.of(context).textTheme.titleLarge,
                    ),
                  ),
                  IconButton(
                    icon: const Icon(Icons.close),
                    onPressed: () => Navigator.of(context).pop(),
                  ),
                ],
              ),
              const SizedBox(height: 12),
              // TODO(B6): Templates-Dropdown ergänzen, sobald Backend
              // Notiz-Templates als Stammdaten anbietet.
              Expanded(
                child: TextField(
                  controller: _controller,
                  autofocus: true,
                  maxLines: null,
                  expands: true,
                  textAlignVertical: TextAlignVertical.top,
                  decoration: const InputDecoration(
                    labelText: 'Notiz',
                    border: OutlineInputBorder(),
                    alignLabelWithHint: true,
                  ),
                ),
              ),
              const SizedBox(height: 16),
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  TextButton(
                    onPressed: () => Navigator.of(context).pop(),
                    child: const Text('Abbrechen'),
                  ),
                  const SizedBox(width: 8),
                  FilledButton.icon(
                    onPressed: _empty ? null : _save,
                    icon: const Icon(Icons.save),
                    label: const Text('Speichern'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}
