import 'package:flutter/material.dart';

import '../../../../api/errors/error_mapper.dart';
import '../../../../api/marianumcloud/webdav/queries/list_files/cacheable_file.dart';
import '../../../../routing/app_routes.dart';
import '../../../../state/app/infrastructure/loadable_state/bloc/loadable_state_bloc.dart';
import '../../../../state/app/infrastructure/loadable_state/bloc/loadable_state_state.dart';
import '../../../../state/app/infrastructure/loadable_state/view/loadable_state_background_loading.dart';
import '../../../../state/app/infrastructure/loadable_state/view/loadable_state_error_bar.dart';
import '../../../../state/app/infrastructure/loadable_state/view/loadable_state_error_screen.dart';
import '../../../../state/app/infrastructure/loadable_state/view/loadable_state_primary_loading.dart';
import '../../../../state/app/infrastructure/utility_widgets/bloc_module.dart';
import '../../../../widget/placeholder_view.dart';
import '../widgets/file_element.dart';
import 'files_search_controller.dart';

/// Renders the live state of a [FilesSearchController]. Wraps everything in a
/// `LoadableStateBloc` module so the search reuses the standard primary /
/// background loading and error views from the rest of the app.
class FilesSearchResults extends StatelessWidget {
  final FilesSearchController controller;
  final VoidCallback? onResultTap;

  const FilesSearchResults({
    required this.controller,
    this.onResultTap,
    super.key,
  });

  @override
  Widget build(BuildContext context) =>
      BlocModule<LoadableStateBloc, LoadableStateState>(
        create: (_) => LoadableStateBloc(),
        child: (context, bloc, _) {
          bloc.reFetch = controller.retry;
          return ListenableBuilder(
            listenable: controller,
            builder: (context, _) => _buildBody(context),
          );
        },
      );

  Widget _buildBody(BuildContext context) {
    if (controller.query.trim().isEmpty) {
      return const PlaceholderView(
        icon: Icons.search,
        text: 'Tippen, um in Dateien zu suchen.',
      );
    }
    final combined = controller.combinedResults;
    final hasContent = combined.isNotEmpty;
    final hasError = controller.serverError != null;
    final isLoading = controller.serverLoading;

    final showPrimaryLoading = isLoading && !hasContent;
    final showBackgroundLoading = isLoading && hasContent;
    final showErrorScreen = hasError && !hasContent && !isLoading;
    final showErrorBar = hasError && hasContent;
    final showEmpty = !hasContent && !hasError && !isLoading;

    final errorMessage = hasError ? errorToUserMessage(controller.serverError) : null;

    return Column(
      children: [
        LoadableStateErrorBar(
          visible: showErrorBar,
          hasContent: hasContent,
          message: errorMessage,
        ),
        // Background loading sits *outside* the result Stack so the linear
        // progress bar is not painted over by the opaque ListView/ListTiles
        // when cache hits are already on screen and the server is still
        // working. The widget collapses to zero height when invisible.
        LoadableStateBackgroundLoading(visible: showBackgroundLoading),
        Expanded(
          child: Stack(
            children: [
              LoadableStatePrimaryLoading(visible: showPrimaryLoading),
              LoadableStateErrorScreen(
                visible: showErrorScreen,
                message: errorMessage,
              ),
              if (showEmpty) _emptyState(context),
              if (hasContent) _resultList(context, combined),
            ],
          ),
        ),
      ],
    );
  }

  Widget _emptyState(BuildContext context) => PlaceholderView(
    icon: Icons.search_off_outlined,
    text: 'Keine Treffer gefunden.',
    button: controller.isScoped
        ? FilledButton.icon(
            onPressed: controller.searchEverywhere,
            icon: const Icon(Icons.travel_explore),
            label: const Text('Im Hauptverzeichnis suchen'),
          )
        : null,
  );

  Widget _resultList(BuildContext context, List<CacheableFile> combined) {
    final groups = _groupByParent(combined);
    final orderedKeys = groups.keys.toList()..sort();
    final items = <Widget>[];
    for (final folder in orderedKeys) {
      final segments = _segmentsOf(folder);
      items.add(
        _FolderHeader(
          folder: folder,
          onOpen: () {
            onResultTap?.call();
            AppRoutes.openFolder(context, segments);
          },
        ),
      );
      for (final file in groups[folder]!) {
        items.add(
          FileElement(
            file,
            segments,
            controller.retry,
            highlight: controller.query,
          ),
        );
      }
    }
    return ListView(padding: EdgeInsets.zero, children: items);
  }

  Map<String, List<CacheableFile>> _groupByParent(List<CacheableFile> files) {
    final map = <String, List<CacheableFile>>{};
    for (final file in files) {
      map.putIfAbsent(_parentOf(file), () => []).add(file);
    }
    return map;
  }

  String _parentOf(CacheableFile file) {
    final stripped = file.path.replaceAll(RegExp(r'^/+|/+$'), '');
    final segments = stripped.split('/');
    if (segments.length <= 1) return '/';
    segments.removeLast();
    return '/${segments.join('/')}';
  }

  List<String> _segmentsOf(String folder) {
    final stripped = folder.replaceAll(RegExp(r'^/+|/+$'), '');
    if (stripped.isEmpty) return const [];
    return stripped.split('/');
  }
}

class _FolderHeader extends StatelessWidget {
  final String folder;
  final VoidCallback onOpen;
  const _FolderHeader({required this.folder, required this.onOpen});

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Container(
      width: double.infinity,
      height: 38,
      color: theme.colorScheme.surfaceContainer,
      padding: const EdgeInsets.only(left: 16),
      child: Row(
        children: [
          Expanded(
            child: Text(
              folder,
              style: theme.textTheme.labelLarge?.copyWith(
                color: theme.colorScheme.primary,
                fontWeight: FontWeight.w700,
                letterSpacing: 1.2,
              ),
              overflow: TextOverflow.ellipsis,
            ),
          ),
          IconButton(
            tooltip: 'Ordner öffnen',
            iconSize: 20,
            visualDensity: VisualDensity.compact,
            icon: const Icon(Icons.folder_open_outlined),
            onPressed: onOpen,
          ),
        ],
      ),
    );
  }
}
