import 'package:flutter/material.dart';
import 'package:graphql/client.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:tstor_ui/api/client.dart';
import 'package:tstor_ui/api/fs_entry.graphql.dart';
import 'package:tstor_ui/api/torrent.graphql.dart';
import 'package:tstor_ui/components/download.dart';
import 'package:tstor_ui/components/sliver_header.dart';

import 'package:tstor_ui/font/t_icons_icons.dart';
import 'package:path/path.dart' as p;
import 'package:tstor_ui/screens/torrent_stats.dart';
import 'package:tstor_ui/utils/bytes.dart';

class FileViewScreen extends StatefulWidget {
  final String initialPath;

  const FileViewScreen({super.key, this.initialPath = "/"});

  @override
  State<FileViewScreen> createState() => _FileViewScreenState();
}

class _FileViewScreenState extends State<FileViewScreen> {
  late String path;

  late final TextEditingController pathController;

  @override
  void initState() {
    path = widget.initialPath;
    pathController = TextEditingController(text: path);
    listDirFuture = client.query$ListDir(
      Options$Query$ListDir(
        variables: Variables$Query$ListDir(path: path),
      ),
    );
    super.initState();
  }

  void cd(String part) {
    setState(() {
      listDirFuture = null;
    });

    setState(() {
      path = p.normalize(p.join(path, part));
      pathController.text = path;
      listDirFuture = client.query$ListDir(
        Options$Query$ListDir(
          variables: Variables$Query$ListDir(path: path),
        ),
      );
    });
  }

  void refresh() {
    setState(() {
      listDirFuture = null;
    });

    setState(() {
      listDirFuture = client.query$ListDir(
        Options$Query$ListDir(
          variables: Variables$Query$ListDir(path: path),
          fetchPolicy: FetchPolicy.noCache,
        ),
      );
    });
  }

  Future<QueryResult<Query$ListDir>>? listDirFuture;

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: (didPop) {
        cd("..");
      },
      child: Scaffold(
        appBar: AppBar(
          title: TextField(
            controller: pathController,
            onEditingComplete: () => cd(pathController.text),
          ),
          leading: IconButton(
            onPressed: () => cd(".."),
            icon: const Icon(Icons.arrow_upward),
          ),
          actions: [
            IconButton(
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const TorrentStatsScreen()),
              ),
              icon: const Icon(Icons.trending_up),
            ),
            IconButton(
              icon: const Icon(Icons.refresh),
              onPressed: refresh,
            )
          ],
        ),
        body: FutureBuilder(
          key: GlobalKey(),
          future: listDirFuture,
          initialData: null,
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              return const Center(child: CircularProgressIndicator());
            }

            final data = snapshot.data!;

            if (data.exception != null) {
              return Text("Error\n${data.exception.toString()}");
            }

            final entry = snapshot.data?.parsedData?.fsEntry;
            if (entry == null) {
              return const Center(child: Text("Entry not exists"));
            }

            final entries = _getEntries(entry);

            if (entries == null || entries.isEmpty) {
              return const Center(child: Text("Empty dir"));
            }

            return CustomScrollView(
              slivers: [
                EntryHeaderSliver(entry: entry),
                SliverList.builder(
                  itemCount: entries.length,
                  itemBuilder: (context, index) {
                    return DirEntry(
                      entry: entries[index],
                      onTap: (name, isFile) {
                        if (!isFile) {
                          cd(name);
                        }
                      },
                    );
                  },
                ),
              ],
            );
          },
        ),
      ),
    );
  }
}

List<Fragment$DirEntry>? _getEntries(Query$ListDir$fsEntry entry) {
  switch (entry) {
    case Query$ListDir$fsEntry$$ArchiveFS entry:
      return entry.entries;
    case Query$ListDir$fsEntry$$ResolverFS entry:
      return entry.entries;
    case Query$ListDir$fsEntry$$SimpleDir entry:
      return entry.entries;
    case Query$ListDir$fsEntry$$TorrentFS entry:
      return entry.entries;
    default:
      return null;
  }
}

class DirEntry extends StatelessWidget {
  final Fragment$DirEntry entry;
  final void Function(String name, bool isFile) onTap;

  const DirEntry({super.key, required this.entry, required this.onTap});

  @override
  Widget build(BuildContext context) {
    switch (entry) {
      case Fragment$TorrentDir entry:
        final completness = entry.torrent.bytesCompleted /
            (entry.torrent.bytesCompleted + entry.torrent.bytesMissing);

        return ListTile(
          leading: const Icon(TIcons.bittorrent_bttold_logo),
          title: Text(entry.name),
          subtitle: Row(
            mainAxisSize: MainAxisSize.max,
            children: [
              Text("${completness * 100}%"),
              Expanded(child: LinearProgressIndicator(value: completness)),
              IconButton(
                onPressed: () => client.mutate$MarkTorrentDownload(
                  Options$Mutation$MarkTorrentDownload(
                    variables:
                        Variables$Mutation$MarkTorrentDownload(infohash: entry.torrent.infohash),
                  ),
                ),
                icon: const Icon(Icons.download),
              )
            ],
          ),
          onTap: () => onTap(entry.name, false),
        );
      case Fragment$DirEntry$$SimpleDir entry:
        return ListTile(
          leading: const Icon(Icons.folder),
          title: Text(entry.name),
          onTap: () => onTap(entry.name, false),
        );
      case Fragment$DirEntry$$ArchiveFS entry:
        return ListTile(
          leading: const Icon(Icons.folder_zip),
          title: Text(entry.name),
          onTap: () => onTap(entry.name, false),
        );
      case Fragment$File entry:
        return ListTile(
          leading: const Icon(Icons.insert_drive_file),
          title: Text(entry.name),
          onTap: () => onTap(entry.name, true),
        );
      default:
        return ListTile(
          leading: const Icon(Icons.question_mark),
          title: Text(entry.name),
        );
    }
  }
}

class EntryHeaderSliver extends StatelessWidget {
  final Query$ListDir$fsEntry entry;

  const EntryHeaderSliver({super.key, required this.entry});

  @override
  Widget build(BuildContext context) {
    switch (entry) {
      case Query$ListDir$fsEntry$$TorrentFS entry:
        final total = entry.torrent.bytesCompleted + entry.torrent.bytesMissing;
        return HideableHeaderSliver(
          leading: const Icon(TIcons.bittorrent_bttold_logo),
          body: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(entry.torrent.name),
              Text("Size: ${total.bytesFormat()}"),
              Text("InfoHash: ${entry.torrent.infohash}"),
              DownloadProgress(entry.torrent.bytesCompleted, total)
            ],
          ),
          actions: [
            IconButton(
              icon: const Icon(Icons.download),
              onPressed: () => client.mutate$MarkTorrentDownload(
                Options$Mutation$MarkTorrentDownload(
                  variables: Variables$Mutation$MarkTorrentDownload(
                    infohash: entry.torrent.infohash,
                  ),
                ),
              ),
            )
          ],
        );

      default:
        return HideableHeaderSliver(
          leading: const Icon(Icons.folder),
          body: Text(entry.name),
        );
    }
  }
}