import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:holzleitner_api/holzleitner_api.dart' show HolzleitnerApi;

import 'package:hl_lieferservice/data/cache/attachment_cache.dart';
import 'package:hl_lieferservice/main.dart' show locator;

/// Lädt und zeigt ein Attachment-Vorschaubild über
/// `GET /attachments/{id}` an. Nutzt die geteilte, authentifizierte
/// Dio-Instanz (`HolzleitnerApi.dio`) — der Auth-Interceptor hängt den
/// Bearer-Token an, ein generierter Client-Methodenaufruf ist für die
/// Binär-Antwort nicht zuverlässig.
///
/// Reines Lese-Widget (kein Bloc): Bild-Anzeige ist kein App-State.
class AttachmentImage extends StatefulWidget {
  const AttachmentImage({
    super.key,
    required this.attachmentId,
    this.width = 1024,
    this.height = 1024,
    this.quality = 80,
    this.fit = BoxFit.cover,
    this.deleted = false,
  });

  /// Unsere Attachment-UUID (steht in `DeliveryNote.imageAttachment`).
  final String attachmentId;

  /// Wenn `true`: die lokale Bilddatei wurde nach dem Report-Upload gelöscht
  /// (das Bild steckt im Lieferbericht in DOCUframe). Statt eines Downloads
  /// wird ein Hinweis gezeigt.
  final bool deleted;

  /// Angefragte Vorschau-Abmessungen (Backend rendert per DOCUframe).
  final int width;
  final int height;
  final int quality;
  final BoxFit fit;

  @override
  State<AttachmentImage> createState() => _AttachmentImageState();
}

class _AttachmentImageState extends State<AttachmentImage> {
  late Future<Uint8List> _future;

  @override
  void initState() {
    super.initState();
    // Gelöschte Anhänge nicht laden — es gibt keine lokale Datei mehr.
    _future = widget.deleted ? Future.value(Uint8List(0)) : _load();
  }

  @override
  void didUpdateWidget(AttachmentImage oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.attachmentId != widget.attachmentId ||
        oldWidget.width != widget.width ||
        oldWidget.height != widget.height ||
        oldWidget.quality != widget.quality) {
      _future = _load();
    }
  }

  static const _ext = 'jpeg';

  Future<Uint8List> _load() async {
    final cache = locator<AttachmentCache>();

    // 1. Disk-Cache zuerst — Attachments sind unveränderlich, ein Treffer
    //    ist also immer gültig (auch offline).
    final cached = await cache.read(
      attachmentId: widget.attachmentId,
      w: widget.width,
      h: widget.height,
      q: widget.quality,
      ext: _ext,
    );
    if (cached != null) return cached;

    // 2. Miss → über die authentifizierte Dio-Instanz aus DOCUframe holen.
    final api = locator<HolzleitnerApi>();
    final response = await api.dio.get<List<int>>(
      '/attachments/${widget.attachmentId}',
      queryParameters: {
        'w': widget.width,
        'h': widget.height,
        'q': widget.quality,
        'ext': _ext,
      },
      options: Options(responseType: ResponseType.bytes),
    );
    final bytes = Uint8List.fromList(response.data ?? const []);

    // 3. Erfolgreichen Download persistieren (best-effort, blockiert die
    //    Anzeige nicht — write schluckt Fehler).
    if (bytes.isNotEmpty) {
      await cache.write(
        attachmentId: widget.attachmentId,
        w: widget.width,
        h: widget.height,
        q: widget.quality,
        ext: _ext,
        bytes: bytes,
      );
    }
    return bytes;
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    if (widget.deleted) {
      return _DeletedHint(fit: widget.fit);
    }
    return FutureBuilder<Uint8List>(
      future: _future,
      builder: (context, snapshot) {
        if (snapshot.connectionState != ConnectionState.done) {
          return const Center(
            child: Padding(
              padding: EdgeInsets.all(16),
              child: SizedBox(
                width: 22,
                height: 22,
                child: CircularProgressIndicator(strokeWidth: 2),
              ),
            ),
          );
        }
        if (snapshot.hasError ||
            snapshot.data == null ||
            snapshot.data!.isEmpty) {
          return Center(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Icon(
                Icons.broken_image_outlined,
                color: theme.colorScheme.onSurfaceVariant,
              ),
            ),
          );
        }
        return Image.memory(snapshot.data!, fit: widget.fit);
      },
    );
  }
}

/// Hinweis für gelöschte Bild-Anhänge: das Bild liegt im Lieferbericht.
class _DeletedHint extends StatelessWidget {
  const _DeletedHint({required this.fit});

  final BoxFit fit;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Container(
      color: theme.colorScheme.surfaceContainerHighest,
      alignment: Alignment.center,
      padding: const EdgeInsets.all(16),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            Icons.picture_as_pdf_outlined,
            color: theme.colorScheme.onSurfaceVariant,
          ),
          const SizedBox(height: 8),
          Text(
            'Bild im Lieferbericht enthalten',
            textAlign: TextAlign.center,
            style: theme.textTheme.bodySmall?.copyWith(
              color: theme.colorScheme.onSurfaceVariant,
            ),
          ),
        ],
      ),
    );
  }
}
