import 'dart:io';

import 'package:audioplayers/audioplayers.dart';
import 'package:background_downloader/background_downloader.dart';
import 'package:cross_file/cross_file.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hoshan/core/gen/assets.gen.dart';
import 'package:hoshan/core/services/api/dio_service.dart';
import 'package:hoshan/core/services/downloader/downloader_service.dart';
import 'package:hoshan/ui/theme/colors.dart';
import 'package:hoshan/ui/theme/text.dart';
import 'package:hoshan/ui/widgets/components/button/circle_icon_btn.dart';
import 'package:path_provider/path_provider.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:string_validator/string_validator.dart';

class MusicPlayer extends StatefulWidget {
  final String url;
  const MusicPlayer({super.key, required this.url});

  @override
  State<MusicPlayer> createState() => _MusicPlayerState();
}

class _MusicPlayerState extends State<MusicPlayer> {
  final player = AudioPlayer();
  dynamic fileSource;
  bool isReady = false;
  Duration? duration;

  final DownloaderService _downloadFileService = DownloaderService();

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((_) async {
      try {
        if (widget.url.isNotEmpty) {
          if (!widget.url.isURL()) {
            XFile? file = XFile(widget.url);
            fileSource = DeviceFileSource(file.path);
          } else {
            var fileName = widget.url.split('/').last;
            if (!fileName.endsWith('.mp3')) {
              fileName = '$fileName.mp3';
            }
            final directory = await getApplicationDocumentsDirectory();
            final file = File('${directory.path}/$fileName');
            if (await directory.exists() && await file.exists()) {
              fileSource = DeviceFileSource(file.path);
            }
          }
          if (fileSource != null) {
            try {
              await player.setSource(fileSource!);
            } catch (e) {
              if (kDebugMode) {
                print('Error in setSource: $e');
              }
            }
            duration = await player.getDuration();
            setState(() {
              isReady = true;
            });
          }
        }
      } catch (e) {
        if (kDebugMode) {
          print('Error in initState: $e');
        }
      }
    });
  }

  @override
  void dispose() {
    player.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (widget.url.isEmpty) {
      return const Text('Audio not found');
    }
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Row(
              children: [
                ValueListenableBuilder(
                    valueListenable: _downloadFileService.onStatus,
                    builder: (context, status, _) {
                      return status == TaskStatus.complete || isReady
                          ? StreamBuilder<PlayerState>(
                              stream: player.onPlayerStateChanged,
                              builder: (context, snapshot) {
                                return CircleIconBtn(
                                  icon: (snapshot.hasData ||
                                              !snapshot.hasError) &&
                                          snapshot.data == PlayerState.playing
                                      ? Assets.icon.bold.pause
                                      : Assets.icon.bold.play,
                                  color: Theme.of(context).colorScheme.primary,
                                  iconColor: Colors.white,
                                  iconPadding: const EdgeInsets.all(6),
                                  size: 32,
                                  onTap: () async {
                                    if (snapshot.data == PlayerState.playing) {
                                      await player.pause();
                                    } else if (snapshot.data ==
                                        PlayerState.paused) {
                                      await player.resume();
                                    } else {
                                      if (fileSource != null) {
                                        await player.play(fileSource!);
                                      }
                                    }
                                  },
                                );
                              })
                          : Container(
                              padding: const EdgeInsets.all(2),
                              decoration: BoxDecoration(
                                  shape: BoxShape.circle,
                                  color: Theme.of(context).colorScheme.primary),
                              child: InkWell(
                                onTap: () async {
                                  if (status == null) {
                                    final path = await _downloadFileService
                                        .downloadFile(widget.url);
                                    if (path != null) {
                                      XFile? file = XFile(path);
                                      fileSource = DeviceFileSource(file.path);
                                    }
                                    if (fileSource != null) {
                                      try {
                                        await player.setSource(fileSource!);
                                      } catch (e) {
                                        if (kDebugMode) {
                                          print('Error in setSource: $e');
                                        }
                                      }
                                      duration = await player.getDuration();
                                      setState(() {
                                        isReady = true;
                                      });
                                    }
                                  } else if (status == TaskStatus.running) {
                                    _downloadFileService.pauseDownload();
                                  } else {
                                    _downloadFileService.resumeDownload();
                                  }
                                },
                                child: ValueListenableBuilder(
                                  valueListenable:
                                      _downloadFileService.progressPer,
                                  builder: (context, progress, _) => progress ==
                                                  0 &&
                                              status != null &&
                                              status == TaskStatus.running ||
                                          progress < 0
                                      ? const SizedBox(
                                          width: 28,
                                          height: 28,
                                          child: Padding(
                                            padding: EdgeInsets.all(2.0),
                                            child: Stack(
                                              alignment: Alignment.center,
                                              children: [
                                                Icon(
                                                  Icons.download_rounded,
                                                  color: Colors.white,
                                                  size: 16,
                                                ),
                                                Positioned.fill(
                                                  child:
                                                      CircularProgressIndicator(
                                                    color: Colors.white,
                                                    strokeWidth: 2,
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ),
                                        )
                                      : CircularPercentIndicator(
                                          radius: 14.0,
                                          animation: true,
                                          animationDuration: 100,
                                          lineWidth: 2.0,
                                          percent: progress,
                                          animateFromLastPercent: true,
                                          center: status != null &&
                                                  status == TaskStatus.running
                                              ? Text(
                                                  (progress * 100)
                                                      .abs()
                                                      .round()
                                                      .toString(),
                                                  style: const TextStyle(
                                                      color: Colors.white,
                                                      fontSize: 10.0),
                                                )
                                              : const Icon(
                                                  Icons.download,
                                                  color: Colors.white,
                                                  size: 14,
                                                ),
                                          circularStrokeCap:
                                              CircularStrokeCap.round,
                                          backgroundColor: AppColors.gray[300],
                                          progressColor:
                                              AppColors.green.defaultShade,
                                        ),
                                ),
                              ),
                            );
                    }),
                const SizedBox(
                  width: 8,
                ),
                InkWell(
                  onTap: () async {
                    final pos = await player.getCurrentPosition();
                    if (pos != null) {
                      final targetPosition =
                          Duration(seconds: pos.inSeconds - 5);

                      await player.seek(targetPosition);
                    } else {
                      if (kDebugMode) {
                        print('Failed to get current position');
                      }
                    }
                  },
                  child: Container(
                    width: 32,
                    height: 32,
                    decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: Theme.of(context).colorScheme.primary),
                    child: const Icon(
                      Icons.replay_5_rounded,
                      color: Colors.white,
                      size: 22,
                    ),
                  ),
                ),
                const SizedBox(
                  width: 8,
                ),
                InkWell(
                  onTap: () async {
                    final pos = await player.getCurrentPosition();
                    if (pos != null) {
                      final targetPosition =
                          Duration(seconds: pos.inSeconds + 5);

                      await player.seek(targetPosition);
                    } else {
                      if (kDebugMode) {
                        print('Failed to get current position');
                      }
                    }
                  },
                  child: Container(
                    width: 32,
                    height: 32,
                    decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: Theme.of(context).colorScheme.primary),
                    child: const Icon(
                      Icons.forward_5_rounded,
                      color: Colors.white,
                      size: 22,
                    ),
                  ),
                ),
              ],
            ),
            InkWell(
              onTap: () {
                setState(() {
                  if (player.playbackRate == 2) {
                    player.setPlaybackRate(1);
                  } else {
                    player.setPlaybackRate(2);
                  }
                });
              },
              child: Text(
                player.playbackRate == 2 ? '2X' : '1X',
                style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 16,
                    color: Theme.of(context).colorScheme.primary),
              ),
            )
          ],
        ),
        const SizedBox(
          height: 16,
        ),
        if (isReady)
          Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              if (duration != null)
                SizedBox(
                  child: StreamBuilder<Duration>(
                      stream: player.onPositionChanged,
                      builder: (context, position) {
                        return Slider(
                          value: position.hasData && !position.hasError
                              ? position.data!.inMilliseconds.toDouble()
                              : 0,
                          onChanged: (value) {
                            player.seek(Duration(milliseconds: value.round()));
                          },
                          min: 0,
                          max: duration!.inMilliseconds.toDouble(),
                        );
                      }),
                ),
              const SizedBox(
                height: 8,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  StreamBuilder<Duration>(
                      stream: player.onPositionChanged,
                      builder: (context, snapshot) {
                        return Text(
                          snapshot.hasError ||
                                  !snapshot.hasData && snapshot.data == null
                              ? '00:00'
                              : '${snapshot.data!.inMinutes.remainder(60).toString().padLeft(2, '0')}:${(snapshot.data!.inSeconds.remainder(60)).toString().padLeft(2, '0')}',
                          style: AppTextStyles.body6.copyWith(
                              color: Theme.of(context).colorScheme.onSurface),
                        );
                      }),
                  Text(
                    duration == null
                        ? '00:00'
                        : '${duration!.inMinutes.remainder(60).toString().padLeft(2, '0')}:${(duration!.inSeconds.remainder(60)).toString().padLeft(2, '0')}',
                    style: AppTextStyles.body6.copyWith(
                        color: Theme.of(context).colorScheme.onSurface),
                  ),
                ],
              )
            ],
          ),
        if (widget.url.isURL())
          FutureBuilder(
              future: DioService.getFileSize(widget.url),
              builder: (context, size) {
                if (!size.hasData || size.hasError) {
                  return const SizedBox.shrink();
                }
                return SizedBox();
                // Container(
                //   padding: const EdgeInsets.all(8),
                //   decoration: BoxDecoration(
                //       color: Theme.of(context).colorScheme.primary,
                //       borderRadius: BorderRadius.circular(16)),
                //   child: Text(
                //     '${size.data} MB',
                //     style: const TextStyle(
                //         color: Colors.white,
                //         fontSize: 14,
                //         fontWeight: FontWeight.bold),
                //   ),
                // );
              })
      ],
    );
  }
}
