import 'dart:ui' as ui;

import 'package:flutter/material.dart';

import '../../core/config/app_pill_gradient.dart';
import '../../core/config/app_visual_style.dart';
import 'liquid_glass.dart';

class _GlossyParts {
  final bool dark;
  final Gradient fill;
  final Border rim;
  final Gradient topSheen;
  final Gradient bottomShade;

  const _GlossyParts({
    required this.dark,
    required this.fill,
    required this.rim,
    required this.topSheen,
    required this.bottomShade,
  });
}

class GlossyDecor {
  static final Map<Color, _GlossyParts> _cache = {};

  static _GlossyParts _parts(Color base) {
    final cached = _cache[base];
    if (cached != null) return cached;
    if (_cache.length > 64) _cache.clear();
    final hsl = HSLColor.fromColor(base);
    final dark = hsl.lightness < 0.5;
    Color shift(double d) =>
        hsl.withLightness((hsl.lightness + d).clamp(0.0, 1.0)).toColor();
    final parts = _GlossyParts(
      dark: dark,
      fill: LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: [shift(dark ? 0.06 : 0.05), base, shift(dark ? -0.05 : -0.07)],
        stops: const [0.0, 0.5, 1.0],
      ),
      rim: Border.all(
        color: Colors.white.withValues(alpha: dark ? 0.08 : 0.6),
        width: 0.8,
      ),
      topSheen: LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.center,
        colors: [
          Colors.white.withValues(alpha: dark ? 0.11 : 0.45),
          Colors.white.withValues(alpha: 0.0),
        ],
      ),
      bottomShade: LinearGradient(
        begin: Alignment.bottomCenter,
        end: Alignment.center,
        colors: [
          Colors.black.withValues(alpha: dark ? 0.2 : 0.07),
          Colors.black.withValues(alpha: 0.0),
        ],
      ),
    );
    _cache[base] = parts;
    return parts;
  }

  static bool isDark(Color base) => _parts(base).dark;
  static Gradient fillGradient(Color base) => _parts(base).fill;
  static Border rimBorder(Color base) => _parts(base).rim;
  static Gradient topSheen(Color base) => _parts(base).topSheen;
  static Gradient bottomShade(Color base) => _parts(base).bottomShade;

  static BoxShadow dropShadow(Color base, double depth) {
    final dark = _parts(base).dark;
    return BoxShadow(
      color: Colors.black.withValues(alpha: dark ? 0.5 : 0.22),
      blurRadius: depth * 1.6,
      spreadRadius: -depth * 0.3,
      offset: Offset(0, depth * 0.6),
    );
  }
}

class GlossyPill extends StatelessWidget {
  final Widget child;
  final EdgeInsetsGeometry padding;
  final BorderRadius borderRadius;
  final Color? color;
  final VoidCallback? onTap;
  final VoidCallback? onLongPress;
  final double depth;
  final bool elevated;
  final BorderSide? borderSide;
  final double? blurSigma;
  final bool liquid;
  final BackdropKey? backdropKey;

  const GlossyPill({
    super.key,
    required this.child,
    this.padding = EdgeInsets.zero,
    BorderRadius? borderRadius,
    this.color,
    this.onTap,
    this.onLongPress,
    this.depth = 10,
    this.elevated = false,
    this.borderSide,
    this.blurSigma,
    this.liquid = false,
    this.backdropKey,
  }) : borderRadius =
           borderRadius ?? const BorderRadius.all(Radius.circular(100));

  double? _sigmaFor(Color base) =>
      blurSigma != null && base.a < 1 ? blurSigma : null;

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<VisualStyle>(
      valueListenable: AppVisualStyle.current,
      builder: (context, style, _) {
        if (style == VisualStyle.materialYou) return _flat(context);
        if (liquid && LiquidGlass.isSupported) return _liquid(context);
        return ValueListenableBuilder<bool>(
          valueListenable: AppPillGradient.current,
          builder: (context, gradient, _) => _glossy(context, gradient),
        );
      },
    );
  }

  Widget _liquid(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final base = color ?? cs.surfaceContainerHigh;
    final content = Padding(padding: padding, child: child);

    return RepaintBoundary(
      child: DecoratedBox(
        decoration: BoxDecoration(
          borderRadius: borderRadius,
          border: GlossyDecor.rimBorder(base),
          boxShadow: [GlossyDecor.dropShadow(base, depth)],
        ),
        child: LiquidGlassSurface(
          borderRadius: borderRadius,
          tint: Colors.transparent,
          child: onTap == null && onLongPress == null
              ? content
              : Material(
                  type: MaterialType.transparency,
                  child: InkWell(
                    onTap: onTap,
                    onLongPress: onLongPress,
                    child: content,
                  ),
                ),
        ),
      ),
    );
  }

  Widget _flat(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final base = color ?? cs.surfaceContainerHigh;
    final content = Padding(padding: padding, child: child);
    final material = Material(
      color: base,
      elevation: elevated ? 3 : 0,
      shadowColor: Colors.black.withValues(alpha: 0.4),
      surfaceTintColor: Colors.transparent,
      shape: RoundedRectangleBorder(
        borderRadius: borderRadius,
        side: borderSide ?? BorderSide.none,
      ),
      clipBehavior: Clip.antiAlias,
      child: onTap == null && onLongPress == null
          ? content
          : InkWell(onTap: onTap, onLongPress: onLongPress, child: content),
    );
    final sigma = _sigmaFor(base);
    if (sigma == null) return material;
    return ClipRRect(
      borderRadius: borderRadius,
      child: BackdropFilter(
        filter: ui.ImageFilter.blur(sigmaX: sigma, sigmaY: sigma),
        backdropGroupKey: backdropKey,
        child: material,
      ),
    );
  }

  Widget _glossy(BuildContext context, bool gradient) {
    final cs = Theme.of(context).colorScheme;
    final base = color ?? cs.surfaceContainerHigh;
    final content = Padding(padding: padding, child: child);
    final sigma = _sigmaFor(base);

    return RepaintBoundary(
      child: DecoratedBox(
        decoration: BoxDecoration(
          borderRadius: borderRadius,
          color: gradient ? null : base,
          gradient: gradient ? GlossyDecor.fillGradient(base) : null,
          border: GlossyDecor.rimBorder(base),
          boxShadow: [GlossyDecor.dropShadow(base, depth)],
        ),
        child: ClipRRect(
          borderRadius: borderRadius,
          child: Stack(
            fit: StackFit.passthrough,
            children: [
              if (sigma != null)
                Positioned.fill(
                  child: BackdropFilter(
                    filter: ui.ImageFilter.blur(sigmaX: sigma, sigmaY: sigma),
                    backdropGroupKey: backdropKey,
                    child: const SizedBox.expand(),
                  ),
                ),
              if (gradient) ...[
                Positioned.fill(
                  child: IgnorePointer(
                    child: DecoratedBox(
                      decoration: BoxDecoration(
                        gradient: GlossyDecor.topSheen(base),
                      ),
                    ),
                  ),
                ),
                Positioned.fill(
                  child: IgnorePointer(
                    child: DecoratedBox(
                      decoration: BoxDecoration(
                        gradient: GlossyDecor.bottomShade(base),
                      ),
                    ),
                  ),
                ),
              ],
              if (onTap == null && onLongPress == null)
                content
              else
                Material(
                  type: MaterialType.transparency,
                  child: InkWell(
                    onTap: onTap,
                    onLongPress: onLongPress,
                    child: content,
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }
}
