import 'dart:async';

import 'package:feet/notifications/tasks.dart';
import 'package:feet/util.dart';
import 'package:feet/widgets/centered_page_hint.dart';
import 'package:feet/widgets/filter_menu.dart';
import 'package:feet/widgets/homepage_post.dart';
import 'package:feet/widgets/login_prompt.dart';
import 'package:flutter/material.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'api/api.dart';

// Limit the maximum amount of posts to fetch so we don't wait forever when
// fetching a large list
const fetchMaxPosts = 1000;

// Store these globally so our notification handler can access them
BuildContext? globalContext;
final api = FeverAPI();

void main() {
  setupBackgroundTasks();
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  SharedPreferences? prefs;

  Future<bool> _loadPrefs() async {
    var prefs = await SharedPreferences.getInstance();
    this.prefs = prefs;
    api.sharedPrefs = prefs;
    var apiKey = prefs.getString('apiKey'), apiUrl = prefs.getString('apiUrl');

    if (apiUrl != null && apiKey != null) {
      api.apiUrl = apiUrl;
      api.apiKey = apiKey;
      return true;
    }

    return false;
  }

  @override
  Widget build(BuildContext context) {
    return DynamicColorBuilder(
      builder: ((lightDynamic, darkDynamic) => MaterialApp(
            title: 'Feet',
            theme: ThemeData(
              brightness: Brightness.light,
              useMaterial3: true,
              colorScheme: lightDynamic,
            ),
            darkTheme: ThemeData(
              brightness: Brightness.dark,
              useMaterial3: true,
              colorScheme: darkDynamic,
            ),
            themeMode: ThemeMode.system,
            home: FutureBuilder<bool>(
              builder: (context, snapshot) {
                globalContext = context;
                if (snapshot.hasData && prefs != null) {
                  return MyHomePage(title: 'Feet', api: api, prefs: prefs!);
                }
                return const SizedBox();
              },
              future: _loadPrefs(),
            ),
          )),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;
  final FeverAPI api;
  final SharedPreferences prefs;
  const MyHomePage(
      {super.key, required this.title, required this.api, required this.prefs});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _index = 0;
  var _fetched = false;
  var _fetchedCount = 0;
  var _knownPostsSize = -1;
  var _isDemoUser = false;
  List<int> _feedFilter = [];

  Future<void> refresh() async {
    widget.api.cache.clear();
    setState(() {
      _fetchedCount = 0;
      _knownPostsSize = -1;
      _feedFilter = [];
    });

    print("Starting refresh");

    var data = await widget.api
        .request()
        .withFeeds()
        .withGroups()
        .withFavicons()
        .withItems()
        .sinceId(0)
        .execute();

    while ((data['items'] as List<dynamic>).isNotEmpty &&
        _fetchedCount < fetchMaxPosts) {
      print("Fetching more items");

      var ids = widget.api.cache.items
          .getAll()
          .values
          .map((value) => value.id)
          .toList()
        ..sort((a, b) => b - a);

      setState(() {
        _fetchedCount = ids.length;
        _knownPostsSize = data['total_items'] ?? -1;
      });

      data =
          await widget.api.request().withItems().sinceId(ids.first).execute();

      print(
          "Item cache size is now ${widget.api.cache.items.size} ${ids.first} ${ids.last}");
    }
  }

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

    setState(() {
      print("Demo: ${widget.prefs.getBool("isDemo")}");
      _isDemoUser = widget.prefs.getBool("isDemo") ?? false;
    });

    refresh().then((_) => setState(() {
          _fetched = true;
        }));
  }

  @override
  Widget build(BuildContext context) {
    var isDemo = widget.prefs.getBool("isDemo");
    if (isDemo != _isDemoUser) {
      setState(() {
        _isDemoUser = isDemo ?? false;
      });
    }

    var loggedIn = widget.api.loggedIn();
    var posts = widget.api.cache.items.getAll().values.where((element) =>
        _feedFilter.isEmpty || _feedFilter.contains(element.feedId));

    var savedPosts = posts.where((element) => element.isSaved);
    var unreadPosts = posts.where((element) => !element.isRead);

    final pages = [
      /* Posts list */
      posts.isNotEmpty
          ? ListView(
              children: posts.map((value) => HomepagePost(post: value)).toList()
                ..sort((a, b) => b.post.createdOnTime.millisecondsSinceEpoch
                    .compareTo(a.post.createdOnTime.millisecondsSinceEpoch)),
            )
          : const CenteredPageHint(
              icon: Icons.coffee, text: "Your feed is currently empty."),
      /* Unread */
      unreadPosts.isNotEmpty
          ? ListView(
              children: unreadPosts
                  .map((value) => HomepagePost(post: value))
                  .toList()
                ..sort((a, b) => b.post.createdOnTime.millisecondsSinceEpoch
                    .compareTo(a.post.createdOnTime.millisecondsSinceEpoch)),
            )
          : const CenteredPageHint(
              icon: Icons.check, text: "Nothing new here!"),
      /* Saved posts */
      savedPosts.isNotEmpty
          ? ListView(
              children: savedPosts
                  .map((value) => HomepagePost(post: value))
                  .toList()
                ..sort((a, b) => b.post.createdOnTime.millisecondsSinceEpoch
                    .compareTo(a.post.createdOnTime.millisecondsSinceEpoch)),
            )
          : const CenteredPageHint(
              icon: Icons.bookmarks_outlined,
              text: "Nothing here yet. Try saving some posts!"),
    ];

    // I'm aware that this is stupid, but I'm sick and tired and
    // really don't care as long as it works
    if (!loggedIn) {
      Timer.periodic(const Duration(seconds: 1), (timer) {
        setState(() {
          loggedIn = widget.api.loggedIn();
        });

        if (loggedIn) {
          timer.cancel();
          refresh().then((_) => setState(() => _fetched = true));
        }
      });
    }

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: loggedIn
            ? [
                _isDemoUser
                    ? ElevatedButton(
                        onPressed: () {
                          showDialog(
                            context: context,
                            builder: (context) => AlertDialog(
                              title: const Text("Connected to demo server"),
                              content: RichText(
                                  text: TextSpan(
                                children: [
                                  const TextSpan(
                                      text:
                                          "You are currently connected to the demo server.\n"
                                          "Use the"),
                                  WidgetSpan(
                                    child: Icon(Icons.adaptive.more, size: 20),
                                  ),
                                  const TextSpan(
                                      text:
                                          "button in the top right to log out and switch "
                                          "to your own instance once you're done exploring."),
                                ],
                              )),
                              actions: [
                                TextButton(
                                  onPressed: () => Navigator.of(context).pop(),
                                  child: const Text("Got it!"),
                                ),
                              ],
                            ),
                          );
                        },
                        style: ElevatedButton.styleFrom(
                          backgroundColor:
                              const Color.fromARGB(255, 114, 77, 7),
                          foregroundColor: Colors.amber,
                        ),
                        child: Row(children: const [
                          Icon(Icons.warning),
                          SizedBox(width: 8),
                          Text("Demo"),
                        ]))
                    : Container(),
                IconButton(
                  onPressed: () {
                    var theme = Theme.of(context);

                    HapticFeedback.heavyImpact();
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(
                        content: Text('Refreshing feeds',
                            style: TextStyle(
                                color: theme.colorScheme.onBackground)),
                        duration: const Duration(seconds: 2),
                        backgroundColor: theme.colorScheme.secondaryContainer,
                      ),
                    );
                    refresh().then((_) {
                      setState(() {});
                    });
                  },
                  icon: const Icon(Icons.replay_outlined),
                ), // Refresh
                PopupMenuButton(
                    itemBuilder: (context) => [
                          PopupMenuItem(
                            value: "log_out",
                            child: const Text("Log out"),
                            onTap: () {
                              Future.delayed(
                                const Duration(seconds: 0),
                                () => showDialog(
                                  context: context,
                                  builder: (context) => AlertDialog(
                                    title: const Text("Log out"),
                                    content: const Text(
                                        "Are you sure you want to log out?"),
                                    actions: [
                                      TextButton(
                                        onPressed: () {
                                          Navigator.pop(context);
                                        },
                                        child: const Text("Nevermind"),
                                      ),
                                      TextButton(
                                          onPressed: () async {
                                            Navigator.pop(context);
                                            await widget.prefs.clear();

                                            setState(() {
                                              widget.api.apiKey = null;
                                              widget.api.apiUrl = null;
                                              widget.api.cache.clear();
                                            });
                                          },
                                          child: const Text("Do it!")),
                                    ],
                                  ),
                                ),
                              );
                            },
                          ),
                          PopupMenuItem(
                            value: "filter",
                            child: Text(_feedFilter.isEmpty
                                ? "Filter..."
                                : "Filter (${_feedFilter.length}/${widget.api.cache.feeds.size})"),
                            onTap: () {
                              Future.delayed(
                                Duration.zero,
                                () => showDialog(
                                  context: context,
                                  barrierDismissible: false,
                                  builder: (context) => FilterMenu(
                                    api: widget.api,
                                    initData: _feedFilter,
                                    onConfirm: (items) {
                                      setState(() {
                                        _feedFilter = items;
                                      });
                                    },
                                  ),
                                ),
                              );
                            },
                          ),
                          PopupMenuItem(
                            value: "feedback",
                            child: const Text("Feedback"),
                            onTap: () async {
                              await openUrl(context,
                                  "https://git.amogus.cloud/Lea/feet/issues");
                            },
                          ),
                        ]),
              ]
            : [],
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _index,
        onTap: (value) => setState(() => _index = value),
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.list),
            label: 'Feed',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.lens_blur),
            label: 'Unread',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.bookmark_outline),
            activeIcon: Icon(Icons.bookmark),
            label: 'Saved',
          ),
        ],
      ),
      body: loggedIn
          ? (_fetched
              ? pages[_index]
              : CenteredPageHint(
                  icon: Icons.downloading,
                  text:
                      "Fetching your feeds...\n${_fetchedCount > 0 && _knownPostsSize > -1 ? "$_fetchedCount / $_knownPostsSize" : ""}"))
          : Center(child: LoginPrompt(api: widget.api)),
    );
  }
}
