import 'dart:io';

import 'package:background_fetch/background_fetch.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/database/init.dart';
// import 'package:refilc/helpers/notification_helper.dart';
import 'package:refilc/models/settings.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:refilc/app.dart';
import 'package:flutter/services.dart';
import 'package:refilc/utils/service_locator.dart';
import 'package:refilc_mobile_ui/screens/error_screen.dart';
import 'package:refilc_mobile_ui/screens/error_report_screen.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:shake_flutter/models/shake_report_configuration.dart';
import 'package:shake_flutter/shake_flutter.dart';

import 'helpers/live_activity_helper.dart';

// days without touching grass: 5,843 (16 yrs)

void main() async {
  // Initalize
  WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
  // ignore: deprecated_member_use
  binding.renderView.automaticSystemUiAdjustment = false;
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  // navigation
  setupLocator();

  // Startup
  Startup startup = Startup();
  await startup.start();

  // Custom error page
  ErrorWidget.builder = errorBuilder;

  BackgroundFetch.registerHeadlessTask(backgroundHeadlessTask);

  // setting up things for shakebugs
  // List<ShakePickerItem> pickerItems = [
  //   ShakePickerItem('Bug', 'Hiba', tag: 'bug'),
  //   ShakePickerItem('Suggestion', 'Fejlesztési javaslat', tag: 'suggestion'),
  //   ShakePickerItem('Question', 'Kérdés', tag: 'question')
  // ];
  // ShakePicker picker =
  //     ShakePicker('Feedback type', 'Visszajelzés típusa', pickerItems);
  // ShakeTitle title = ShakeTitle('Title', 'Leírás', required: true);

  // ShakeInspectButton inspect = ShakeInspectButton();
  // ShakeAttachments attachments = ShakeAttachments();

  // List<ShakeFormComponent> components = [picker, title, inspect, attachments];
  // ShakeForm form = ShakeForm(components);

  // Shake.setShakeForm(form);

  // shakebugs initialization
  // Shake.setInvokeShakeOnScreenshot(true);
  Shake.start('Y44AwzfY6091xO2Nr0w59RHSpNxJhhiSFGs4enmoJwelN82ZRzTLE5X');

  // pre-cache required icons
  const todaySvg = SvgAssetLoader('assets/svg/menu_icons/today_selected.svg');
  const gradesSvg = SvgAssetLoader('assets/svg/menu_icons/grades_selected.svg');
  const timetableSvg =
      SvgAssetLoader('assets/svg/menu_icons/timetable_selected.svg');
  const notesSvg = SvgAssetLoader('assets/svg/menu_icons/notes_selected.svg');
  const absencesSvg =
      SvgAssetLoader('assets/svg/menu_icons/absences_selected.svg');

  svg.cache
      .putIfAbsent(todaySvg.cacheKey(null), () => todaySvg.loadBytes(null));
  svg.cache
      .putIfAbsent(gradesSvg.cacheKey(null), () => gradesSvg.loadBytes(null));
  svg.cache.putIfAbsent(
      timetableSvg.cacheKey(null), () => timetableSvg.loadBytes(null));
  svg.cache
      .putIfAbsent(notesSvg.cacheKey(null), () => notesSvg.loadBytes(null));
  svg.cache.putIfAbsent(
      absencesSvg.cacheKey(null), () => absencesSvg.loadBytes(null));

  // Run App
  runApp(App(
    database: startup.database,
    settings: startup.settings,
    user: startup.user,
  ));
}

class Startup {
  late SettingsProvider settings;
  late UserProvider user;
  late DatabaseProvider database;

  Future<void> start() async {
    database = DatabaseProvider();
    var db = await initDB(database);
    await db.close();
    await database.init();
    settings = await database.query.getSettings(database);
    user = await database.query.getUsers(settings);

    // Set all notification categories to seen to avoid having notifications that the user has already seen in the app
    // NotificationsHelper().setAllCategoriesSeen(user);

    late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
    // Notifications setup
    if (!kIsWeb) {
      initPlatformState();
      initAdditionalBackgroundFetch();
      flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    }

    // Get permission to show notifications
    if (kIsWeb) {
      // do nothing
    } else if (Platform.isAndroid) {
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()!
          .requestNotificationsPermission();
    } else if (Platform.isIOS) {
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              IOSFlutterLocalNotificationsPlugin>()
          ?.requestPermissions(
            alert: false,
            badge: true,
            sound: true,
          );
    } else if (Platform.isMacOS) {
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              MacOSFlutterLocalNotificationsPlugin>()
          ?.requestPermissions(
            alert: false,
            badge: true,
            sound: true,
          );
    } else if (Platform.isLinux) {
      // no permissions are needed on linux
    }

    // Platform specific settings
    if (!kIsWeb) {
      // const DarwinInitializationSettings initializationSettingsDarwin =
      //     DarwinInitializationSettings(
      //   requestSoundPermission: true,
      //   requestBadgePermission: true,
      //   requestAlertPermission: false,
      // );
      // const AndroidInitializationSettings initializationSettingsAndroid =
      //     AndroidInitializationSettings('ic_notification');
      // const LinuxInitializationSettings initializationSettingsLinux =
      //     LinuxInitializationSettings(defaultActionName: 'Open notification');
      // const InitializationSettings initializationSettings =
      //     InitializationSettings(
      //   android: initializationSettingsAndroid,
      //   iOS: initializationSettingsDarwin,
      //   macOS: initializationSettingsDarwin,
      //   linux: initializationSettingsLinux,
      // );

      // Initialize notifications
      // await flutterLocalNotificationsPlugin.initialize(
      //   initializationSettings,
      //   onDidReceiveNotificationResponse:
      //       NotificationsHelper().onDidReceiveNotificationResponse,
      // );
    }

    // if (Platform.isAndroid || Platform.isIOS) {
    //   await Firebase.initializeApp(
    //     options: DefaultFirebaseOptions.currentPlatform,
    //   );
    // }
  }
}

bool errorShown = false;
String lastException = '';

Widget errorBuilder(FlutterErrorDetails details) {
  return Builder(builder: (context) {
    if (Navigator.of(context).canPop()) Navigator.pop(context);

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!errorShown && details.exceptionAsString() != lastException) {
        errorShown = true;
        lastException = details.exceptionAsString();
        Navigator.of(context, rootNavigator: true)
            .push(MaterialPageRoute(builder: (context) {
          if (kReleaseMode) {
            // silent report to shakebugs
            ShakeReportConfiguration configuration = ShakeReportConfiguration();
            configuration.blackBoxData = true;
            configuration.activityHistoryData = true;
            configuration.screenshot = true;
            configuration.video = false;
            Shake.silentReport(
              configuration: configuration,
              description:
                  'Silent Report #${DateTime.now().year}${DateTime.now().month}${DateTime.now().day}',
            );
            // show error report screen
            return ErrorReportScreen(details);
          } else {
            return ErrorScreen(details);
          }
        })).then((_) => errorShown = false);
      }
    });

    return Container();
  });
}

Future<void> initPlatformState() async {
  // Configure BackgroundFetch.
  int status = await BackgroundFetch.configure(
      BackgroundFetchConfig(
          minimumFetchInterval: 15,
          stopOnTerminate: false,
          enableHeadless: true,
          requiresBatteryNotLow: false,
          requiresCharging: false,
          requiresStorageNotLow: false,
          requiresDeviceIdle: false,
          requiredNetworkType: NetworkType.ANY,
          startOnBoot: true), (String taskId) async {
    // <-- Event handler
    if (kDebugMode) {
      print("[BackgroundFetch] Event received $taskId");
    }
    if (taskId == "com.transistorsoft.refilcliveactivity") {
      if (!Platform.isIOS) return;
      LiveActivityHelper().backgroundJob();
    } else {
      // NotificationsHelper().backgroundJob();
    }
    BackgroundFetch.finish(taskId);
  }, (String taskId) async {
    // <-- Task timeout handler.
    if (kDebugMode) {
      print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
    }
    BackgroundFetch.finish(taskId);
  });
  if (kDebugMode) {
    print('[BackgroundFetch] configure success: $status');
  }
  BackgroundFetch.scheduleTask(TaskConfig(
      taskId: "com.transistorsoft.refilcnotification",
      delay: 900000, // 15 minutes
      periodic: true,
      forceAlarmManager: true,
      stopOnTerminate: false,
      enableHeadless: true));
}

@pragma('vm:entry-point')
void backgroundHeadlessTask(HeadlessTask task) {
  String taskId = task.taskId;
  bool isTimeout = task.timeout;
  if (isTimeout) {
    if (kDebugMode) {
      print("[BackgroundFetch] Headless task timed-out: $taskId");
    }
    BackgroundFetch.finish(taskId);
    return;
  }
  if (kDebugMode) {
    print('[BackgroundFetch] Headless event received.');
  }
  if (taskId == "com.transistorsoft.refilcliveactivity") {
    if (!Platform.isIOS) return;
    LiveActivityHelper().backgroundJob();
  } else {
    // NotificationsHelper().backgroundJob();
  }
  BackgroundFetch.finish(task.taskId);
}

Future<void> initAdditionalBackgroundFetch() async {
  int status = await BackgroundFetch.configure(
      BackgroundFetchConfig(
          minimumFetchInterval: 1, // 1 minute
          stopOnTerminate: false,
          enableHeadless: true,
          requiresBatteryNotLow: false,
          requiresCharging: false,
          requiresStorageNotLow: false,
          requiresDeviceIdle: false,
          requiredNetworkType: NetworkType.ANY,
          startOnBoot: true), (String taskId) async {
    // <-- Event handler

    if (kDebugMode) {
      print("[BackgroundFetch] Event received $taskId");
    }
    LiveActivityHelper liveActivityHelper = LiveActivityHelper();
    liveActivityHelper.backgroundJob();

    BackgroundFetch.finish(taskId);
  }, (String taskId) async {
    // <-- Task timeout handler.
    if (kDebugMode) {
      print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
    }
    BackgroundFetch.finish(taskId);
  });
  if (kDebugMode) {
    print('[BackgroundFetch] configure success: $status');
  }
  BackgroundFetch.scheduleTask(TaskConfig(
      taskId: "com.transistorsoft.refilcliveactivity",
      delay: 300000, // 5 minute
      periodic: true,
      forceAlarmManager: true,
      stopOnTerminate: false,
      enableHeadless: true));
}