import 'dart:async';

import 'package:cross_file/cross_file.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:hoshan/core/gen/assets.gen.dart';
import 'package:hoshan/core/services/permission/permission_service.dart';
import 'package:hoshan/core/utils/date_time.dart';
import 'package:hoshan/ui/theme/colors.dart';
import 'package:hoshan/ui/theme/text.dart';
import 'package:hoshan/ui/widgets/components/audio/player.dart';
import 'package:hoshan/ui/widgets/components/button/circle_icon_btn.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

class Recorder extends StatefulWidget {
  final bool play;
  final Function(XFile) onRecordFinish;
  final Function()? onDelete;
  final Function(String?)? onError;
  const Recorder(
      {super.key,
      required this.play,
      this.onDelete,
      required this.onRecordFinish,
      this.onError});

  @override
  State<Recorder> createState() => _RecorderState();
}

class _RecorderState extends State<Recorder> {
  final recorder = FlutterSoundRecorder();
  bool isRecorderReady = false;
  String? path;
  Timer? timer;
  ValueNotifier<int> seconds = ValueNotifier(0);

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await initRecorder();
    });
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
    timer?.cancel();
  }

  Future initRecorder() async {
    final status = await PermissionService.getPermission(
        permission: Permission.microphone);
    if (!status) {
      widget.onError?.call('Permission Error');
      throw 'Permission Error';
    }

    await recorder.openRecorder();
    setState(() {
      isRecorderReady = true;
    });
    recorder.setSubscriptionDuration(const Duration(milliseconds: 500));
    if (widget.play) {
      await record();
    }
  }

  Future record() async {
    if (!isRecorderReady) return;
    try {
      final tempDir = await getTemporaryDirectory();
      final fileName = '${DateTime.now().millisecondsSinceEpoch ~/ 1000}.aac';
      final filePath = '${tempDir.path}/$fileName';

      if (kDebugMode) {
        print('Starting recording to: $filePath');
      }

      await recorder.startRecorder(
        toFile: filePath,
        codec: Codec.aacMP4,
      );
      timer = Timer.periodic(
        const Duration(seconds: 1),
        (timer) {
          seconds.value = seconds.value + 1;
        },
      );
    } catch (e) {
      widget.onError?.call('$e');

      if (kDebugMode) {
        print('record Error: $e');
      }
    }
  }

  Future recordStop() async {
    if (!isRecorderReady) return;
    timer?.cancel();
    path = await recorder.stopRecorder();
    if (path == null) {
      widget.onError?.call('record File Path Error');

      throw 'record File Path Error';
    }
    setState(() {});
    final XFile file = XFile(path!);
    widget.onRecordFinish(file);
    if (kDebugMode) {
      print("filePath: $path");
    }
  }

  void handleRecorder() async {
    if (recorder.isRecording) {
      await recordStop();
    } else {
      await record();
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return isRecorderReady
        ? SizedBox(
            height: 46,
            child: path != null
                ? Row(
                    children: [
                      Expanded(
                          child: Player(
                        fileUrl: path!,
                        onDelete: widget.onDelete,
                      )),
                    ],
                  )
                : Row(
                    children: [
                      CircleIconBtn(
                        icon: Assets.icon.bold.stop,
                        onTap: handleRecorder,
                      ),
                      const SizedBox(
                        width: 8,
                      ),
                      Expanded(
                        child: SizedBox(
                          height: 28,
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: List.generate(
                              6,
                              (index) => SpinKitWave(
                                color: AppColors.primaryColor.defaultShade,
                                size: 32,
                                itemCount: 10,
                              ),
                            ),
                          ),
                        ),
                      ),
                      const SizedBox(
                        width: 8,
                      ),
                      ValueListenableBuilder<int>(
                        valueListenable: seconds,
                        builder: (context, s, _) {
                          return Text(
                            DateTimeUtils.getTimeFromDuration(s),
                            style: AppTextStyles.body4.copyWith(
                                color: Theme.of(context).colorScheme.onSurface,
                                fontWeight: FontWeight.bold),
                          );
                        },
                      ),
                    ],
                  ),
          )
        : const SizedBox.shrink();
  }
}
