import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:kasy_kit/core/theme/theme.dart';

/// Tone for the icon bubble displayed at the top of [KasyBottomSheet].
enum KasySheetIconTone { info, success, warning, danger, neutral }

/// A design-system bottom sheet panel.
///
/// Use [showKasyBottomSheet] to present it. The sheet handles drag-handle,
/// optional icon bubble, title, message, custom body, and action buttons.
class KasyBottomSheet extends StatelessWidget {
  final String? title;
  final String? message;

  /// Optional icon shown inside a soft-tinted bubble above the title.
  final IconData? icon;
  final KasySheetIconTone iconTone;

  /// Custom content displayed between [message] and [actions].
  final Widget? body;

  /// Action buttons displayed at the bottom (usually [KasyButton] widgets).
  final List<Widget> actions;

  final bool showDragHandle;

  /// Set to false when the sheet is detached (floating) so the outer
  /// layout handles the bottom safe area instead.
  final bool addBottomSafeArea;

  /// When true, the sheet grows by the keyboard inset so its surface continues
  /// underneath the keyboard while content remains visible above it.
  final bool addKeyboardInset;

  const KasyBottomSheet({
    super.key,
    this.title,
    this.message,
    this.icon,
    this.iconTone = KasySheetIconTone.info,
    this.body,
    this.actions = const [],
    this.showDragHandle = true,
    this.addBottomSafeArea = true,
    this.addKeyboardInset = false,
  });

  @override
  Widget build(BuildContext context) {
    final double bottomSafeArea =
        addBottomSafeArea ? MediaQuery.paddingOf(context).bottom : 0;
    final double keyboardInset =
        addKeyboardInset ? MediaQuery.viewInsetsOf(context).bottom : 0;
    final double bottomInset = bottomSafeArea + keyboardInset;
    final bool hasIcon = icon != null;
    final bool centered = hasIcon;

    // Elevate the input fill color for any KasyTextField.primary inside the
    // sheet. primary variant reads inputDecorationTheme.fillColor first, so
    // fields automatically contrast against the surface background without
    // callers needing to specify variant: secondary manually.
    final Color elevatedFill = context.isDark
        ? const Color(0xFF272729)
        : const Color(0xFFF0F0F2);

    return Material(
      color: context.colors.surface,
      borderRadius: const BorderRadius.vertical(
        top: Radius.circular(KasyRadius.xl),
      ),
      child: Theme(
        data: Theme.of(context).copyWith(
          inputDecorationTheme: Theme.of(context).inputDecorationTheme.copyWith(
            fillColor: elevatedFill,
          ),
        ),
        child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment:
            centered ? CrossAxisAlignment.center : CrossAxisAlignment.start,
        children: [
          if (showDragHandle) _DragHandle(),
          AnimatedPadding(
            duration: const Duration(milliseconds: 180),
            curve: Curves.easeOutCubic,
            padding: EdgeInsets.fromLTRB(
              KasySpacing.lg,
              hasIcon ? KasySpacing.lg : KasySpacing.md,
              KasySpacing.lg,
              bottomInset + KasySpacing.lg,
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment:
                  centered ? CrossAxisAlignment.center : CrossAxisAlignment.start,
              children: [
                if (hasIcon) ...[
                  _IconBubble(icon: icon!, tone: iconTone),
                  const SizedBox(height: KasySpacing.md),
                ],
                if (title != null)
                  Text(
                    title!,
                    textAlign: centered ? TextAlign.center : TextAlign.start,
                    style: context.textTheme.titleLarge?.copyWith(
                      fontWeight: FontWeight.w600,
                      color: context.colors.onSurface,
                    ),
                  ),
                if (message != null) ...[
                  const SizedBox(height: KasySpacing.sm),
                  Text(
                    message!,
                    textAlign: centered ? TextAlign.center : TextAlign.start,
                    style: context.textTheme.bodyMedium?.copyWith(
                      color: context.colors.onSurface.withValues(alpha: 0.6),
                      height: 1.5,
                    ),
                  ),
                ],
                if (body != null) ...[
                  const SizedBox(height: KasySpacing.md),
                  body!,
                ],
                if (actions.isNotEmpty) ...[
                  const SizedBox(height: KasySpacing.lg),
                  ...actions.expand(
                    (w) => [
                      w,
                      if (w != actions.last) const SizedBox(height: KasySpacing.sm),
                    ],
                  ),
                ],
              ],
            ),
          ),
        ],
      ),
      ),
    );
  }
}

/// Shows a [KasyBottomSheet] using Material's modal bottom sheet.
///
/// Example:
/// ```dart
/// showKasyBottomSheet(
///   context: context,
///   builder: (_) => KasyBottomSheet(
///     icon: KasyIcons.security,
///     iconTone: KasySheetIconTone.success,
///     title: 'Keep yourself safe',
///     message: 'Update your app for better security.',
///     actions: [
///       KasyButton(label: 'Update Now', expand: true, onPressed: () {}),
///       KasyButton(label: 'Later', variant: KasyButtonVariant.ghost, expand: true, onPressed: () {}),
///     ],
///   ),
/// );
/// ```
Future<T?> showKasyBottomSheet<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  bool isDismissible = true,
  bool enableDrag = true,
  bool isScrollControlled = false,
  Color? barrierColor,
}) {
  return showModalBottomSheet<T>(
    context: context,
    useRootNavigator: true,
    isDismissible: isDismissible,
    enableDrag: enableDrag,
    isScrollControlled: isScrollControlled,
    backgroundColor: Colors.transparent,
    barrierColor: barrierColor ??
        Colors.black.withValues(
          alpha: Theme.of(context).brightness == Brightness.dark ? 0.6 : 0.45,
        ),
    builder: builder,
  );
}

/// Shows a [KasyBottomSheet] with a frosted-glass blur overlay instead of
/// the standard dim barrier. Uses [showGeneralDialog] for full-screen control.
Future<T?> showKasyBlurBottomSheet<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  bool isDismissible = true,
  double blurSigma = 8,
}) {
  return showGeneralDialog<T>(
    context: context,
    barrierDismissible: isDismissible,
    barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
    barrierColor: Colors.transparent,
    transitionDuration: const Duration(milliseconds: 320),
    pageBuilder: (ctx, animation, _) => _BlurSheetScaffold(
      animation: animation,
      blurSigma: blurSigma,
      isDismissible: isDismissible,
      child: builder(ctx),
    ),
    transitionBuilder: (_, _, _, child) => child,
  );
}

class _BlurSheetScaffold extends StatelessWidget {
  final Animation<double> animation;
  final double blurSigma;
  final bool isDismissible;
  final Widget child;

  const _BlurSheetScaffold({
    required this.animation,
    required this.blurSigma,
    required this.isDismissible,
    required this.child,
  });

  @override
  Widget build(BuildContext context) {
    final CurvedAnimation curved = CurvedAnimation(
      parent: animation,
      curve: Curves.easeOutCubic,
    );
    return AnimatedBuilder(
      animation: curved,
      builder: (ctx, _) {
        final double t = curved.value;
        return Stack(
          children: [
            GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: isDismissible ? () => Navigator.of(ctx).pop() : null,
              child: BackdropFilter(
                filter: ImageFilter.blur(
                  sigmaX: blurSigma * t,
                  sigmaY: blurSigma * t,
                ),
                child: ColoredBox(
                  color: Colors.black.withValues(alpha: 0.28 * t),
                  child: const SizedBox.expand(),
                ),
              ),
            ),
            Positioned(
              left: 0,
              right: 0,
              bottom: 0,
              child: SlideTransition(
                position: Tween<Offset>(
                  begin: const Offset(0, 1),
                  end: Offset.zero,
                ).animate(curved),
                child: child,
              ),
            ),
          ],
        );
      },
    );
  }
}

class _DragHandle extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: KasySpacing.smd),
      child: Center(
        child: Container(
          width: 36,
          height: 4,
          decoration: BoxDecoration(
            color: context.colors.outline.withValues(alpha: 0.35),
            borderRadius: BorderRadius.circular(KasyRadius.full),
          ),
        ),
      ),
    );
  }
}

class _IconBubble extends StatelessWidget {
  final IconData icon;
  final KasySheetIconTone tone;

  const _IconBubble({required this.icon, required this.tone});

  @override
  Widget build(BuildContext context) {
    final _SheetIconPalette p = _resolvePalette(context, tone);
    return Container(
      width: 72,
      height: 72,
      decoration: BoxDecoration(color: p.background, shape: BoxShape.circle),
      child: Icon(icon, size: 30, color: p.foreground),
    );
  }

  _SheetIconPalette _resolvePalette(BuildContext context, KasySheetIconTone tone) {
    final KasyColors c = context.colors;
    final bool dark = context.isDark;
    return switch (tone) {
      KasySheetIconTone.info => _SheetIconPalette(
        background: c.primary.withValues(alpha: dark ? 0.22 : 0.12),
        foreground: c.primary,
      ),
      KasySheetIconTone.success => _SheetIconPalette(
        background: c.success.withValues(alpha: dark ? 0.22 : 0.12),
        foreground: c.success,
      ),
      KasySheetIconTone.warning => _SheetIconPalette(
        background: c.warning.withValues(alpha: dark ? 0.22 : 0.12),
        foreground: c.warning,
      ),
      KasySheetIconTone.danger => _SheetIconPalette(
        background: c.error.withValues(alpha: dark ? 0.22 : 0.12),
        foreground: c.error,
      ),
      KasySheetIconTone.neutral => _SheetIconPalette(
        background: c.outline.withValues(alpha: dark ? 0.22 : 0.12),
        foreground: c.onSurface.withValues(alpha: 0.7),
      ),
    };
  }
}

class _SheetIconPalette {
  final Color background;
  final Color foreground;

  const _SheetIconPalette({required this.background, required this.foreground});
}
