import 'dart:io';

import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart';
import 'package:puzzleweave/audio/jc_audio_controller.dart';
import 'package:puzzleweave/l10n/app_localizations.dart';
import 'package:puzzleweave/settings/settings_controller.dart';
import 'package:puzzleweave/skin/skin.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:launch_review_latest/launch_review_latest.dart';

class SettingScreen extends StatefulWidget {
  const SettingScreen({super.key});

  @override
  State<StatefulWidget> createState() => _SettingScreenState();

  static PageRouteBuilder buildRoute() {
    return PageRouteBuilder(
      pageBuilder: (context, animation, secondaryAnimation) {
        return const SettingScreen();
      },
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        return SlideTransition(
          position: Tween(begin: const Offset(1, 0), end: Offset.zero).animate(animation),
          child: child,
        );
      },
    );
  }
}

class _SettingScreenState extends State<SettingScreen> {
  List<List<SettingItem>>? configs;

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

  @override
  didChangeDependencies() {
    super.didChangeDependencies();
    final settings = context.watch<SettingsController>();
    configs = [
      [
        SettingItem(
          SettingItemType.toggle,
          Icons.volume_up_rounded,
          AppLocalizations.of(context)!.sound,
          onToggle: (val) {
            settings.toggleSound();
          },
          toggleValue: () => settings.sound.value,
        ),
        SettingItem(
          SettingItemType.toggle,
          Icons.audiotrack_rounded,
          AppLocalizations.of(context)!.backgroundMusic,
          onToggle: (val) {
            settings.toggleMusic();
          },
          toggleValue: () => settings.music.value,
        ),
        SettingItem(
          SettingItemType.toggle,
          Icons.vibration_rounded,
          AppLocalizations.of(context)!.touchFeedback,
          onToggle: (val) {
            settings.toggleVibrate();
          },
          toggleValue: () => settings.vibrate.value,
        ),
      ],
      [
        SettingItem(SettingItemType.action, Icons.reviews_rounded, AppLocalizations.of(context)!.giveMeAReview, action: _launchReview),
        SettingItem(SettingItemType.action, Icons.pest_control_rounded, AppLocalizations.of(context)!.bugReport, action: _bugReportAction),
        SettingItem(SettingItemType.action, Icons.add_comment_rounded, AppLocalizations.of(context)!.featureRequest, action: _featureRequest),
      ],
      [
        SettingItem(
          SettingItemType.action,
          Icons.info_rounded,
          AppLocalizations.of(context)!.termOfService,
          action: () {
            _linkLaunch('https://longreachai.net/game/terms_of_service.html');
          },
        ),
        SettingItem(
          SettingItemType.action,
          Icons.description_rounded,
          AppLocalizations.of(context)!.privacyPolicy,
          action: () {
            _linkLaunch('https://longreachai.net/game/privacy_policy.html');
          },
        ),
      ],
    ];
  }

  Future<String> _versionInfo() async {
    final pkgInfo = await PackageInfo.fromPlatform();
    final output = {
      'OS Version': '${Platform.operatingSystem} ${Platform.operatingSystemVersion} ',
      'App Version': '${pkgInfo.version} ${pkgInfo.buildNumber}',
    };

    return output.keys.map((e) => '$e: ${output[e]}').join("<br/>");
  }

  _bugReportAction() async {
    final infos = await _versionInfo();
    Uri url = Uri(scheme: 'mailto', path: 'whippanyplex@outlook.com', query: 'subject=Bug Report - Jigsort Solitaire &body=<br/>------------------<br/>$infos');
    if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
      throw Exception('Could not launch $url');
    }
  }

  _featureRequest() async {
    Uri url = Uri(scheme: 'mailto', path: 'whippanyplex@outlook.com', query: 'subject=Feature Request - Jigsort Solitaire');
    if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
      throw Exception('Could not launch $url');
    }
  }

  _linkLaunch(String link) async {
    Uri url = Uri.parse(link);
    if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
      throw Exception('Could not launch $url');
    }
  }

  _launchReview() {
    LaunchReviewLatest.launch(androidAppId: 'jigsort.solitaire.jigsaw.match.games', iOSAppId: '6499138123');
  }

  @override
  Widget build(BuildContext context) {
    final audio = context.read<JcAudioController>();
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        centerTitle: true,
        title: Text(
          AppLocalizations.of(context)!.setting,
          style: TextStyle(color: Colors.black87, fontWeight: FontWeight.bold, fontSize: 24),
        ),
        elevation: 1,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back_outlined, color: Colors.black87),
          onPressed: () {
            audio.playSfx(SfxType.click);
            Navigator.pop(context);
          },
        ),
      ),
      body: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: Padding(
          padding: const EdgeInsets.all(10),
          child: Column(children: _buildAll(configs!)),
        ),
      ),
    );
  }

  List<Widget> _buildAll(List<List<SettingItem>> groups) {
    return groups.map((e) => _buildGroup(e)).toList();
  }

  Widget _buildGroup(List<SettingItem> list) {
    return Padding(
      padding: const EdgeInsets.only(top: 10),
      child: Material(
        elevation: 1,
        borderRadius: BorderRadius.circular(10),
        child: Padding(
          padding: const EdgeInsets.all(10),
          child: Column(children: list.map((e) => _buildItem(e)).toList()),
        ),
      ),
    );
  }

  Widget _buildItem(SettingItem item) {
    final audio = context.read<JcAudioController>();
    return Row(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Icon(item.icon, color: item.iconColor, size: 24),
        if (item.type == SettingItemType.toggle)
          Expanded(
            child: Padding(
              padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
              // child: Text(item.text, style: TextStyle(color: item.textColor, fontWeight: FontWeight.bold)),
              child: TextButton(
                onPressed: null,
                style: TextButton.styleFrom(padding: EdgeInsets.zero, alignment: Alignment.centerLeft),
                child: Text(item.text, style: TextStyle(color: item.textColor, fontSize: 16)),
              ),
            ),
          ),
        if (item.type == SettingItemType.dropdown)
          Expanded(
            child: Padding(
              padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
              child: TextButton(
                onPressed: null,
                style: TextButton.styleFrom(padding: EdgeInsets.zero, alignment: Alignment.centerLeft),
                child: Text(item.text, style: TextStyle(color: item.textColor, fontSize: 16)),
              ),
            ),
          ),
        if (item.type == SettingItemType.action)
          Expanded(
            child: Padding(
              padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
              child: SizedBox(
                width: double.infinity,
                child: TextButton(
                  onPressed: () {
                    audio.playSfx(SfxType.click);
                    item.action?.call();
                  },
                  style: TextButton.styleFrom(padding: EdgeInsets.zero, alignment: Alignment.centerLeft),
                  child: Text(item.text, style: TextStyle(color: item.textColor, fontSize: 16)),
                ),
              ),
            ),
          ),
        if (item.type == SettingItemType.toggle)
          Switch(
            activeTrackColor: SkinHelper.color5,
            inactiveTrackColor: Colors.white,
            inactiveThumbColor: SkinHelper.color4,
            value: item.toggleValue?.call() ?? false,
            onChanged: (value) {
              audio.playSfx(SfxType.click);
              item.onToggle?.call(value);
              setState(() {});
            },
          ),
        if (item.type == SettingItemType.dropdown)
          DropdownButton(
            value: item.dropdownValue?.call() ?? 0,
            items: (item.dropdownList?.call())!.map((e) => DropdownMenuItem(value: e, child: Text(e.toString()))).toList(),
            onChanged: (value) {
              audio.playSfx(SfxType.click);
              item.onDropdown?.call(value ?? 0);
              setState(() {});
            },
          ),
      ],
    );
  }
}

enum SettingItemType { toggle, action, dropdown }

typedef ToggleCallback = Function(bool val);
typedef ToggleValueGetter = bool Function();
typedef DropdownCallback = Function(int val);
typedef DropdownValueGetter = int Function();
typedef DropdownListGetter = List<int> Function();

class SettingItem {
  final SettingItemType type;
  final IconData icon;
  final String text;
  final String? configKey;
  ToggleCallback? onToggle;
  ToggleValueGetter? toggleValue;

  VoidCallback? action;

  DropdownCallback? onDropdown;
  DropdownValueGetter? dropdownValue;
  DropdownListGetter? dropdownList;

  Color iconColor;
  Color textColor;

  SettingItem(
    this.type,
    this.icon,
    this.text, {
    this.configKey,
    this.iconColor = const Color.fromARGB(255, 8, 66, 9),
    this.textColor = Colors.black87,
    this.action,
    this.onToggle,
    this.toggleValue,
    this.onDropdown,
    this.dropdownList,
    this.dropdownValue,
  });
}
