import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../models/slide.dart';
import '../../theme/app_theme.dart';
import '../../l10n/app_localizations.dart';

class AddSlideDialog extends StatelessWidget {
  const AddSlideDialog({super.key});

  static Future<SlideType?> show(BuildContext context) {
    return showDialog<SlideType>(
      context: context,
      builder: (_) => const AddSlideDialog(),
    );
  }

  static const _types = [
    (SlideType.title, 'Titelpagina'),
    (SlideType.section, 'Tussentitel'),
    (SlideType.bullets, 'Alleen Bullets'),
    (SlideType.twoBullets, 'Twee Bulletkolommen'),
    (SlideType.bulletsImage, 'Bullets + Afbeelding'),
    (SlideType.twoImages, 'Twee Afbeeldingen'),
    (SlideType.image, 'Grote Afbeelding'),
    (SlideType.video, 'Video'),
    (SlideType.quote, 'Quote'),
    (SlideType.table, 'Tabel'),
    (SlideType.chart, 'Grafiek'),
    (SlideType.code, 'Broncode'),
    (SlideType.freeMarkdown, 'Vrije Markdown'),
  ];

  @override
  Widget build(BuildContext context) {
    final l10n = context.l10n;
    return CallbackShortcuts(
      bindings: {
        const SingleActivator(LogicalKeyboardKey.escape): () =>
            Navigator.pop(context),
      },
      child: AlertDialog(
        title: Text(l10n.d('Slide type kiezen')),
        content: SizedBox(
          width: 440,
          // Reading-order tabbing through the cards; the first one takes
          // focus so the dialog is fully keyboard-operable right away.
          child: FocusTraversalGroup(
            policy: ReadingOrderTraversalPolicy(),
            child: Wrap(
              spacing: 10,
              runSpacing: 10,
              children: [
                for (var i = 0; i < _types.length; i++)
                  _TypeCard(
                    type: _types[i].$1,
                    label: l10n.d(_types[i].$2),
                    autofocus: i == 0,
                    onTap: () => Navigator.pop(context, _types[i].$1),
                  ),
              ],
            ),
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text(l10n.t('cancel')),
          ),
        ],
      ),
    );
  }
}

class _TypeCard extends StatelessWidget {
  final SlideType type;
  final String label;
  final VoidCallback onTap;
  final bool autofocus;

  const _TypeCard({
    required this.type,
    required this.label,
    required this.onTap,
    this.autofocus = false,
  });

  @override
  Widget build(BuildContext context) {
    return Semantics(
      button: true,
      child: InkWell(
        onTap: onTap,
        autofocus: autofocus,
        borderRadius: BorderRadius.circular(8),
        focusColor: AppTheme.accent.withValues(alpha: 0.14),
        hoverColor: AppTheme.accent.withValues(alpha: 0.06),
        child: Container(
          width: 100,
          padding: const EdgeInsets.all(8),
          decoration: BoxDecoration(
            border: Border.all(color: const Color(0xFFCBD5E1)),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // A stylised wireframe of the layout, so the card shows what
              // the slide will look like instead of an abstract icon.
              ExcludeSemantics(
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(4),
                  child: AspectRatio(
                    aspectRatio: 16 / 9,
                    child: CustomPaint(
                      painter: SlideTypePreviewPainter(type: type),
                    ),
                  ),
                ),
              ),
              const SizedBox(height: 6),
              Text(
                label,
                textAlign: TextAlign.center,
                maxLines: 2,
                style: const TextStyle(fontSize: 11, height: 1.15),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

/// Paints a miniature 16:9 wireframe of a slide layout, in the spirit of the
/// layout pickers in other presentation tools: title bars, text lines, image
/// placeholders. All geometry lives on a 160×90 design canvas and is scaled
/// to whatever size the card provides.
@visibleForTesting
class SlideTypePreviewPainter extends CustomPainter {
  final SlideType type;

  /// Wireframe palette: dark bars for titles, soft bars for body text.
  static const _canvas = Color(0xFFF8FAFC);
  static const _ink = Color(0xFF334155);
  static const _soft = Color(0xFFB6C2D2);
  static const _fill = Color(0xFFE2E8F0);
  static const _accent = AppTheme.accent;

  const SlideTypePreviewPainter({required this.type});

  @override
  void paint(Canvas canvas, Size size) {
    final u = size.width / 160;
    canvas.scale(u);
    canvas.drawRect(const Rect.fromLTWH(0, 0, 160, 90), _paint(_canvas));

    switch (type) {
      case SlideType.title:
        _bar(canvas, 30, 34, 100, 12, _ink);
        _bar(canvas, 45, 53, 70, 7, _accent);
      case SlideType.section:
        _bar(canvas, 16, 36, 5, 24, _accent);
        _bar(canvas, 30, 38, 86, 11, _ink);
        _bar(canvas, 30, 54, 52, 6, _soft);
      case SlideType.bullets:
        _bar(canvas, 14, 12, 84, 9, _ink);
        _bullets(canvas, 14, 34, 110, 4);
      case SlideType.twoBullets:
        _bar(canvas, 14, 12, 84, 9, _ink);
        _bullets(canvas, 14, 32, 56, 3);
        _bullets(canvas, 90, 32, 56, 3);
      case SlideType.bulletsImage:
        _bar(canvas, 14, 12, 66, 9, _ink);
        _bullets(canvas, 14, 32, 60, 3);
        _imageBox(canvas, 90, 26, 56, 50);
      case SlideType.twoImages:
        _imageBox(canvas, 12, 16, 64, 46);
        _imageBox(canvas, 84, 16, 64, 46);
        _bar(canvas, 20, 68, 48, 5, _soft);
        _bar(canvas, 92, 68, 48, 5, _soft);
      case SlideType.image:
        _imageBox(canvas, 10, 10, 140, 70);
      case SlideType.video:
        _imageBox(canvas, 10, 10, 140, 70, pictogram: false);
        canvas.drawCircle(const Offset(80, 45), 14, _paint(Colors.white));
        final play = Path()
          ..moveTo(75, 37)
          ..lineTo(89, 45)
          ..lineTo(75, 53)
          ..close();
        canvas.drawPath(play, _paint(_ink));
      case SlideType.quote:
        _quoteMark(canvas, 16, 16);
        _bar(canvas, 42, 30, 96, 7, _ink);
        _bar(canvas, 42, 43, 78, 7, _ink);
        _bar(canvas, 42, 60, 42, 5, _accent);
      case SlideType.table:
        _bar(canvas, 14, 16, 132, 14, _soft, radius: 2);
        final line = _paint(_ink.withValues(alpha: 0.45))..strokeWidth = 1.5;
        for (var r = 1; r <= 4; r++) {
          canvas.drawLine(
            Offset(14, 16 + r * 14),
            Offset(146, 16 + r * 14),
            line,
          );
        }
        for (var c = 0; c <= 3; c++) {
          canvas.drawLine(
            Offset(14 + c * 44, 16),
            Offset(14 + c * 44, 72),
            line,
          );
        }
      case SlideType.chart:
        final axis = _paint(_soft)..strokeWidth = 2;
        canvas.drawLine(const Offset(20, 14), const Offset(20, 74), axis);
        canvas.drawLine(const Offset(20, 74), const Offset(148, 74), axis);
        _bar(canvas, 34, 50, 18, 24, _soft, radius: 2);
        _bar(canvas, 64, 36, 18, 38, _accent, radius: 2);
        _bar(canvas, 94, 44, 18, 30, _soft, radius: 2);
        _bar(canvas, 124, 24, 18, 50, _accent, radius: 2);
      case SlideType.code:
        _bar(canvas, 10, 10, 140, 70, const Color(0xFF1E293B), radius: 4);
        _bar(canvas, 20, 22, 44, 6, const Color(0xFF7DD3A7), radius: 3);
        _bar(canvas, 30, 34, 64, 6, const Color(0xFF93B8F8), radius: 3);
        _bar(canvas, 30, 46, 50, 6, const Color(0xFFE2C08D), radius: 3);
        _bar(canvas, 20, 58, 32, 6, const Color(0xFF7DD3A7), radius: 3);
      case SlideType.freeMarkdown:
        _bar(canvas, 14, 12, 10, 9, _accent, radius: 2);
        _bar(canvas, 28, 12, 62, 9, _ink);
        _bar(canvas, 14, 32, 120, 6, _soft);
        _bar(canvas, 14, 44, 132, 6, _soft);
        _bar(canvas, 14, 56, 92, 6, _soft);
        _bar(canvas, 14, 68, 110, 6, _soft);
    }
  }

  void _bar(
    Canvas canvas,
    double x,
    double y,
    double w,
    double h,
    Color color, {
    double? radius,
  }) {
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromLTWH(x, y, w, h),
        Radius.circular(radius ?? h / 2),
      ),
      _paint(color),
    );
  }

  /// A column of bullet points: accent dot plus a soft text line.
  void _bullets(Canvas canvas, double x, double y, double w, int count) {
    for (var i = 0; i < count; i++) {
      final dy = y + i * 13.0;
      canvas.drawCircle(Offset(x + 3, dy + 3), 3, _paint(_accent));
      _bar(canvas, x + 11, dy, w * (i.isEven ? 1.0 : 0.74), 6, _soft);
    }
  }

  /// Image placeholder: filled box with a sun and mountains pictogram.
  void _imageBox(
    Canvas canvas,
    double x,
    double y,
    double w,
    double h, {
    bool pictogram = true,
  }) {
    _bar(canvas, x, y, w, h, _fill, radius: 4);
    if (!pictogram) return;
    final dark = _paint(_soft);
    canvas.drawCircle(Offset(x + w * 0.28, y + h * 0.30), h * 0.11, dark);
    final hills = Path()
      ..moveTo(x + w * 0.08, y + h * 0.88)
      ..lineTo(x + w * 0.38, y + h * 0.45)
      ..lineTo(x + w * 0.58, y + h * 0.72)
      ..lineTo(x + w * 0.74, y + h * 0.52)
      ..lineTo(x + w * 0.94, y + h * 0.88)
      ..close();
    canvas.drawPath(hills, dark);
  }

  /// A stylised double quotation mark.
  void _quoteMark(Canvas canvas, double x, double y) {
    final paint = _paint(_accent);
    for (final dx in [0.0, 11.0]) {
      canvas.drawCircle(Offset(x + 4 + dx, y + 8), 4, paint);
      final tail = Path()
        ..moveTo(x + dx, y + 8)
        ..quadraticBezierTo(x + dx, y + 17, x + 7 + dx, y + 18)
        ..lineTo(x + 7 + dx, y + 14)
        ..quadraticBezierTo(x + 4 + dx, y + 13, x + 4 + dx, y + 8)
        ..close();
      canvas.drawPath(tail, paint);
    }
  }

  @override
  bool shouldRepaint(SlideTypePreviewPainter old) => old.type != type;
}

Paint _paint(Color color) => Paint()..color = color;
