import 'dart:async';
import 'dart:io';
import 'dart:collection';
import 'dart:math' as math;

import 'package:country_codes/country_codes.dart';
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:path_provider/path_provider.dart';
import 'package:search_engine/screens/content.dart';
import 'package:search_engine/widgets/base.dart';
import 'package:skeletonizer/skeletonizer.dart';
import '../database.dart';
import 'package:search_engine/utils.dart' as utils;
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart'
    as nav;
// ignore: library_prefixes
import 'package:search_engine/services/notification_service.dart';

// Clase auxiliar para representar una coincidencia
class _Match {
  final int start;
  final int end;
  final String text;

  _Match({required this.start, required this.end, required this.text});
}

// Clase auxiliar para representar un fragmento de texto
class _TextFragment {
  final String beforeMatch;
  final String matchText;
  final String afterMatch;

  _TextFragment({
    required this.beforeMatch,
    required this.matchText,
    required this.afterMatch,
  });
}

// Clase para el caché de búsqueda
class SearchCache {
  // LRU Cache con capacidad máxima
  final int _maxSize;
  final LinkedHashMap<String, List<Draft>> _cache = LinkedHashMap();
  final Map<String, int> _totalResultsCache = {};
  // Almacena todos los resultados de una búsqueda
  final Map<String, List<Draft>> _allResultsCache = {};

  SearchCache({int maxSize = 10}) : _maxSize = maxSize;

  // Obtener resultados del caché
  List<Draft>? get(String query) {
    final normalizedQuery = query.trim().toLowerCase();
    if (!_cache.containsKey(normalizedQuery)) return null;

    // Mover el elemento al final (más reciente)
    final results = _cache.remove(normalizedQuery);
    _cache[normalizedQuery] = results!;
    return results;
  }

  // Guardar resultados en el caché
  void put(String query, List<Draft> results) {
    final normalizedQuery = query.trim().toLowerCase();

    // Si el caché está lleno, eliminar el elemento más antiguo
    if (_cache.length >= _maxSize) {
      final oldestKey = _cache.keys.first;
      _cache.remove(oldestKey);
      // También eliminar del caché de todos los resultados
      _allResultsCache.remove(oldestKey);
      _totalResultsCache.remove(oldestKey);
    }

    _cache[normalizedQuery] = results;
  }

  // Limpiar el caché
  void clear() {
    _cache.clear();
    _totalResultsCache.clear();
    _allResultsCache.clear();
  }

  // Obtener el total de resultados para una consulta
  int? getTotalResults(String query) {
    final normalizedQuery = query.trim().toLowerCase();
    return _totalResultsCache[normalizedQuery];
  }

  // Guardar el total de resultados para una consulta
  void setTotalResults(String query, int total) {
    final normalizedQuery = query.trim().toLowerCase();
    _totalResultsCache[normalizedQuery] = total;
  }

  // Guardar todos los resultados de una búsqueda
  void putAllResults(String query, List<Draft> results) {
    final normalizedQuery = query.trim().toLowerCase();
    _allResultsCache[normalizedQuery] = results;
  }

  // Obtener todos los resultados de una búsqueda
  List<Draft>? getAllResults(String query) {
    final normalizedQuery = query.trim().toLowerCase();
    return _allResultsCache[normalizedQuery];
  }
}

class GenericSearchPage extends StatefulWidget {
  final String? searchTerm;
  final String title;
  final String hintText;
  final Future<List<Draft>> Function(String query, int pageKey, int offset)
      searchFunction;
  final Widget Function(Draft message, String currentQuery)? customItemBuilder;
  final Widget? emptyStateWidget;
  final Widget? loadingWidget;
  final Widget? errorWidget;

  const GenericSearchPage({
    super.key,
    this.searchTerm,
    required this.title,
    required this.hintText,
    required this.searchFunction,
    this.customItemBuilder,
    this.emptyStateWidget,
    this.loadingWidget,
    this.errorWidget,
  });

  @override
  _GenericSearchPageState createState() => _GenericSearchPageState();
}

class _GenericSearchPageState extends State<GenericSearchPage>
    with TickerProviderStateMixin {
  late TextEditingController _searchController;
  late AppDatabase database;
  late Directory appDirectory;
  int resultCount = 0;
  int totalResults = 0;
  bool isLoading = false;
  // Nuevas variables para separar las fases de carga
  bool dataLoading = false; // Para la fase de carga de datos
  Timer? _debounce;
  final _baseUrl = dotenv.env['BASE_URL'];
  final _token = dotenv.env['TOKEN'];
  bool _isSearching = false;
  late AnimationController _animationController;
  late Animation<double> _fadeAnimation;

  // Controlador para la animación de pulso del indicador de búsqueda
  late AnimationController _pulseController;
  late Animation<double> _pulseAnimation;

  // Controlador de paginación
  final PagingController<int, Draft> _pagingController = PagingController(
    firstPageKey: 1,
    // Set invisibleItemsThreshold to load the next page earlier
    invisibleItemsThreshold: 5,
  );

  // Tamaño de página para la carga incremental
  static const _pageSize = 20;

  // Consulta actual
  String _currentQuery = '';

  // Almacena todos los resultados de la búsqueda actual
  List<Draft>? _allSearchResults;

  // Instancia del caché de búsqueda
  final SearchCache _searchCache = SearchCache(maxSize: 20);

  // Caché para nombres de países
  final Map<String, String> _countryNameCache = {};

  // Caché para los spans resaltados
  final Map<String, List<TextSpan>> _highlightedSpansCache = {};

  @override
  void initState() {
    super.initState();
    _searchController = TextEditingController(text: widget.searchTerm);
    _initAppDirectory();
    database = AppDatabase();

    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );

    _fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
      CurvedAnimation(
        parent: _animationController,
        curve: Curves.easeIn,
      ),
    );

    // Inicializar el controlador de la animación de pulso
    _pulseController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1500),
    )..repeat(reverse: true);

    _pulseAnimation = Tween<double>(begin: 0.8, end: 1.2).animate(
      CurvedAnimation(
        parent: _pulseController,
        curve: Curves.easeInOut,
      ),
    );

    // Configurar el listener para la paginación
    _pagingController.addPageRequestListener((pageKey) {
      if (_currentQuery.isNotEmpty) {
        _fetchPage(pageKey);
      }
    });

    if (_searchController.text.isNotEmpty) {
      Timer(const Duration(milliseconds: 100), () {
        _onSearch(_searchController.text);
      });
    }
  }

  @override
  void dispose() {
    _pagingController.dispose();
    _animationController.dispose();
    _pulseController.dispose();
    database.close();
    _debounce?.cancel();
    _searchController.dispose();
    super.dispose();
  }

  void _onSearch(String value) {
    if (_searchController.text.trim().isNotEmpty) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          setState(() {
            _isSearching = true;
            _currentQuery = _searchController.text;
            totalResults = 0;
            isLoading = true;
            dataLoading = true;
            _allSearchResults = null;
          });

          // Limpiar caché de resaltado para la nueva búsqueda
          _highlightedSpansCache.clear();

          // Refrescar el controlador de paginación
          _pagingController.refresh();
          _animationController.forward();
        }
      });
    } else {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          setState(() {
            _isSearching = false;
            _currentQuery = '';
            totalResults = 0;
            isLoading = false;
            dataLoading = false;
            _allSearchResults = null;
          });

          // Limpiar caché de resaltado
          _highlightedSpansCache.clear();

          // Limpiar y refrescar el controlador de paginación
          _pagingController.itemList?.clear();
          _pagingController.refresh();

          if (_animationController.isAnimating) {
            _animationController.stop();
          }
          if (_animationController.value > 0) {
            _animationController.reverse();
          }
        }
      });
    }
  }

  void _clearSearch() {
    _searchController.clear();

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (mounted) {
        setState(() {
          _isSearching = false;
          _currentQuery = '';
          isLoading = false;
          dataLoading = false;
          _allSearchResults = null;
        });

        // Limpiar caché de resaltado
        _highlightedSpansCache.clear();

        // Refrescar el controlador de paginación
        _pagingController.refresh();

        if (_animationController.isAnimating) {
          _animationController.stop();
        }
        if (_animationController.value > 0) {
          _animationController.reverse();
        }
      }
    });
  }

  Future<void> _fetchPage(int pageKey) async {
    if (!mounted) return;

    try {
      // Verificar si los resultados están en caché
      final cachedResults = _searchCache.get('${_currentQuery}_page_$pageKey');

      if (cachedResults != null) {
        final isLastPage = cachedResults.length < _pageSize;
        if (isLastPage) {
          _pagingController.appendLastPage(cachedResults);
        } else {
          _pagingController.appendPage(cachedResults, pageKey + 1);
        }

        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (mounted) {
            setState(() {
              resultCount = _pagingController.itemList?.length ?? 0;
            });
          }
        });

        return;
      }

      // Calcular el offset y límite para la paginación
      final offset = (pageKey - 1) * _pageSize;
      final limit = _pageSize;

      // Indicar que estamos cargando datos
      if (pageKey == 1) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (mounted) {
            setState(() {
              isLoading = true;
              dataLoading = true;
            });
          }
        });
      }

      // Get the RootIsolateToken before starting the search
      final token = RootIsolateToken.instance;
      if (token == null) {
        throw Exception('RootIsolateToken is not initialized');
      }

      // Si ya tenemos todos los resultados, usamos paginación local
      if (_allSearchResults != null) {
        final int start = offset;
        final int end = math.min(start + limit, _allSearchResults!.length);

        if (start >= _allSearchResults!.length) {
          // No hay más resultados
          _pagingController.appendLastPage([]);
        } else {
          final pageResults = _allSearchResults!.sublist(start, end);
          final bool isLastPage = end >= _allSearchResults!.length;

          if (isLastPage) {
            _pagingController.appendLastPage(pageResults);
          } else {
            _pagingController.appendPage(pageResults, pageKey + 1);
          }

          // Actualizar el conteo de resultados
          WidgetsBinding.instance.addPostFrameCallback((_) {
            if (mounted) {
              setState(() {
                isLoading = false;
                dataLoading = false;
                totalResults = _allSearchResults!.length;
                resultCount = (_pagingController.itemList?.length ?? 0);
              });
            }
          });
        }
        return;
      }

      // Si no tenemos los resultados completos, realizar la búsqueda
      final searchFuture =
          widget.searchFunction(_currentQuery, pageKey, offset);
      final pageResults = await searchFuture;

      // Si es la primera página, cargar todos los resultados
      if (pageKey == 1) {
        // Obtener todos los resultados completos (no solo la primera página)
        try {
          // Extraer la lista de IDs de todos los resultados
          Map<String, dynamic> searchResult = pageResults.isNotEmpty
              ? (pageResults.first as dynamic).searchResultData ?? {}
              : {};

          List<String> allResultIds = [];
          if (searchResult.containsKey('allResultIds')) {
            allResultIds = List<String>.from(searchResult['allResultIds']);
          }

          if (allResultIds.isNotEmpty) {
            _allSearchResults = await database.getMessagesByIds(
                allResultIds, context.locale.toString());

            totalResults = _allSearchResults?.length ?? 0;

            if (_allSearchResults != null) {
              _searchCache.putAllResults(_currentQuery, _allSearchResults!);
              _searchCache.setTotalResults(
                  _currentQuery, _allSearchResults!.length);
            }
          }
        } catch (e) {
          if (kDebugMode) {
            print('Error cargando todos los resultados: $e');
          }
          // Continuar con la paginación normal si falla
          _allSearchResults = null;
        }
      }

      // Si no pudimos cargar todos los resultados, continuar con la paginación normal
      if (_allSearchResults == null) {
        // Obtener resultados únicos por ID de documento
        final uniqueResults = pageResults
            .fold<Map<String, Draft>>({}, (map, result) {
              if (!map.containsKey(result.id)) {
                map[result.id] = result;
              }
              return map;
            })
            .values
            .toList();

        // Actualizar el total de resultados si es la primera página
        if (pageKey == 1) {
          WidgetsBinding.instance.addPostFrameCallback((_) {
            if (mounted) {
              setState(() {
                totalResults = uniqueResults.length;
                dataLoading = false;
              });
            }
          });
        }

        // Guardar esta página en caché
        _searchCache.put('${_currentQuery}_page_$pageKey', uniqueResults);

        // Mostrar los resultados
        final isLastPage = uniqueResults.length < _pageSize;
        if (isLastPage) {
          _pagingController.appendLastPage(uniqueResults);
        } else {
          _pagingController.appendPage(uniqueResults, pageKey + 1);
        }
      } else {
        // Usar los resultados completos para la primera página
        final int start = 0;
        final int end = math.min(limit, _allSearchResults!.length);
        final firstPageResults = _allSearchResults!.sublist(start, end);

        // Guardar esta página en caché
        _searchCache.put('${_currentQuery}_page_1', firstPageResults);

        final bool isLastPage = end >= _allSearchResults!.length;
        if (isLastPage) {
          _pagingController.appendLastPage(firstPageResults);
        } else {
          _pagingController.appendPage(firstPageResults, pageKey + 1);
        }
      }

      // Actualizar el estado después del frame
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          setState(() {
            isLoading = false;
            dataLoading = false;
            resultCount = (_pagingController.itemList?.length ?? 0);
          });

          if (pageKey == 1) {
            if (_animationController.isCompleted) {
              _animationController.reset();
            }
            _animationController.forward();
          }
        }
      });
    } catch (e) {
      if (kDebugMode) {
        print('Error en paginación: $e');
      }

      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          setState(() {
            isLoading = false;
            dataLoading = false;
          });
          _pagingController.error = e;
        }
      });
    }
  }

  Future<void> _initAppDirectory() async {
    appDirectory = await getApplicationDocumentsDirectory();
  }

  Future<File?> _getThumbnail(String directoryPath, String fileId) async {
    final dir = Directory(directoryPath);

    if (!await dir.exists()) {
      await dir.create(recursive: true);
    }

    final entities = await dir.list().toList();

    for (var entity in entities) {
      if (entity is File) {
        final fileName = entity.uri.pathSegments.last;
        if (fileName == '$fileId+SD.jpg') {
          return entity;
        }
      }
    }

    final String url =
        '$_baseUrl/assets/$fileId?access_token=$_token&width=320&height=180&quality=50&fit=cover&format=jpg';
    final String thumbnailPath = '$directoryPath/$fileId+SD.jpg';
    if (fileId == '') {
      return null;
    }
    try {
      await Dio().download(url, thumbnailPath);
      return File(thumbnailPath);
    } catch (e) {
      if (kDebugMode) {
        print('Error downloading thumbnail: $e');
      }
      return null;
    }
  }

  Widget _buildThumbnail(String thumbnailId) {
    return FutureBuilder<File?>(
      future: _getThumbnail(
          '${appDirectory.path}/LGCC_Search/${context.locale}/thumbnails/',
          thumbnailId),
      builder: (context, snapshot) {
        return Skeletonizer(
          enableSwitchAnimation: true,
          enabled: snapshot.connectionState != ConnectionState.done,
          effect: const ShimmerEffect(
            baseColor: Color(0xFFf1f5eb),
            highlightColor: Colors.white30,
            duration: Duration(milliseconds: 1000),
          ),
          child: snapshot.hasData && snapshot.data != null
              ? Image.file(
                  snapshot.data!,
                  height: double.infinity,
                  width: double.infinity,
                  fit: BoxFit.cover,
                  cacheHeight: 180,
                  cacheWidth: 320,
                )
              : Image.asset(
                  'assets/image/default_thumbnail.jpg',
                  height: double.infinity,
                  width: double.infinity,
                  fit: BoxFit.cover,
                  alignment: Alignment.topCenter,
                  cacheHeight: 180,
                  cacheWidth: 320,
                ),
        );
      },
    );
  }

  List<TextSpan> _getHighlightedSpans(String text, String searchText) {
    if (searchText.isEmpty) {
      return [TextSpan(text: text)];
    }

    // El texto ya está limpio de HTML, podemos usarlo directamente
    final String plainText = text;

    // Si el texto es muy corto, no procesarlo
    if (plainText.length < 3) {
      return [TextSpan(text: plainText)];
    }

    // Caché de resultados para evitar recálculos
    final String cacheKey = '$plainText:$searchText';
    if (_highlightedSpansCache.containsKey(cacheKey)) {
      return _highlightedSpansCache[cacheKey]!;
    }

    final List<TextSpan> spans = [];

    // Extraer palabras clave de la búsqueda y filtrar las muy cortas
    final List<String> keywords = searchText
        .trim()
        .toLowerCase()
        .split(RegExp(r'\s+'))
        .where((word) => word.isNotEmpty && word.length >= 3)
        .toList();

    if (keywords.isEmpty) {
      return [TextSpan(text: plainText)];
    }

    // Texto en minúsculas para comparaciones
    final String lowerText = plainText.toLowerCase();

    // Crear una lista de todas las coincidencias
    final List<_Match> allMatches = [];

    // Usar un enfoque más eficiente para encontrar coincidencias
    for (final keyword in keywords) {
      // Para palabras de más de 4 letras, considerar la raíz como las primeras n-1 letras
      String baseWord = keyword;
      if (baseWord.length > 4) {
        baseWord = baseWord.substring(0, baseWord.length - 1);
      }

      // Buscar la palabra base en el texto
      int startIndex = 0;
      while (true) {
        final int index = lowerText.indexOf(baseWord, startIndex);
        if (index == -1) break;

        // Encontrar el final de la palabra
        int endIndex = index + baseWord.length;
        while (endIndex < lowerText.length &&
            _isWordCharacter(lowerText[endIndex])) {
          endIndex++;
        }

        // Añadir la coincidencia
        allMatches.add(_Match(
          start: index,
          end: endIndex,
          text: plainText.substring(index, endIndex),
        ));

        // Continuar desde el final de esta coincidencia
        startIndex = endIndex;
      }
    }

    // Si no hay coincidencias, devolver el texto original
    if (allMatches.isEmpty) {
      return [TextSpan(text: plainText)];
    }

    // Ordenar coincidencias por posición
    allMatches.sort((a, b) => a.start.compareTo(b.start));

    // Manejar coincidencias superpuestas
    final List<_Match> mergedMatches = [];
    if (allMatches.isNotEmpty) {
      _Match current = allMatches.first;
      for (int i = 1; i < allMatches.length; i++) {
        final _Match next = allMatches[i];
        if (current.end >= next.start) {
          // Las coincidencias se superponen, fusionarlas
          current = _Match(
            start: current.start,
            end: math.max(current.end, next.end),
            text: plainText.substring(
                current.start, math.max(current.end, next.end)),
          );
        } else {
          // Sin superposición, agregar la actual al resultado y pasar a la siguiente
          mergedMatches.add(current);
          current = next;
        }
      }
      mergedMatches.add(current); // Agregar la última coincidencia
    }

    // Construir spans a partir de coincidencias fusionadas
    int lastIndex = 0;
    for (final match in mergedMatches) {
      if (match.start > lastIndex) {
        spans.add(TextSpan(
          text: plainText.substring(lastIndex, match.start),
        ));
      }

      spans.add(TextSpan(
        text: plainText.substring(match.start, match.end),
        style: const TextStyle(backgroundColor: Color(0xFFfff930)),
      ));

      lastIndex = match.end;
    }

    // Agregar texto restante
    if (lastIndex < plainText.length) {
      spans.add(TextSpan(
        text: plainText.substring(lastIndex),
      ));
    }

    // Guardar en caché para uso futuro
    _highlightedSpansCache[cacheKey] = spans;

    return spans;
  }

  // Verificar si un carácter es parte de una palabra
  bool _isWordCharacter(String char) {
    return RegExp(r'[a-zñáéíóúüA-ZÑÁÉÍÓÚÜ0-9]').hasMatch(char);
  }

  // Widget optimizado para texto resaltado
  Widget _buildHighlightedText(String text, String searchText, TextStyle style,
      {int maxLines = 2}) {
    return RichText(
      maxLines: maxLines,
      overflow: TextOverflow.ellipsis,
      text: TextSpan(
        children: _getHighlightedSpans(text, searchText),
        style: style,
      ),
      textScaler: TextScaler.linear(1.0),
    );
  }

  // Widget optimizado para texto de ubicación
  Widget _buildLocationText(Draft message) {
    // Evitar cálculos costosos en cada reconstrucción
    final String locationText = message.city.isNotEmpty
        ? '${message.city}, ${_getCountryNameCached(message.country)}'
        : _getCountryNameCached(message.country);

    return Text(
      locationText,
      style: const TextStyle(fontSize: 14, height: 1.2),
      overflow: TextOverflow.ellipsis,
      maxLines: 1,
    );
  }

  // Versión en caché de _getCountryName
  String _getCountryNameCached(String countryCode) {
    if (countryCode.isEmpty) {
      return 'N/A';
    }

    if (_countryNameCache.containsKey(countryCode)) {
      return _countryNameCache[countryCode]!;
    }

    try {
      final name = CountryCodes.detailsFromAlpha2(countryCode).name.toString();
      _countryNameCache[countryCode] = name;
      return name;
    } catch (e) {
      _countryNameCache[countryCode] = countryCode;
      return countryCode;
    }
  }

  Widget _buildDefaultItem(Draft message) {
    // Usar un widget de construcción diferida para mejorar el rendimiento
    return RepaintBoundary(
      child: Card(
        key: ValueKey(
            'search_result_${message.id}_${message.date.millisecondsSinceEpoch}'),
        color: const Color(0xFFdfe6ce),
        margin: const EdgeInsets.only(bottom: 16),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
        child: InkWell(
          onTap: () => nav.pushScreenWithoutNavBar(
              context,
              TextViewer(
                  data: message,
                  searchTerm: message.body != null
                      ? _getMatchedText(message.body!, _currentQuery)
                      : _currentQuery)),
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    ClipRRect(
                      borderRadius: BorderRadius.circular(8),
                      child: Container(
                        width: 100,
                        height: 80,
                        decoration: const BoxDecoration(
                          color: Color(0xFFf1f5eb),
                        ),
                        child: _buildThumbnail(message.thumbnail),
                      ),
                    ),
                    const SizedBox(width: 16),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          _buildItemTitle(message),
                          const SizedBox(height: 5),
                          Text(
                            utils.formatDate(
                                message.date, context.locale.toString()),
                            style: const TextStyle(fontSize: 14, height: 1),
                          ),
                          const SizedBox(height: 5),
                          _buildLocationText(message),
                          const SizedBox(height: 5),
                          Text(
                            "${plural('activity', 1)} ${message.activity}",
                            style: const TextStyle(fontSize: 14, height: 1),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
                if (message.body != null && message.body!.isNotEmpty)
                  _buildSnippet(message.body!, _currentQuery),
              ],
            ),
          ),
        ),
      ),
    );
  }

  // Widget optimizado para el título del item
  Widget _buildItemTitle(Draft message) {
    if (message.title.isEmpty) {
      return Text(
        utils.formatDate(message.date, context.locale.toString()),
        style: const TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 16,
          height: 1.2,
        ),
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
      );
    }

    return _buildHighlightedText(
      message.title,
      _currentQuery,
      const TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 16,
        height: 1.2,
        color: Colors.black,
        fontFamily: 'Outfit',
      ),
      maxLines: 2,
    );
  }

  // Widget optimizado para el snippet
  Widget _buildSnippet(String snippet, String query) {
    return Padding(
      padding: const EdgeInsets.only(top: 16),
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
        decoration: BoxDecoration(
          color: Colors.white.withOpacity(0.5),
          borderRadius: BorderRadius.circular(8),
        ),
        child: _buildHighlightedText(
          snippet,
          query,
          const TextStyle(
            fontSize: 14,
            color: Colors.black87,
            height: 1.5,
            fontFamily: 'Outfit',
          ),
          maxLines: 3,
        ),
      ),
    );
  }

  // Widget para el encabezado de búsqueda
  Widget _buildSearchHeader() {
    Widget loadingIndicator(String text) {
      return Container(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        decoration: BoxDecoration(
          color: const Color(0xFF6b8e23).withOpacity(0.15),
          borderRadius: BorderRadius.circular(12),
          border: Border.all(
            color: const Color(0xFF6b8e23).withOpacity(0.3),
            width: 1,
          ),
        ),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            AnimatedBuilder(
              animation: _pulseAnimation,
              builder: (context, child) {
                return Transform.scale(
                  scale: _pulseAnimation.value,
                  child: child,
                );
              },
              child: const SizedBox(
                width: 14,
                height: 14,
                child: CircularProgressIndicator(
                  strokeWidth: 2,
                  valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF6b8e23)),
                ),
              ),
            ),
            const SizedBox(width: 8),
            Text(
              text,
              style: const TextStyle(
                fontSize: 13,
                fontWeight: FontWeight.w500,
                color: Color(0xFF6b8e23),
              ),
            ),
          ],
        ),
      );
    }

    return Row(
      children: [
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Expanded(
                    child: Text(
                      '${'searching'.tr()}: "$_currentQuery"',
                      style: const TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                  // Mostrar el contador de resultados tan pronto como tengamos los datos
                  if (!dataLoading && totalResults > 0)
                    Container(
                      padding: const EdgeInsets.symmetric(
                          horizontal: 8, vertical: 4),
                      decoration: BoxDecoration(
                        color: const Color(0xFF6b8e23).withOpacity(0.15),
                        borderRadius: BorderRadius.circular(8),
                      ),
                      child: Text(
                        "$totalResults ${'results'.plural(totalResults)}",
                        style: const TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.bold,
                          color: Color(0xFF6b8e23),
                        ),
                      ),
                    ),
                ],
              ),
            ],
          ),
        ),
        if (dataLoading) loadingIndicator('searching_in_progress'.tr()),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return BaseScreen(
      title: widget.title,
      showSearchBar: true,
      showSettingsButton: true,
      searchController: _searchController,
      onSearchChanged: _onSearch,
      onSearchSubmitted: (query) => _onSearch(query),
      searchHintText: widget.hintText,
      returnButton: true,
      child: Stack(
        children: [
          // Logo cuando no hay búsqueda activa
          if (!_isSearching || _currentQuery.isEmpty)
            Positioned(
              bottom: 80.0,
              left: 0,
              right: 0,
              child: Center(
                child: Image.asset(
                  'assets/image/logo.png',
                  width: 200,
                ),
              ),
            ),

          // Resultados de búsqueda
          if (_isSearching)
            Padding(
              padding: const EdgeInsets.all(20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  _buildSearchHeader(),
                  const SizedBox(height: 16),
                  Expanded(
                    child: Expanded(
                      child: PagedListView<int, Draft>.separated(
                        pagingController: _pagingController,
                        padding: const EdgeInsets.only(bottom: 24, top: 8),
                        separatorBuilder: (context, index) =>
                            const SizedBox(height: 12),
                        builderDelegate: PagedChildBuilderDelegate<Draft>(
                          itemBuilder: (context, message, index) =>
                              widget.customItemBuilder != null
                                  ? widget.customItemBuilder!(
                                      message, _currentQuery)
                                  : _buildDefaultItem(message),
                          firstPageProgressIndicatorBuilder: (_) => Center(
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                AnimatedBuilder(
                                  animation: _pulseAnimation,
                                  builder: (context, child) {
                                    return Transform.scale(
                                      scale: _pulseAnimation.value,
                                      child: child,
                                    );
                                  },
                                  child: const CircularProgressIndicator(
                                    color: Color(0XFF6b8e23),
                                    strokeWidth: 3,
                                  ),
                                ),
                                const SizedBox(height: 16),
                                Container(
                                  padding: const EdgeInsets.symmetric(
                                      horizontal: 20, vertical: 10),
                                  decoration: BoxDecoration(
                                    color: const Color(0xFF6b8e23)
                                        .withOpacity(0.15),
                                    borderRadius: BorderRadius.circular(12),
                                    border: Border.all(
                                      color: const Color(0xFF6b8e23)
                                          .withOpacity(0.3),
                                      width: 1,
                                    ),
                                  ),
                                  child: Text(
                                    'searching_in_progress'.tr(),
                                    style: const TextStyle(
                                      fontSize: 14,
                                      fontWeight: FontWeight.w500,
                                      color: Color(0xFF6b8e23),
                                    ),
                                  ),
                                ),
                                // Mostrar el contador de resultados tan pronto como tengamos los datos
                                if (!dataLoading && totalResults > 0)
                                  Padding(
                                    padding: const EdgeInsets.only(top: 8),
                                    child: Container(
                                      padding: const EdgeInsets.symmetric(
                                          horizontal: 16, vertical: 8),
                                      decoration: BoxDecoration(
                                        color: const Color(0xFF6b8e23)
                                            .withOpacity(0.15),
                                        borderRadius: BorderRadius.circular(12),
                                        border: Border.all(
                                          color: const Color(0xFF6b8e23)
                                              .withOpacity(0.3),
                                          width: 1,
                                        ),
                                      ),
                                      child: Text(
                                        "$totalResults ${'results'.plural(totalResults)} ${'found'.tr()}",
                                        style: const TextStyle(
                                          fontSize: 16,
                                          fontWeight: FontWeight.bold,
                                          color: Color(0xFF6b8e23),
                                        ),
                                      ),
                                    ),
                                  ),
                              ],
                            ),
                          ),
                          newPageProgressIndicatorBuilder: (_) => Container(
                            padding: const EdgeInsets.symmetric(vertical: 16),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Container(
                                  padding: const EdgeInsets.symmetric(
                                      horizontal: 16, vertical: 10),
                                  decoration: BoxDecoration(
                                    color: const Color(0xFF6b8e23)
                                        .withOpacity(0.15),
                                    borderRadius: BorderRadius.circular(12),
                                    border: Border.all(
                                      color: const Color(0xFF6b8e23)
                                          .withOpacity(0.3),
                                      width: 1,
                                    ),
                                  ),
                                  child: Row(
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      AnimatedBuilder(
                                        animation: _pulseAnimation,
                                        builder: (context, child) {
                                          return Transform.scale(
                                            scale: _pulseAnimation.value,
                                            child: child,
                                          );
                                        },
                                        child: const SizedBox(
                                          width: 14,
                                          height: 14,
                                          child: CircularProgressIndicator(
                                            strokeWidth: 2,
                                            valueColor:
                                                AlwaysStoppedAnimation<Color>(
                                                    Color(0xFF6b8e23)),
                                          ),
                                        ),
                                      ),
                                      const SizedBox(width: 10),
                                      Text(
                                        'loading_more'.tr(),
                                        style: const TextStyle(
                                          fontSize: 13,
                                          fontWeight: FontWeight.w500,
                                          color: Color(0xFF6b8e23),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ),
                          noItemsFoundIndicatorBuilder: (_) =>
                              widget.emptyStateWidget ??
                              Center(
                                child: Column(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    Container(
                                      padding: const EdgeInsets.all(24),
                                      decoration: BoxDecoration(
                                        color: const Color(0xFF6b8e23)
                                            .withOpacity(0.1),
                                        shape: BoxShape.circle,
                                      ),
                                      child: const Icon(
                                        Icons.search_off_rounded,
                                        size: 48,
                                        color: Color(0XFF6b8e23),
                                      ),
                                    ),
                                    const SizedBox(height: 16),
                                    Container(
                                      padding: const EdgeInsets.symmetric(
                                          horizontal: 20, vertical: 12),
                                      decoration: BoxDecoration(
                                        color: const Color(0xFF6b8e23)
                                            .withOpacity(0.15),
                                        borderRadius: BorderRadius.circular(12),
                                        border: Border.all(
                                          color: const Color(0xFF6b8e23)
                                              .withOpacity(0.3),
                                          width: 1,
                                        ),
                                      ),
                                      child: Text(
                                        'no_results'.tr(),
                                        style: const TextStyle(
                                          fontSize: 16,
                                          fontWeight: FontWeight.w600,
                                          color: Color(0xFF6b8e23),
                                        ),
                                      ),
                                    ),
                                    const SizedBox(height: 8),
                                    Padding(
                                      padding: const EdgeInsets.symmetric(
                                          horizontal: 40),
                                      child: Text(
                                        'try_different_search'.tr(),
                                        textAlign: TextAlign.center,
                                        style: TextStyle(
                                          fontSize: 14,
                                          color: Colors.grey[700],
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                          firstPageErrorIndicatorBuilder: (context) =>
                              widget.errorWidget ??
                              Center(
                                child: Column(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    const Icon(
                                      Icons.error_outline,
                                      size: 64,
                                      color: Colors.red,
                                    ),
                                    const SizedBox(height: 16),
                                    Text(
                                      'search_error'.tr(),
                                      style: const TextStyle(
                                        fontSize: 18,
                                        fontWeight: FontWeight.bold,
                                      ),
                                    ),
                                    const SizedBox(height: 8),
                                    ElevatedButton(
                                      onPressed: () =>
                                          _pagingController.refresh(),
                                      child: Text('retry'.tr()),
                                    ),
                                  ],
                                ),
                              ),
                        ),
                        // Configure to load the next page earlier
                        scrollDirection: Axis.vertical,
                        shrinkWrap: true,
                        addAutomaticKeepAlives: true,
                        addRepaintBoundaries: true,
                        // Add these properties to make pagination more responsive
                        addSemanticIndexes: false,
                        physics: const AlwaysScrollableScrollPhysics(),
                      ),
                    ),
                  ),
                ],
              ),
            ),
        ],
      ),
    );
  }

  String _getMatchedText(String content, String searchQuery) {
    if (searchQuery.isEmpty) return '';

    // Convertir a minúsculas para búsqueda insensible a mayúsculas/minúsculas
    final lowerContent = content.toLowerCase();
    final lowerQuery = searchQuery.toLowerCase();

    // Buscar la coincidencia exacta
    final int index = lowerContent.indexOf(lowerQuery);
    if (index != -1) {
      // Devolver el texto original que coincidió, no la versión en minúsculas
      return content.substring(index, index + searchQuery.length);
    }

    // Si no hay coincidencia exacta, buscar palabras individuales
    final queryWords = lowerQuery
        .split(RegExp(r'\s+'))
        .where((word) => word.length > 2)
        .toList();

    for (final word in queryWords) {
      final wordIndex = lowerContent.indexOf(word);
      if (wordIndex != -1) {
        // Devolver la primera palabra que coincida
        return content.substring(wordIndex, wordIndex + word.length);
      }
    }

    return searchQuery; // Fallback al término de búsqueda original
  }

  void _showNotification() {
    NotificationService().showSearchNotification(
      title: 'search'.tr(),
      body: 'empty_results'.tr(),
    );
  }
}
