import 'dart:math' as math;

import 'package:flutter/material.dart'; // These are the Viewport values of your Figma Design.

// These are used in the code as a reference to create your UI Responsively.
const num figmaDesignWidth = 430; // iPhone X / 12 base width, 375
const num figmaDesignHeight = 927; // iPhone X / 12 base height 812

const num figmaDesignWidthTF = 375;
const num figmaDesignHeightTF = 812;

extension ConstrainedResponsive on num {
  /// Width with max cap for tablets
  double get wCapped => isTablet ? math.min(w, this * 1.3) : w;

  /// Height with max cap for tablets
  double get hCapped => isTablet ? math.min(h, this * 1.3) : h;
}

extension ResponsiveExtension on num {
  double get _screenWidth => SizeUtils.width;

  double get _screenHeight => SizeUtils.height;

  /// Check if device is likely a foldable
  bool get _isFoldable {
    double aspectRatio = _screenWidth / _screenHeight;
    double shorterSide = _screenWidth < _screenHeight ? _screenWidth : _screenHeight;

    // Foldable devices (unfolded) typically have:
    // - Shorter side > 600 logical pixels (to exclude regular phones)
    // - Aspect ratio between 0.80 and 0.92 (almost square, like Galaxy Z Fold)
    // Galaxy Z Fold 5: 1812x2176 physical, ~690x796 logical = 0.866 aspect ratio
    // Regular phones: typically 375-430 width, aspect ratio 0.45-0.55
    return (shorterSide > 600) && (aspectRatio > 0.80 && aspectRatio < 0.92);
  }

  /// Scale text size - enhanced for foldable devices
  double get f {
    double aspectRatio = _screenWidth / _screenHeight;
    double scale = (_screenWidth < _screenHeight ? _screenWidth : _screenHeight) / figmaDesignWidth;

    // Enhanced clamping for different device types
    double clamp;
    if (SizeUtils.deviceType == DeviceType.tablet || _isFoldable) {
      if (SizeUtils.deviceType != DeviceType.tablet && _isFoldable) {
        // clamp = (aspectRatio > 1.5 || aspectRatio < 0.67) ? 1.4 : 1.4;
        clamp = 1.1;
      } else {
        // More conservative scaling for tablets and foldables
        clamp = (aspectRatio > 1.5 || aspectRatio < 0.67) ? 1.6 : 1.4;
      }
    } else {
      // Original logic for phones
      clamp = (aspectRatio > 1.3 || aspectRatio < 0.77) ? 1.6 : 1.2;
    }

    if (scale > clamp) scale = clamp;
    return this * scale;
  }

  /// Scale horizontally (width-based) - enhanced for foldable devices
  double get w {
    double baseScale = (this * _screenWidth) / figmaDesignWidth;

    if (_isFoldable || isTablet) {
      // For foldables, use more conservative width scaling
      double scale = _screenWidth / figmaDesignWidthTF;
      scale = scale.clamp(0.8, 1.4);
      return this * scale;
    }

    return baseScale;
  }

  /// Scale vertically (height-based) - enhanced for foldable devices
  double get h {
    double baseScale = (this * _screenHeight) / figmaDesignHeight;

    if (_isFoldable || isTablet) {
      // For foldables, use height-based scaling but with constraints
      double scale = (_screenHeight / figmaDesignHeightTF).clamp(0.8, 1.4);
      return this * scale;
    }

    return baseScale;
  }

  /// Radius - enhanced for foldable devices
  double get r {
    double baseScale = (this * _screenWidth) / figmaDesignWidth;

    if (_isFoldable || isTablet) {
      // Use the same logic as enhanced width for foldables
      double scale = _screenWidth / figmaDesignWidthTF;
      scale = scale.clamp(0.8, 1.4);
      return this * scale;
    }

    return baseScale;
  }

  // New enhanced getters (additional options)

  /// Enhanced font scaling with device-specific adjustments
  double get fh {
    double baseScale = _screenHeight / figmaDesignHeight;

    if (_isFoldable) {
      // Special handling for foldable devices - use more conservative scaling
      baseScale = baseScale.clamp(0.8, 1.3);
    } else if (SizeUtils.deviceType == DeviceType.tablet) {
      // Tablet-specific scaling
      baseScale = baseScale.clamp(0.9, 1.5);
    } else {
      // Phone scaling
      baseScale = baseScale.clamp(0.8, 1.8);
    }

    return this * baseScale;
  }

  /// Adaptive scaling - automatically chooses best scaling method
  double get adaptive {
    if (_isFoldable) {
      return fh;
    } else if (SizeUtils.deviceType == DeviceType.tablet) {
      return f * 0.9; // Slightly smaller for tablets
    }
    return f;
  }

  /// Minimum size constraint (useful for touch targets)
  double get minSize {
    double scaled = adaptive;
    return scaled < 44 ? 44 : scaled; // Minimum 44pt for accessibility
  }

  /// Optional: direct accessors for full width/height
  static double get screenWidth => SizeUtils.width;

  static double get screenHeight => SizeUtils.height;
}

extension FormatExtension on double {
  double toDoubleValue({int fractionDigits = 2}) {
    return double.parse(toStringAsFixed(fractionDigits));
  }

  double isNonZero({num defaultValue = 0.0}) {
    return this > 0 ? this : defaultValue.toDouble();
  }
}

enum DeviceType { mobile, tablet, desktop }

typedef ResponsiveBuild = Widget Function(
  BuildContext context,
  Orientation orientation,
  DeviceType deviceType,
);

class Sizer extends StatelessWidget {
  const Sizer({super.key, required this.builder});

  /// Builds the widget whenever the orientation changes.
  final ResponsiveBuild builder;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        return OrientationBuilder(
          builder: (context, orientation) {
            SizeUtils.setScreenSize(constraints, orientation);
            return builder(context, orientation, SizeUtils.deviceType);
          },
        );
      },
    );
  }
}

// ignore_for_file: must_be_immutable
class SizeUtils {
  /// Device's BoxConstraints
  static late BoxConstraints boxConstraints;

  /// Device's Orientation
  static late Orientation orientation;

  /// Type of Device
  ///
  /// This can either be mobile or tablet
  static late DeviceType deviceType;

  /// Device's Height
  static double height = 667;

  /// Device's Width
  static double width = 375;

  static void setScreenSize(BoxConstraints constraints, Orientation currentOrientation) {
    boxConstraints = constraints;
    orientation = currentOrientation;

    double screenWidth;
    double screenHeight;

    if (orientation == Orientation.portrait) {
      screenWidth = boxConstraints.maxWidth.isNonZero(
        defaultValue: figmaDesignWidth,
      );
      screenHeight = boxConstraints.maxHeight.isNonZero();
    } else {
      screenWidth = boxConstraints.maxHeight.isNonZero(
        defaultValue: figmaDesignWidth,
      );
      screenHeight = boxConstraints.maxWidth.isNonZero();
    }

    width = screenWidth;
    height = screenHeight;

    // Fix device type detection
    double longerSide = screenWidth > screenHeight ? screenWidth : screenHeight;
    double shorterSide = screenWidth < screenHeight ? screenWidth : screenHeight;

    if (longerSide >= 1200) {
      deviceType = DeviceType.tablet;
    } else if (shorterSide >= 700) {
      // Use shorter side to distinguish tablets (iPads typically have 768+ width)
      deviceType = DeviceType.tablet;
    } else {
      deviceType = DeviceType.mobile;
    }

    debugPrint("============ Device Detection ============");
    debugPrint("longerSide: $longerSide");
    debugPrint("shorterSide: $shorterSide");
    debugPrint("width: $width");
    debugPrint("height: $height");
    debugPrint("deviceType: $deviceType");
    debugPrint("isTablet: $isTablet");
    debugPrint("isFoldable: $isFoldable");
    debugPrint("aspectRatio: ${width / height}");
    debugPrint("==========================================");
  }
}

// Or create a helper method
bool get isTablet => SizeUtils.deviceType == DeviceType.tablet;

bool get isMobile => SizeUtils.deviceType == DeviceType.mobile;

bool get isDesktop => SizeUtils.deviceType == DeviceType.desktop;

bool get isFoldable {
  double aspectRatio = SizeUtils.width / SizeUtils.height;
  double shorterSide = SizeUtils.width < SizeUtils.height ? SizeUtils.width : SizeUtils.height;

  // Foldable devices (unfolded) typically have:
  // - Shorter side > 600 logical pixels (to exclude regular phones)
  // - Aspect ratio between 0.80 and 0.92 (almost square, like Galaxy Z Fold)
  // Galaxy Z Fold 5: 1812x2176 physical, ~690x796 logical = 0.866 aspect ratio
  // Regular phones: typically 375-430 width, aspect ratio 0.45-0.55
  return (shorterSide > 600) && (aspectRatio > 0.80 && aspectRatio < 0.92);
}
