import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:recording_tool/core/utils/rate_limiter.dart';
import 'package:recording_tool/features/recording/widgets/record_content_transition.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_button.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_context_clock_chip.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_setup_hints.dart';

/// 录制页 HUD 层（状态提示、录制控制）
class RecordingHudWidget extends StatelessWidget {
  const RecordingHudWidget({
    super.key,
    this.errorMessage,
    this.permissionWarning,
    required this.hasDndAccess,
    required this.isBatteryOptimizedIgnored,
    required this.notificationsGranted,
    required this.isRecording,
    required this.isStartingRecording,
    required this.isSwitchingLens,
    required this.isTouchLocked,
    this.showContextHint = false,
    this.contextAddress = '',
    required this.zoomRatio,
    required this.minZoomRatio,
    required this.maxZoomRatio,
    required this.onStart,
    required this.onStop,
    required this.onOpenDnd,
    required this.onOpenBattery,
    required this.onToggleTouchLock,
    required this.onZoomSelected,
  });

  final String? errorMessage;
  final String? permissionWarning;
  final bool hasDndAccess;
  final bool isBatteryOptimizedIgnored;
  final bool notificationsGranted;
  final bool isRecording;
  final bool isStartingRecording;
  final bool isSwitchingLens;
  final bool isTouchLocked;
  final bool showContextHint;
  final String contextAddress;
  final double zoomRatio;
  final double minZoomRatio;
  final double maxZoomRatio;
  final Future<void> Function() onStart;
  final Future<void> Function() onStop;
  final VoidCallback onOpenDnd;
  final VoidCallback onOpenBattery;
  final VoidCallback onToggleTouchLock;
  final ValueChanged<double> onZoomSelected;

  static double get _recordButtonSize => 70.r;
  static double get _recordButtonBottom => 63.r;
  static double get _overlayInfoLeft => 13.r;
  static double get _overlayInfoBottom => 10.r;

  @override
  Widget build(BuildContext context) {
    return Stack(
      fit: StackFit.expand,
      children: [
        Positioned(
          left: 0,
          right: 0,
          top: 0,
          bottom: _recordButtonBottom + _recordButtonSize + 16.h,
          child: Column(
            children: [
              SizedBox(height: 8.h),
              const Spacer(),
              if (errorMessage != null)
                Padding(
                  padding: EdgeInsets.all(12.r),
                  child: Text(
                    errorMessage!,
                    style: const TextStyle(color: Colors.amber),
                    textAlign: TextAlign.center,
                  ),
                ),
              if (permissionWarning != null)
                Padding(
                  padding: EdgeInsets.symmetric(
                    horizontal: 16.r,
                    vertical: 8.r,
                  ),
                  child: Text(
                    permissionWarning!,
                    style: TextStyle(
                      color: Colors.orangeAccent,
                      fontSize: 12.sp,
                    ),
                    textAlign: TextAlign.center,
                  ),
                ),
              RecordingSetupHintsWidget(
                hasDndAccess: hasDndAccess,
                isBatteryIgnored: isBatteryOptimizedIgnored,
                notificationsGranted: notificationsGranted,
                onOpenDnd: onOpenDnd,
                onOpenBattery: onOpenBattery,
                onOpenNotificationSettings: openAppSettings,
              ),
            ],
          ),
        ),
        Positioned(
          left: _overlayInfoLeft,
          bottom: _overlayInfoBottom,
          child: AnimatedSwitcher(
            duration: RecordContentTransition.duration,
            switchInCurve: Curves.easeOutCubic,
            switchOutCurve: Curves.easeInCubic,
            layoutBuilder: RecordContentTransition.bottomStackLayoutBuilder,
            transitionBuilder: RecordContentTransition.builder,
            child: showContextHint
                ? RecordingContextClockChipWidget(
                    key: const ValueKey('recording-context-info'),
                    address: contextAddress,
                  )
                : const SizedBox.shrink(
                    key: ValueKey('recording-context-info-hidden'),
                  ),
          ),
        ),
        if (isRecording)
          Positioned(
            left: 16.r,
            bottom: _recordButtonBottom,
            child: SizedBox(
              height: _recordButtonSize,
              child: Center(
                child: IconButton(
                  onPressed: onToggleTouchLock,
                  icon: Icon(
                    isTouchLocked ? Icons.lock : Icons.lock_open,
                    color: Colors.white,
                    size: 28.r,
                  ),
                ),
              ),
            ),
          ),
        Positioned(
          right: 16.r,
          bottom: 260.r,
          child: _ZoomPresetControl(
            enabled: !isSwitchingLens,
            zoomRatio: zoomRatio,
            minZoomRatio: minZoomRatio,
            maxZoomRatio: maxZoomRatio,
            presets: _zoomPresetsForRange(minZoomRatio),
            onSelected: onZoomSelected,
          ),
        ),
        Positioned(
          left: 0,
          right: 0,
          bottom: _recordButtonBottom,
          child: Center(
            child: RecordingControlButton(
              isRecording: isRecording,
              isStartingRecording: isStartingRecording,
              enabled: !isStartingRecording && !isSwitchingLens,
              size: _recordButtonSize,
              onTap: () {
                if (isRecording) {
                  RateLimit.instance.debounce<void>(
                    key: 'recording.session.stop',
                    value: null,
                    duration: Duration(milliseconds: 300),
                    onCallback: (_) async {
                      await onStop();
                    },
                  );
                } else {
                  RateLimit.instance.debounce<void>(
                    key: 'recording.session.start',
                    value: null,
                    duration: Duration(milliseconds: 300),
                    onCallback: (_) async {
                      await onStart();
                    },
                  );
                }
              },
            ),
          ),
        ),
      ],
    );
  }

  List<double> _zoomPresetsForRange(double minZoomRatio) {
    return [if (minZoomRatio < 1.0) minZoomRatio, 1.0];
  }
}

class _ZoomPresetControl extends StatelessWidget {
  const _ZoomPresetControl({
    required this.enabled,
    required this.zoomRatio,
    required this.minZoomRatio,
    required this.maxZoomRatio,
    required this.presets,
    required this.onSelected,
  });

  final bool enabled;
  final double zoomRatio;
  final double minZoomRatio;
  final double maxZoomRatio;
  final List<double> presets;
  final ValueChanged<double> onSelected;

  @override
  Widget build(BuildContext context) {
    final availablePresets = presets
        .where(_isPresetAvailable)
        .toList(growable: false);
    if (availablePresets.isEmpty) {
      return const SizedBox.shrink();
    }

    return DecoratedBox(
      decoration: BoxDecoration(
        color: Colors.black.withValues(alpha: 0.46),
        borderRadius: BorderRadius.circular(18.r),
        border: Border.all(color: Colors.white.withValues(alpha: 0.18)),
      ),
      child: Padding(
        padding: EdgeInsets.all(3.r),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            for (final preset in availablePresets)
              _ZoomPresetButton(
                displayRatio: preset,
                requestRatio: preset,
                selected: _isPresetSelected(preset),
                enabled: enabled,
                onSelected: onSelected,
              ),
          ],
        ),
      ),
    );
  }

  bool _isPresetAvailable(double preset) {
    if (preset < 1.0) {
      return minZoomRatio <= preset && maxZoomRatio >= preset;
    }
    return preset >= minZoomRatio && preset <= maxZoomRatio;
  }

  bool _isPresetSelected(double preset) {
    if (preset < 1.0) {
      return zoomRatio < 1.0;
    }
    return (zoomRatio - preset).abs() < 0.05;
  }
}

class _ZoomPresetButton extends StatelessWidget {
  const _ZoomPresetButton({
    required this.displayRatio,
    required this.requestRatio,
    required this.selected,
    required this.enabled,
    required this.onSelected,
  });

  final double displayRatio;
  final double requestRatio;
  final bool selected;
  final bool enabled;
  final ValueChanged<double> onSelected;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 1.r),
      child: TextButton(
        onPressed: selected || !enabled
            ? null
            : () => RateLimit.instance.debounce<void>(
                key:
                    'recording.session.zoom.${requestRatio.toStringAsFixed(1)}',
                value: null,
                duration: Duration(milliseconds: 300),
                onCallback: (_) async {
                  onSelected(requestRatio);
                },
              ),
        style: TextButton.styleFrom(
          minimumSize: Size(38.r, 32.r),
          padding: EdgeInsets.zero,
          tapTargetSize: MaterialTapTargetSize.shrinkWrap,
          foregroundColor: selected ? Colors.black : Colors.white,
          disabledForegroundColor: Colors.black,
          backgroundColor: selected ? Colors.white : Colors.transparent,
          disabledBackgroundColor: Colors.white,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15.r),
          ),
        ),
        child: Text(
          _formatZoomRatio(displayRatio),
          style: TextStyle(
            fontSize: 13.sp,
            fontWeight: FontWeight.w700,
            letterSpacing: 0,
          ),
        ),
      ),
    );
  }

  String _formatZoomRatio(double ratio) {
    if (ratio < 1.0) {
      return '广角';
    }
    if (ratio == ratio.roundToDouble()) {
      return '${ratio.toStringAsFixed(0)}x';
    }
    return '${ratio.toStringAsFixed(1)}x';
  }
}
