import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:recording_tool/core/platform/app_platform_info.dart';
import 'package:recording_tool/core/platform/device_health_checker.dart';
import 'package:recording_tool/features/dialog/dialog-record.dart';
import 'package:recording_tool/features/recording/model/model_recording.dart';
import 'package:recording_tool/features/recording/platform/recording_platform.dart';
import 'package:recording_tool/features/recording/utils/recording_display_name.dart';
import 'package:recording_tool/features/recording/view-model/view_model_recording.dart';
import 'package:recording_tool/features/recording/widgets/widget_camera_preview.dart';
import 'package:recording_tool/features/recording/widgets/widget_record_footer.dart';
import 'package:recording_tool/features/recording/widgets/widget_record_header.dart';
import 'package:recording_tool/features/recording/widgets/widget_record_timer.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_hud.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_loading_overlay.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_saved_dialog.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_touch_lock_overlay.dart';
import 'package:recording_tool/shared/widgets/widgets.dart';

/// 录制页入口
class RecordingPage extends ConsumerStatefulWidget {
  const RecordingPage({super.key});

  @override
  /// 创建页面状态
  ConsumerState<RecordingPage> createState() => _RecordingPageState();
}

class _RecordingPageState extends ConsumerState<RecordingPage> {
  var _immersiveApplied = false;

  @override
  /// 首帧后初始化录制流程
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => _bootstrap());
  }

  /// 检查设备健康状态并弹窗提示
  Future<void> _checkAndShowDeviceHealthAlerts() async {
    final snapshot = await AppPlatformInfo.deviceHealth();
    if (!mounted) return;

    final lines = DeviceHealthChecker.warningLines(snapshot);
    if (lines.isEmpty) return;

    await RecordDialog.showSingle(
      context,
      title: lines.join('\n'),
      buttonText: '确定',
    );
  }

  /// 页面启动：健康检查、读剪贴板、进入录制模式、准备相机会话
  Future<void> _bootstrap() async {
    await _checkAndShowDeviceHealthAlerts();
    if (!mounted) return;

    final clipboardResult = await ref
        .read(recordingViewModelProvider.notifier)
        .getClipboardContent();
    if (!mounted) return;
    if (clipboardResult == ClipboardReadResult.invalid) {
      AppToast.show('无选手信息');
    }
    await _enterRecordingMode();
    // Allow PlatformView to attach before binding CameraX preview.
    await Future<void>.delayed(const Duration(milliseconds: 400));
    if (!mounted) return;
    await ref.read(recordingViewModelProvider.notifier).prepareSession();
  }

  /// Android 进入沉浸式全屏
  Future<void> _enterRecordingMode() async {
    if (!Platform.isAndroid) return;
    await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
    await RecordingPlatform.setImmersiveMode(enabled: true);
    _immersiveApplied = true;
  }

  /// 解析保存成功弹窗的标题文案
  String _savedDialogSessionTitle(
    RecordingModel recordingInfo,
    String? savedName,
  ) {
    final clipboard = recordingInfo.clipboardRecordingModel;
    if (recordingInfo.hasValidClipboardInfo &&
        clipboard.title.trim().isNotEmpty) {
      return clipboard.title.trim();
    }
    if (savedName != null && savedName.isNotEmpty) {
      return resolveRecordingDisplayName(savedName);
    }
    return '录制完成';
  }

  /// 从剪贴板粘贴赛事信息（与 header「粘贴选手信息」一致）。
  Future<void> _pasteEventInfo() async {
    final result = await ref
        .read(recordingViewModelProvider.notifier)
        .getClipboardContent();
    if (!mounted) return;
    if (result != ClipboardReadResult.success) {
      AppToast.show('无选手信息');
    }
  }

  /// 无选手信息时弹窗提示
  Future<void> _showNoPlayerInfoDialog() {
    return RecordDialog.showSingle(
      context,
      title: '无选手信息！',
      buttonText: '粘贴',
      onPressed: _pasteEventInfo,
    );
  }

  /// 根据缺失权限生成弹窗文案。
  String _recordingPermissionDialogTitle(RecordingRequiredPermissions result) {
    if (!result.cameraGranted && !result.microphoneGranted) {
      return '录制需要开启相机和录音权限，请在系统设置中授权后重试';
    }
    if (!result.cameraGranted) {
      return '录制需要开启相机权限，请在系统设置中授权后重试';
    }
    return '录制需要开启录音权限，请在系统设置中授权后重试';
  }

  /// 开始录制前检测相机、录音权限，未授予则弹窗并跳转系统设置。
  Future<bool> _ensureRecordingPermissions() async {
    final result = await ref
        .read(recordingViewModelProvider.notifier)
        .ensureCameraAndMicrophonePermissions();
    if (result.allGranted) {
      final ready = ref.read(recordingViewModelProvider).session.isPreviewReady;
      if (ready) return true;
      if (!mounted) return false;
      AppToast.show('相机预览启动失败，请重试');
      return false;
    }
    if (!mounted) return false;

    await RecordDialog.showSingle(
      context,
      title: _recordingPermissionDialogTitle(result),
      buttonText: '确定',
      onPressed: openAppSettings,
    );
    return false;
  }

  /// 点击开始录制：校验剪贴板、权限与健康状态
  Future<void> _onStartRecording() async {
    final recordingInfo = ref.read(recordingViewModelProvider);
    if (!recordingInfo.hasClipboardFilename) {
      await _showNoPlayerInfoDialog();
      return;
    }
    if (!await _ensureRecordingPermissions()) return;
    if (!mounted) return;
    await _checkAndShowDeviceHealthAlerts();
    if (!mounted) return;
    await ref.read(recordingViewModelProvider.notifier).startRecording();
  }

  /// 停止录制并按结果显示保存提示。
  Future<void> _stopRecordingAndShowResult() async {
    await ref.read(recordingViewModelProvider.notifier).stopRecording();
    if (!mounted) return;
    final latest = ref.read(recordingViewModelProvider).session;
    if (latest.gallerySaveFailed) {
      AppToast.show(latest.errorMessage ?? '保存到相册失败，请开启相册权限');
      return;
    }
    await _showRecordingSavedDialogIfNeeded();
  }

  /// 清空剪贴板信息，准备新一轮录制
  void _clearClipboardForNewRound() {
    final notifier = ref.read(recordingViewModelProvider.notifier);
    notifier.resetClipboardInfo();
    notifier.clearSavedRecordingResult();
  }

  /// 保存成功后按需弹出完成对话框
  Future<void> _showRecordingSavedDialogIfNeeded() async {
    final recordingInfo = ref.read(recordingViewModelProvider);
    final session = recordingInfo.session;
    if (session.lastSavedDisplayName == null || session.gallerySaveFailed) {
      return;
    }

    final sessionTitle = _savedDialogSessionTitle(
      recordingInfo,
      session.lastSavedDisplayName,
    );

    await showRecordingSavedDialog(
      context,
      sessionTitle: sessionTitle,
      onContinueRound: () {
        ref
            .read(recordingViewModelProvider.notifier)
            .clearSavedRecordingResult();
      },
      onRecordNewRound: _clearClipboardForNewRound,
    );
  }

  /// 退出沉浸式并释放录制会话
  Future<void> _exitRecordingMode() async {
    if (!_immersiveApplied) return;
    await ref.read(recordingViewModelProvider.notifier).teardown();
    await SystemChrome.setEnabledSystemUIMode(
      SystemUiMode.manual,
      overlays: SystemUiOverlay.values,
    );
    await RecordingPlatform.setImmersiveMode(enabled: false);
    _immersiveApplied = false;
  }

  @override
  /// 页面销毁时恢复系统 UI
  void dispose() {
    if (_immersiveApplied) {
      SystemChrome.setEnabledSystemUIMode(
        SystemUiMode.manual,
        overlays: SystemUiOverlay.values,
      );
      RecordingPlatform.setImmersiveMode(enabled: false);
    }
    super.dispose();
  }

  @override
  /// 构建录制页 UI
  Widget build(BuildContext context) {
    return _RecordingPopScope(
      onExitRecordingMode: _exitRecordingMode,
      child: Scaffold(
        backgroundColor: Colors.black,
        body: Column(
          children: [
            _RecordHeaderSection(
              onPasteEventInfo: _pasteEventInfo,
              onClearEventInfo: _clearClipboardForNewRound,
            ),
            Expanded(
              child: Stack(
                children: [
                  const CameraPreviewWidget(),
                  const _PreviewLoadingLayer(),
                  const RecordTimerWidget(),
                  _RecordingHudLayer(
                    onStart: _onStartRecording,
                    onStop: _stopRecordingAndShowResult,
                  ),
                  _TouchLockOverlayLayer(
                    onStopRecording: _stopRecordingAndShowResult,
                  ),
                  const _StartingRecordingOverlay(),
                ],
              ),
            ),
            const RecordFooter(),
          ],
        ),
      ),
    );
  }
}

class _RecordingPopScope extends ConsumerWidget {
  const _RecordingPopScope({
    required this.onExitRecordingMode,
    required this.child,
  });

  final Future<void> Function() onExitRecordingMode;
  final Widget child;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isRecording = ref.watch(
      recordingViewModelProvider.select((m) => m.session.isRecording),
    );

    return PopScope(
      canPop: !isRecording,
      onPopInvokedWithResult: (didPop, result) async {
        if (didPop) {
          await onExitRecordingMode();
          return;
        }
        if (isRecording) {
          AppToast.show('录制中无法返回，请先停止录制');
        }
      },
      child: child,
    );
  }
}

class _RecordHeaderSection extends ConsumerWidget {
  const _RecordHeaderSection({
    required this.onPasteEventInfo,
    required this.onClearEventInfo,
  });

  final Future<void> Function() onPasteEventInfo;
  final VoidCallback onClearEventInfo;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final headerState = ref.watch(
      recordingViewModelProvider.select(
        (m) => (
          m.hasValidClipboardInfo,
          m.hasValidClipboardInfo ? m.clipboardRecordingModel.title : null,
          m.session.isRecording,
        ),
      ),
    );
    final (hasValidClipboardInfo, eventTitle, isRecording) = headerState;

    return RecordHeaderWidget(
      hasValidClipboardInfo: hasValidClipboardInfo,
      eventTitle: eventTitle,
      isRecording: isRecording,
      onPasteEventInfo: onPasteEventInfo,
      onClearEventInfo: onClearEventInfo,
    );
  }
}

class _PreviewLoadingLayer extends ConsumerWidget {
  const _PreviewLoadingLayer();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final showLoading = ref.watch(
      recordingViewModelProvider.select(
        (m) => !m.session.isPreviewReady && m.session.errorMessage == null,
      ),
    );

    if (!showLoading) {
      return const SizedBox.shrink();
    }

    return const RecordingLoadingOverlayWidget(message: '正在启动相机…');
  }
}

class _RecordingHudLayer extends ConsumerWidget {
  const _RecordingHudLayer({required this.onStart, required this.onStop});

  final Future<void> Function() onStart;
  final Future<void> Function() onStop;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final hudState = ref.watch(
      recordingViewModelProvider.select(
        (m) => (
          m.session.errorMessage,
          m.session.permissionWarning,
          m.session.hasDndAccess,
          m.session.isBatteryOptimizedIgnored,
          m.session.notificationsGranted,
          m.session.isRecording,
          m.session.isStartingRecording,
          m.session.isTouchLocked,
          m.session.zoomRatio,
          m.session.minZoomRatio,
          m.session.maxZoomRatio,
          m.hasValidClipboardInfo,
          m.clipboardRecordingModel.address.trim(),
        ),
      ),
    );
    final (
      errorMessage,
      permissionWarning,
      hasDndAccess,
      isBatteryOptimizedIgnored,
      notificationsGranted,
      isRecording,
      isStartingRecording,
      isTouchLocked,
      zoomRatio,
      minZoomRatio,
      maxZoomRatio,
      showClipboardHint,
      clipboardAddress,
    ) = hudState;
    final viewModel = ref.read(recordingViewModelProvider.notifier);

    return RecordingHudWidget(
      errorMessage: errorMessage,
      permissionWarning: permissionWarning,
      hasDndAccess: hasDndAccess,
      isBatteryOptimizedIgnored: isBatteryOptimizedIgnored,
      notificationsGranted: notificationsGranted,
      isRecording: isRecording,
      isStartingRecording: isStartingRecording,
      isTouchLocked: isTouchLocked,
      zoomRatio: zoomRatio,
      minZoomRatio: minZoomRatio,
      maxZoomRatio: maxZoomRatio,
      showClipboardHint: showClipboardHint,
      clipboardAddress: clipboardAddress,
      onStart: onStart,
      onStop: onStop,
      onOpenDnd: () async {
        await viewModel.openDndSettings();
        await viewModel.refreshDndAccess();
      },
      onOpenBattery: () async {
        await viewModel.openBatterySettings();
        await viewModel.refreshBatteryOptimization();
      },
      onToggleTouchLock: () {
        final locked = ref
            .read(recordingViewModelProvider)
            .session
            .isTouchLocked;
        viewModel.setTouchLocked(!locked);
      },
      onZoomSelected: (ratio) async {
        await viewModel.setZoomRatio(ratio);
      },
    );
  }
}

class _TouchLockOverlayLayer extends ConsumerWidget {
  const _TouchLockOverlayLayer({required this.onStopRecording});

  final Future<void> Function() onStopRecording;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final overlayState = ref.watch(
      recordingViewModelProvider.select(
        (m) => (m.session.isTouchLocked, m.session.isRecording),
      ),
    );
    final (isTouchLocked, isRecording) = overlayState;

    if (!isTouchLocked || !isRecording) {
      return const SizedBox.shrink();
    }

    final viewModel = ref.read(recordingViewModelProvider.notifier);

    return RecordingTouchLockOverlayWidget(
      enabled: true,
      onUnlocked: (intent) async {
        viewModel.setTouchLocked(false);
        if (intent == RecordingTouchLockUnlockIntent.stopRecording) {
          await onStopRecording();
        }
      },
    );
  }
}

class _StartingRecordingOverlay extends ConsumerWidget {
  const _StartingRecordingOverlay();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isStartingRecording = ref.watch(
      recordingViewModelProvider.select((m) => m.session.isStartingRecording),
    );

    if (!isStartingRecording) {
      return const SizedBox.shrink();
    }

    return RecordingLoadingOverlayWidget(
      message: '正在开始录制…',
      backgroundColor: Colors.black.withValues(alpha: 0.24),
    );
  }
}
