import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart';

import '../../../state/app/infrastructure/loadable_state/loadable_state.dart';
import '../../../state/app/infrastructure/loadable_state/view/loadable_state_consumer.dart';
import '../../../state/app/infrastructure/utility_widgets/bloc_module.dart';
import '../../../state/app/modules/files/bloc/files_bloc.dart';
import '../../../state/app/modules/files/bloc/files_state.dart';
import '../../../state/app/modules/settings/bloc/settings_cubit.dart';
import '../../../utils/cache_invalidation_bus.dart';
import '../../../widget/placeholder_view.dart';
import 'data/sort_options.dart';
import 'files_upload_dialog.dart';
import 'search/files_search_delegate.dart';
import 'widgets/add_file_menu.dart';
import 'widgets/clipboard_banner.dart';
import 'widgets/file_element.dart';
import 'widgets/files_sort_actions.dart';

class Files extends StatelessWidget {
  final List<String> path;

  Files({List<String>? path, super.key}) : path = path ?? [];

  @override
  Widget build(BuildContext context) =>
      BlocModule<FilesBloc, LoadableState<FilesState>>(
        create: (_) => FilesBloc(initialPath: path),
        child: (context, _, _) => _FilesView(path: path),
      );
}

class _FilesView extends StatefulWidget {
  final List<String> path;
  const _FilesView({required this.path});

  @override
  State<_FilesView> createState() => _FilesViewState();
}

class _FilesViewState extends State<_FilesView> {
  late final SettingsCubit settings;
  late SortOption currentSort;
  late bool currentSortDirection;
  late final StreamSubscription<String> _invalidationSub;

  // Cache key in FilesBloc's pathString format: '/' for root, otherwise
  // segments joined without leading/trailing slash.
  String get _myPathString => widget.path.isEmpty ? '/' : widget.path.join('/');

  // Relative folder path matching the WebDAV format used by `CacheableFile.path`
  // (no leading slash; trailing slash for non-root). Empty string means root.
  String get _currentFolderPath =>
      widget.path.isEmpty ? '' : '${widget.path.join('/')}/';

  @override
  void initState() {
    super.initState();
    settings = context.read<SettingsCubit>();
    currentSort = settings.val().fileSettings.sortBy;
    currentSortDirection = settings.val().fileSettings.ascending;
    _invalidationSub = CacheInvalidationBus.listFilesStream.listen(
      _onInvalidation,
    );
  }

  void _onInvalidation(String invalidatedPath) {
    if (!mounted) return;
    if (invalidatedPath != _myPathString) return;
    context.read<FilesBloc>().refresh();
  }

  @override
  void dispose() {
    _invalidationSub.cancel();
    super.dispose();
  }

  Future<void> _mediaUpload(List<String>? paths) async {
    if (paths == null) return;
    final bloc = context.read<FilesBloc>();
    unawaited(
      pushScreen(
        context,
        withNavBar: false,
        screen: FilesUploadDialog(
          filePaths: paths,
          remotePath: widget.path.join('/'),
          onUploadFinished: (_) => bloc.refresh(),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final bloc = context.read<FilesBloc>();
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.path.isNotEmpty ? widget.path.last : 'Dateien'),
        actions: [
          FilesSortActions(
            currentSort: currentSort,
            ascending: currentSortDirection,
            onDirectionChanged: (e) {
              setState(() {
                currentSortDirection = e;
                settings.val(write: true).fileSettings.ascending = e;
              });
            },
            onSortChanged: (e) {
              setState(() {
                currentSort = e;
                settings.val(write: true).fileSettings.sortBy = e;
              });
            },
          ),
          IconButton(
            tooltip: 'Suchen',
            icon: const Icon(Icons.search),
            onPressed: () async {
              final delegate = FilesSearchDelegate(pathScope: widget.path);
              await showSearch<void>(context: context, delegate: delegate);
              delegate.disposeController();
            },
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        heroTag: 'uploadFile',
        backgroundColor: Theme.of(context).primaryColor,
        onPressed: () =>
            showAddFileSheet(context, bloc: bloc, onPickedFiles: _mediaUpload),
        child: const Icon(Icons.add),
      ),
      body: Column(
        children: [
          ClipboardBanner(
            currentFolder: _currentFolderPath,
            onPasteDone: bloc.refresh,
          ),
          Expanded(
            child: LoadableStateConsumer<FilesBloc, FilesState>(
              isReady: (state) => state.listing != null,
              child: (state, _) {
                final listing = state.listing!;
                if (listing.files.isEmpty) {
                  return const PlaceholderView(
                    icon: Icons.folder_off_rounded,
                    text: 'Der Ordner ist leer',
                  );
                }
                final files = listing.sortBy(
                  sortOption: currentSort,
                  foldersToTop: context
                      .watch<SettingsCubit>()
                      .val()
                      .fileSettings
                      .sortFoldersToTop,
                  reversed: currentSortDirection,
                );
                return ListView.builder(
                  padding: EdgeInsets.zero,
                  itemCount: files.length,
                  itemBuilder: (context, index) =>
                      FileElement(files[index], widget.path, bloc.refresh),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
