import 'package:flutter/material.dart';

/// Design System centralisé pour Afterwork
///
/// Ce fichier contient toutes les constantes de design pour assurer
/// une cohérence visuelle à travers toute l'application.
///
/// **Sections:**
/// - Spacing: Espacements standardisés
/// - BorderRadius: Rayons de bordure
/// - Shadows: Ombres et élévations
/// - Durations: Durées d'animations
/// - Curves: Courbes d'animations
/// - Sizes: Tailles standardisées
class DesignSystem {
  // ============================================================================
  // SPACING
  // ============================================================================

  /// Espacements standardisés
  ///
  /// Utiliser ces constantes pour tous les paddings, margins, gaps, etc.
  /// Cela garantit une cohérence visuelle et facilite les ajustements.
  static const double spacing2xs = 2.0;
  static const double spacingXs = 4.0;
  static const double spacingSm = 8.0;
  static const double spacingMd = 12.0;
  static const double spacingLg = 16.0;
  static const double spacingXl = 24.0;
  static const double spacing2xl = 32.0;
  static const double spacing3xl = 48.0;
  static const double spacing4xl = 64.0;

  /// Padding horizontal standard des écrans
  static const double screenPaddingHorizontal = spacingLg;

  /// Padding vertical standard des écrans
  static const double screenPaddingVertical = spacingLg;

  /// Gap entre éléments de liste
  static const double listItemGap = spacingMd;

  /// Gap entre sections
  static const double sectionGap = spacingXl;

  // ============================================================================
  // BORDER RADIUS
  // ============================================================================

  /// Rayons de bordure standardisés
  static const double radiusXs = 4.0;
  static const double radiusSm = 8.0;
  static const double radiusMd = 12.0;
  static const double radiusLg = 16.0;
  static const double radiusXl = 20.0;
  static const double radius2xl = 24.0;
  static const double radiusRound = 999.0;

  /// BorderRadius objets pour utilisation directe
  static final BorderRadius borderRadiusXs = BorderRadius.circular(radiusXs);
  static final BorderRadius borderRadiusSm = BorderRadius.circular(radiusSm);
  static final BorderRadius borderRadiusMd = BorderRadius.circular(radiusMd);
  static final BorderRadius borderRadiusLg = BorderRadius.circular(radiusLg);
  static final BorderRadius borderRadiusXl = BorderRadius.circular(radiusXl);
  static final BorderRadius borderRadius2xl = BorderRadius.circular(radius2xl);
  static final BorderRadius borderRadiusRound = BorderRadius.circular(radiusRound);

  // ============================================================================
  // SHADOWS
  // ============================================================================

  /// Ombres standardisées pour Material Design
  ///
  /// Niveaux d'élévation:
  /// - None: Pas d'ombre
  /// - Sm: Petite élévation (cartes au repos)
  /// - Md: Élévation moyenne (cartes survolées)
  /// - Lg: Grande élévation (dialogs, bottom sheets)
  /// - Xl: Très grande élévation (navigation drawer)

  static const List<BoxShadow> shadowNone = [];

  static const List<BoxShadow> shadowSm = [
    BoxShadow(
      color: Color(0x0F000000), // 6% opacity
      blurRadius: 4,
      offset: Offset(0, 1),
      spreadRadius: 0,
    ),
  ];

  static const List<BoxShadow> shadowMd = [
    BoxShadow(
      color: Color(0x14000000), // 8% opacity
      blurRadius: 8,
      offset: Offset(0, 2),
      spreadRadius: 0,
    ),
  ];

  static const List<BoxShadow> shadowLg = [
    BoxShadow(
      color: Color(0x1F000000), // 12% opacity
      blurRadius: 16,
      offset: Offset(0, 4),
      spreadRadius: 0,
    ),
  ];

  static const List<BoxShadow> shadowXl = [
    BoxShadow(
      color: Color(0x29000000), // 16% opacity
      blurRadius: 24,
      offset: Offset(0, 8),
      spreadRadius: 0,
    ),
  ];

  /// Ombres pour mode sombre (plus subtiles)
  static const List<BoxShadow> shadowSmDark = [
    BoxShadow(
      color: Color(0x33000000), // 20% opacity
      blurRadius: 4,
      offset: Offset(0, 1),
      spreadRadius: 0,
    ),
  ];

  static const List<BoxShadow> shadowMdDark = [
    BoxShadow(
      color: Color(0x3D000000), // 24% opacity
      blurRadius: 8,
      offset: Offset(0, 2),
      spreadRadius: 0,
    ),
  ];

  static const List<BoxShadow> shadowLgDark = [
    BoxShadow(
      color: Color(0x47000000), // 28% opacity
      blurRadius: 16,
      offset: Offset(0, 4),
      spreadRadius: 0,
    ),
  ];

  // ============================================================================
  // DURATIONS (Durées d'animations)
  // ============================================================================

  /// Durées d'animations standardisées
  ///
  /// Suivent les Material Design motion guidelines:
  /// - Fast: Micro-interactions rapides (100-200ms)
  /// - Medium: Transitions standard (200-300ms)
  /// - Slow: Animations complexes (300-500ms)
  static const Duration durationInstant = Duration(milliseconds: 100);
  static const Duration durationFast = Duration(milliseconds: 200);
  static const Duration durationMedium = Duration(milliseconds: 300);
  static const Duration durationSlow = Duration(milliseconds: 400);
  static const Duration durationSlower = Duration(milliseconds: 500);

  // ============================================================================
  // CURVES (Courbes d'animations)
  // ============================================================================

  /// Courbes d'animations standardisées
  ///
  /// Material Design recommande:
  /// - easeIn: Accélération au début (sortie d'écran)
  /// - easeOut: Décélération à la fin (entrée d'écran)
  /// - easeInOut: Accélération puis décélération (transitions)
  /// - bounce: Effet rebond (micro-interactions fun)
  static const Curve curveStandard = Curves.easeInOut;
  static const Curve curveDecelerate = Curves.easeOut;
  static const Curve curveAccelerate = Curves.easeIn;
  static const Curve curveSharp = Curves.easeInOutCubic;
  static const Curve curveBounce = Curves.elasticOut;

  // ============================================================================
  // SIZES (Tailles standardisées)
  // ============================================================================

  /// Tailles d'icônes
  static const double iconSizeXs = 16.0;
  static const double iconSizeSm = 20.0;
  static const double iconSizeMd = 24.0;
  static const double iconSizeLg = 32.0;
  static const double iconSizeXl = 48.0;
  static const double iconSize2xl = 64.0;

  /// Tailles d'avatars
  static const double avatarSizeXs = 24.0;
  static const double avatarSizeSm = 32.0;
  static const double avatarSizeMd = 40.0;
  static const double avatarSizeLg = 56.0;
  static const double avatarSizeXl = 72.0;
  static const double avatarSize2xl = 96.0;

  /// Hauteurs de boutons
  static const double buttonHeightSm = 36.0;
  static const double buttonHeightMd = 44.0;
  static const double buttonHeightLg = 52.0;

  /// Hauteurs de champs de saisie
  static const double inputHeightSm = 40.0;
  static const double inputHeightMd = 48.0;
  static const double inputHeightLg = 56.0;

  /// Tailles de FAB (Floating Action Button)
  static const double fabSizeSm = 48.0;
  static const double fabSizeMd = 56.0;
  static const double fabSizeLg = 64.0;

  // ============================================================================
  // OPACITIES (Opacités standardisées)
  // ============================================================================

  static const double opacityDisabled = 0.38;
  static const double opacityInactive = 0.54;
  static const double opacitySecondary = 0.7;
  static const double opacityPrimary = 0.87;
  static const double opacityFull = 1.0;

  // ============================================================================
  // Z-INDEX / ELEVATION
  // ============================================================================

  static const double elevationNone = 0.0;
  static const double elevationXs = 1.0;
  static const double elevationSm = 2.0;
  static const double elevationMd = 4.0;
  static const double elevationLg = 8.0;
  static const double elevationXl = 16.0;

  // ============================================================================
  // BREAKPOINTS (pour responsive design)
  // ============================================================================

  static const double breakpointMobile = 600.0;
  static const double breakpointTablet = 900.0;
  static const double breakpointDesktop = 1200.0;

  // ============================================================================
  // HELPER METHODS
  // ============================================================================

  /// Retourne les ombres appropriées selon le thème
  static List<BoxShadow> getShadow(
    BuildContext context,
    ShadowSize size,
  ) {
    final isDark = Theme.of(context).brightness == Brightness.dark;

    switch (size) {
      case ShadowSize.none:
        return shadowNone;
      case ShadowSize.sm:
        return isDark ? shadowSmDark : shadowSm;
      case ShadowSize.md:
        return isDark ? shadowMdDark : shadowMd;
      case ShadowSize.lg:
        return isDark ? shadowLgDark : shadowLg;
      case ShadowSize.xl:
        return shadowXl;
    }
  }

  /// Retourne un EdgeInsets avec padding uniforme
  static EdgeInsets paddingAll(double value) => EdgeInsets.all(value);

  /// Retourne un EdgeInsets avec padding horizontal
  static EdgeInsets paddingHorizontal(double value) =>
      EdgeInsets.symmetric(horizontal: value);

  /// Retourne un EdgeInsets avec padding vertical
  static EdgeInsets paddingVertical(double value) =>
      EdgeInsets.symmetric(vertical: value);

  /// Retourne un EdgeInsets avec padding screen standard
  static EdgeInsets get paddingScreen => const EdgeInsets.symmetric(
        horizontal: screenPaddingHorizontal,
        vertical: screenPaddingVertical,
      );

  /// Retourne un SizedBox avec hauteur
  static SizedBox verticalSpace(double height) => SizedBox(height: height);

  /// Retourne un SizedBox avec largeur
  static SizedBox horizontalSpace(double width) => SizedBox(width: width);
}

/// Énumération pour les tailles d'ombres
enum ShadowSize {
  none,
  sm,
  md,
  lg,
  xl,
}

/// Extensions pour faciliter l'utilisation du Design System
extension DesignSystemExtensions on BuildContext {
  /// Retourne les ombres selon le thème
  List<BoxShadow> shadow(ShadowSize size) => DesignSystem.getShadow(this, size);

  /// Retourne true si on est en mode sombre
  bool get isDarkMode => Theme.of(this).brightness == Brightness.dark;

  /// Retourne la largeur de l'écran
  double get screenWidth => MediaQuery.of(this).size.width;

  /// Retourne la hauteur de l'écran
  double get screenHeight => MediaQuery.of(this).size.height;

  /// Retourne true si on est sur mobile
  bool get isMobile => screenWidth < DesignSystem.breakpointMobile;

  /// Retourne true si on est sur tablette
  bool get isTablet =>
      screenWidth >= DesignSystem.breakpointMobile &&
      screenWidth < DesignSystem.breakpointTablet;

  /// Retourne true si on est sur desktop
  bool get isDesktop => screenWidth >= DesignSystem.breakpointDesktop;
}
