import 'dart:convert';

import 'dart:typed_data';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:file_picker/_internal/file_picker_web.dart';
import 'package:file_picker/file_picker.dart';

import 'package:image_picker/image_picker.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import 'package:pluto_grid/pluto_grid.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:path/path.dart' as p;

import 'package:cbluna_crm_lu/helpers/globals.dart';
import 'package:cbluna_crm_lu/models/content_manager/ad_by_genre.dart';
import 'package:cbluna_crm_lu/pages/widgets/toasts/msj_toast.dart';

import '../../lib/models/content_manager/all_ads_one_table_model.dart';
import '../../lib/pages/widgets/video_player_caro.dart';

class VideosProvider extends ChangeNotifier {
  List<PlutoGridStateManager> listStateManager = [];
  PlutoGridStateManager? stateManager;

  final controllerBusqueda = TextEditingController();
  String parametroBusqueda = "";

  TextEditingController modeloController = TextEditingController();

  String? videoCoverFile;
  String? videoName;
  String? videoUrl;
  String? videoPath;

  String fileExtension = '';
  String resolucion = "1";
  String area = "7";

  Uint8List? webVideo;
  String? categoryImgFileName;
  Uint8List? categoryImageToUpload;

  String? categoryName;
  bool noImageToUpload = true;

  //-------
  late final TextEditingController filasController;
  //-------

  List<List<dynamic>> listPagos = [];

  final controllerCount = TextEditingController();
  int countI = 0;
  int countF = 19;

  final controllerBusquedaFiltro = TextEditingController();

  bool filtroAvanzado = false;
  bool filtroSimple = false;

  ///////////////////////////////////////////

  var tableTop1Gourp = AutoSizeGroup();
  var tableTopGroup = AutoSizeGroup();
  var tableContentGroup = AutoSizeGroup();
  final busquedaVideoController = TextEditingController();
  ///////////////////////////////////////////
  late MsjToast toastMessage;

  ///
  ///

  List<AdsByGenre> adsByGenre = [];
  List<List<PlutoRow>> rows = [];
  List<PlutoRow> rows_ = [];
  List<PlutoRow> allVideoRows = [];
  List<String> listaQrsSeleccionados = [];
  //----------------------------------------------Paginador variables

  int seccionActual = 1;
  int totalSecciones = 1;
  int totalFilas = 0;
  int from = 0;
  int hasta = 20;

  //----------------------------------------------Calendario Programacion

  FilePickerResult? docProveedor;
  //----------------------------------------------Video data
  String? videoCoverFileNameNoModif;
  List<String> videoCategories = [];
  List<int> videoCategoriesId = [];
  List<String> selectedVideoCategories = [];
  List<int> selectedVideoCategoriesId = [];
  List<String> videoCategoriesImages = [];

  String? posterPath;
  String tituloVideo = '';
  String descripcionVideo = '';
  String videoOutlink = '';
  String videoPatner = '';
  Uint8List? videoPoster;
  int videoPoints = 0;
  Duration duracionVideo = Duration.zero;
  int duratinVideoSeconds = 0;
  List<String> videoPriority = [];
  String? videoPosterPath;
  //----------------------------------------------VideoYables
  bool showFullVideoTable = true;
  List<AllAdsOneTableModel> videos = [];
  String selectePriority = "baja";

  int warningCountTablaVideos = 0;
  bool showWarningsOnTable = false;
  int? selectedVideoId;
//----------------------------------------------
  VideosProvider() {
    getVideoPrioritiesList();
    getCategories();
    refreshVideoTablet();
  }

  updateState(AdsByGenre expandir) {
    expandir.isExpanded = !expandir.isExpanded;
    notifyListeners();
  }

  getVideoData(Duration? duracion, int? duracionSegundos) async {
    duracionVideo = duracion ?? Duration.zero;
    duratinVideoSeconds = duracionSegundos ?? 0;
  }

  setVideoTableFullOrCategories(int index) {
    switch (index) {
      case 0:
        showFullVideoTable = true;
        getAllAdsOnOneTable();
        break;
      case 1:
        showFullVideoTable = false;
        getAdsByCategories();
        break;
      default:
        showFullVideoTable = false;
        getAdsByCategories();
    }
    notifyListeners();
    return;
  }

  getAdsByCategories() async {
    try {
      final query = supabaseLU.rpc('lu_buscar_videos_por_genero', params: {
        'busqueda': busquedaVideoController.text,
      });

      final res = await query.select();

      if (res == null) {
        return;
      }

      adsByGenre = (res as List<dynamic>)
          .map((ad) => AdsByGenre.fromJson(jsonEncode(ad)))
          .toList();

      rows_ = [];
      rows_.clear();
      rows.clear();

      for (var genre in adsByGenre) {
        adsByGenre[adsByGenre.indexOf(genre)].videoCount = genre.videos.length;
        for (var video in genre.videos) {
          rows_.add(PlutoRow(cells: {
            'video_id': PlutoCell(value: video.videoId.toString()),
            'posterPath': PlutoCell(
                value: video.posterFileName != null
                    ? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
                    : ''),
            'status': PlutoCell(value: video.status ?? 'neutra'),
            'priority': PlutoCell(value: video.priority),
            'title': PlutoCell(value: video.title),
            'urlAd': PlutoCell(value: video.urlAd ?? ''),
            'overview': PlutoCell(value: video.overview),
            'points': PlutoCell(value: 1),
            'expirationDate': PlutoCell(value: video.expirationDate ?? ''),
            'created_at': PlutoCell(value: video.createdAt ?? ''),
            'durationVideo': PlutoCell(value: video.duration ?? ''),
            'video_url': PlutoCell(
                value: video.videoUrl != null
                    ? "${supabase.storage.from('lectores_urb/videos/cm_videos').getPublicUrl(video.videoFileName.toString())}?${DateTime.now().millisecondsSinceEpoch}"
                    : ''),
            'editar': PlutoCell(value: video.videoId),
            'eliminar': PlutoCell(value: video.videoId),
            'video_file_name': PlutoCell(value: video.videoFileName.toString()),
            'poster_file_name':
                PlutoCell(value: video.posterFileName.toString()),
            'patner': PlutoCell(value: video.partner ?? ''),
            'categories': PlutoCell(value: video.categories ?? ''),
            'video_status': PlutoCell(value: video.videoStatus),
          }));
        }
        rows.add(rows_);
        rows_ = [];
      }
      showWarningsOnTable = false;
      notifyListeners();
      return;
    } catch (e) {
      print('error en getAdsByCategories():  ${e.toString()}');
    }
    notifyListeners();
    return;
  }

  getAdsByCategoriesWarnings() async {
    try {
      final query = supabaseLU.rpc('lu_buscar_videos_por_genero', params: {
        'busqueda': busquedaVideoController.text,
      });

      final res = await query.select();

      if (res == null) {
        return;
      }

      adsByGenre = (res as List<dynamic>)
          .map((ad) => AdsByGenre.fromJson(jsonEncode(ad)))
          .toList();

      rows_ = [];
      rows_.clear();
      rows.clear();
      for (var genre in adsByGenre) {
        genre.videoCount = 0;
        for (var video in genre.videos!) {
          if (video.categories[0] == [null] ||
              video.categories[0].isEmpty ||
              video.categories[0] == [""] ||
              video.categories[0] == ["null"] ||
              video.urlAd == null ||
              video.urlAd == "" ||
              video.urlAd == "null" ||
              video.overview == "" ||
              video.overview == "null" ||
              video.partner == "" ||
              video.partner == null) {
            rows_.add(PlutoRow(cells: {
              'video_id': PlutoCell(value: video.videoId.toString()),
              'posterPath': PlutoCell(
                  value: video.posterFileName != null
                      ? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
                      : 'https://placehold.co/150x150'),
              'status': PlutoCell(value: video.status ?? 'neutra'),
              'priority': PlutoCell(value: video.priority ?? '4'),
              'title': PlutoCell(value: video.title),
              'urlAd': PlutoCell(value: video.urlAd ?? ''),
              'overview': PlutoCell(value: video.overview),
              'points': PlutoCell(value: video.points ?? ''),
              'expirationDate': PlutoCell(value: video.expirationDate ?? ''),
              'created_at': PlutoCell(value: video.createdAt ?? ''),
              'durationVideo': PlutoCell(value: video.duration ?? ''),
              'video_url': PlutoCell(
                  value: video.videoUrl != null
                      ? "${supabase.storage.from('lectores_urb/videos/cm_videos').getPublicUrl(video.videoFileName.toString())}?${DateTime.now().millisecondsSinceEpoch}"
                      : ''),
              'editar': PlutoCell(value: video.videoId),
              'eliminar': PlutoCell(value: video.videoId),
              'video_file_name':
                  PlutoCell(value: video.videoFileName.toString()),
              'poster_file_name':
                  PlutoCell(value: video.posterFileName.toString()),
              'patner': PlutoCell(value: video.partner ?? ''),
              'categories': PlutoCell(value: video.categories ?? ''),
              'video_status': PlutoCell(value: video.videoStatus),
            }));
            genre.videoCount += 1;
          }
        }
        rows.add(rows_);
        rows_ = [];
      }

      showWarningsOnTable = true;
      notifyListeners();
      return;
    } catch (e) {
      print('error en getAdsCategoriesWarning:  ${e.toString()}');
    }
  }

  getAllAdsOnOneTable([bool warningMode = false]) async {
    try {
      final String query = busquedaVideoController.text.trim();

      final res = await supabaseLU.rpc('lu_buscar_videos', params: {
        'busqueda': query.isEmpty ? null : query,
        'warningmode': false,
      });

      if (res == null) {
        print("--X---Error: respuesta nula al llamar RPC.");
        return;
      }

      try {
        videos = (res as List<dynamic>)
            .map((ad) => AllAdsOneTableModel.fromJson(jsonEncode(ad)))
            .toList();
      } catch (e) {
        print("Error al parsear lista de videos: ${e.toString()}");
      }

      allVideoRows.clear();

      // El warning count total lo devuelve cada fila, tomamos el primero
      warningCountTablaVideos =
          videos.isNotEmpty ? videos.first.warningCount : 0;

      for (AllAdsOneTableModel video in videos) {
        allVideoRows.add(PlutoRow(cells: {
          'video_id': PlutoCell(value: video.id),
          'poster_path': PlutoCell(
              value: video.posterFileName != null
                  ? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
                  : 'https://placehold.co/150x150'),
          'priority': PlutoCell(value: video.priority),
          'title': PlutoCell(value: video.title),
          'url_ad': PlutoCell(value: video.urlAd ?? ''),
          'overview': PlutoCell(value: video.overview),
          'points': PlutoCell(value: video.points),
          'expiration_date': PlutoCell(value: video.expirationDate),
          'created_at': PlutoCell(value: video.createdAt),
          'duration_video': PlutoCell(value: video.durationVideo),
          'video_url': PlutoCell(
            value: video.video.isNotEmpty
                ? "${video.video}?${DateTime.now().millisecondsSinceEpoch}"
                : '',
          ),
          'editar': PlutoCell(value: video.id),
          'eliminar': PlutoCell(value: video.id),
          'video_file_name': PlutoCell(value: video.videoFileName ?? ''),
          'poster_file_name': PlutoCell(value: video.posterFileName ?? ''),
          'partner': PlutoCell(value: video.partner ?? ''),
          'categories': PlutoCell(value: video.categories),
          'video_status': PlutoCell(value: video.videoStatus),
          'qr_codes': PlutoCell(
            value: video.qrCodes.expand((entry) {
              try {
                final details = entry['details'];

                // Verifica si 'details' está presente y tiene la clave 'qrs'
                if (details != null &&
                    details is Map<String, dynamic> &&
                    details['qrs'] is List) {
                  return (details['qrs'] as List)
                      .map((qrsEntry) => qrsEntry['qrs_concat'])
                      .whereType<String>();
                }
              } catch (e) {
                // Si ocurre un error al intentar acceder a los datos, lo manejamos de forma silenciosa
                print('Error al acceder a QR details: $e');
              }
              return []; // Devuelve una lista vacía en caso de error o datos inválidos
            }).join('\n'), // o ', ' si prefieres en una sola línea
          ),
          'qr_codes_list': PlutoCell(
            value: video.qrCodes.expand((entry) {
              try {
                final details = entry['details'];
                if (details != null &&
                    details is Map<String, dynamic> &&
                    details['qrs'] is List) {
                  return (details['qrs'] as List)
                      .map((qrsEntry) => qrsEntry['qrs_concat'])
                      .whereType<String>();
                }
              } catch (e) {
                print('Error al acceder a QR details (lista): $e');
              }
              return [];
            }).toList(), // ← clave aquí
          ),
        }));
      }

      showWarningsOnTable = false;
      notifyListeners();
    } catch (e) {
      print('Error en getAllAdsOnOneTable: ${e.toString()}');
      notifyListeners();
    }
  }

  getAllAdsOnOneTableWarnings() async {
    try {
      final res = await supabaseLU.from('videos_view').select();
      if (res == null) {
        print("--X---Error: ${res.error}");
        return;
      }

      videos = (res as List<dynamic>)
          .map((ad) => AllAdsOneTableModel.fromJson(jsonEncode(ad)))
          .toList();

      allVideoRows.clear();

      for (AllAdsOneTableModel video in videos) {
        if (video.categories[0] == [null] ||
            video.categories[0] == null ||
            video.categories[0] == [] ||
            video.categories[0] == [""] ||
            video.categories[0] == ["null"] ||
            video.urlAd == "" ||
            video.urlAd == null ||
            video.urlAd == "null" ||
            video.overview == "" ||
            video.overview == "null" ||
            video.partner == "" ||
            video.partner == null) {
          allVideoRows.add(PlutoRow(cells: {
            'id': PlutoCell(value: video.id),
            'posterPath': PlutoCell(
                value: video.posterFileName != null
                    ? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
                    : 'https://placehold.co/150x150'),
            'priority': PlutoCell(value: video.priority ?? '4'),
            'title': PlutoCell(value: video.title ?? ''),
            'urlAd': PlutoCell(value: video.urlAd.toString() ?? ''),
            'overview': PlutoCell(value: video.overview ?? ''),
            'points': PlutoCell(value: video.points ?? ''),
            'expirationDate': PlutoCell(value: video.expirationDate ?? ''),
            'created_at': PlutoCell(value: video.createdAt ?? ''),
            'durationVideo': PlutoCell(value: video.durationVideo ?? ''),
            'video_url': PlutoCell(
                value:
                    "${supabase.storage.from('lectores_urb/videos/cm_videos').getPublicUrl(video.videoFileName.toString())}?${DateTime.now().millisecondsSinceEpoch}"),
            'editar': PlutoCell(value: video.id),
            'eliminar': PlutoCell(value: video.id),
            'video_file_name': PlutoCell(value: video.videoFileName ?? ''),
            'poster_file_name': PlutoCell(value: video.posterFileName ?? ''),
            'patner': PlutoCell(value: video.partner ?? ''),
            'categories': PlutoCell(value: video.categories ?? ''),
            'video_status': PlutoCell(value: video.videoStatus),
          }));
        }
      }
      showWarningsOnTable = true;
      notifyListeners();
      return;
    } catch (e) {
      print('error en getAllAdsOnOneTableWarnings:  ${e.toString()}');
    }
    notifyListeners();
    return;
  }

  Future<List<String>> getCategories() async {
    try {
      final res = await supabaseLU
          .from('video_genero')
          .select('name, id, poster_image_file')
          .eq('visible', true)
          .order('name', ascending: true);

      videoCategories = (res as List<dynamic>)
          .map((category) => category['name'] as String)
          .toList();

      videoCategoriesId = (res as List<dynamic>)
          .map((category) => category['id'] as int)
          .toList();

      videoCategoriesImages = (res as List<dynamic>)
          .map((category) => category['poster_image_file'] as String)
          .toList();

      return videoCategories;
    } catch (e) {
      print("ERROR en getVideosVinculados: " + e.toString());
      notifyListeners();
      return [];
    }
  }

  //usando el id del video cambiar su estado "video_status" a true o false
  cambiarEstadoVideo(int idVideo, bool estado) async {
    await supabaseLU
        .from('videos')
        .update({'video_status': estado})
        .eq('id', idVideo)
        .select();
  }

/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */

  Widget? getPosterImage(dynamic image,
      {double height = 180, BoxFit boxFit = BoxFit.cover}) {
    if (image == null) {
      return Image.asset('assets/images/placeholder_no_image.jpg');
    } else if (image is Uint8List) {
      return Image.memory(
        image,
        height: height,
        width: double.infinity,
        fit: boxFit,
      );
    } else if (image is String) {
      return Image.network(
        image,
        height: height,
        width: double.infinity,
        filterQuality: FilterQuality.high,
        fit: boxFit,
      );
    } else {
      return Image.asset('assets/images/placeholder_no_image.jpg');
    }
  }

  Widget? getCategoryImage(dynamic image,
      {double height = 180, BoxFit boxFit = BoxFit.cover}) {
    if (image == null) {
      noImageToUpload = true;

      return Image.asset('assets/images/placeholder_upload_image.png');
    } else if (image is Uint8List) {
      noImageToUpload = false;

      return Image.memory(
        image,
        height: height,
        width: double.infinity,
        fit: boxFit,
      );
    } else if (image is String) {
      noImageToUpload = false;

      return Image.network(
        "${supabase.storage.from('lectores_urb/imagenes/videos/categories').getPublicUrl(image)}?${DateTime.now().millisecondsSinceEpoch}",
        height: height,
        width: double.infinity,
        filterQuality: FilterQuality.high,
        fit: boxFit,
      );
    } else {
      noImageToUpload = true;

      return Image.asset('assets/images/placeholder_upload_image.png');
    }
  }

  //get video widget   VideoScreenNew;

  Widget? getVideoWidget(dynamic image,
      {double height = 180, width = 500, BoxFit boxFit = BoxFit.contain}) {
    if (videoPath == null) {
      return Image.asset('assets/images/placeholder_no_video.png',
          width: width, height: height, fit: boxFit);
    } else {
      return VideoScreenNew(
        videoUrl: videoPath,
      );
    }
  }

/////////////CATEGORY///////////////////////

  Future<void> selectCategoryImage() async {
    categoryImgFileName = null;
    categoryImageToUpload = null;
    FilePickerResult? picker = await FilePickerWeb.platform
        .pickFiles(type: FileType.custom, allowedExtensions: ['jpg', 'png']);

    //get and load pdf
    if (picker != null) {
      var now = DateTime.now();
      var formatter = DateFormat('yyyyMMddHHmmss');
      var timestamp = formatter.format(now);

      categoryImgFileName = 'category-$timestamp-${picker.files.single.name}';
      categoryImageToUpload = picker.files.single.bytes;
      noImageToUpload = false;
    } else {
      categoryImgFileName = null;
      categoryImageToUpload = null;
    }

    notifyListeners();
    return;
  }

  uploadCategoryImage() async {
    if (categoryImageToUpload != null && categoryImgFileName != null) {
      await supabase.storage
          .from('lectores_urb/imagenes/videos/categories')
          .uploadBinary(
            categoryImgFileName!,
            categoryImageToUpload!,
            fileOptions: const FileOptions(
              cacheControl: '3600',
              upsert: false,
            ),
          );

      return;
    }
    return null;
  }

  Future<bool> registrarNuevaCategoria() async {
    await uploadCategoryImage();

    final res = await supabaseLU.from('video_genero').insert(
      {
        'name': categoryName,
        'poster_image_file': categoryImgFileName,
      },
    ).select();

    if (res == null) {
      print("Error al registrar categoria");
      print(res.error!.message);
      return false;
    }

    return true;
  }

/////////////ACTUALIZAR CATEGORIA///////////////////////

  Future<bool> updateCategory(int idCategory, String? name) async {
    if (categoryImageToUpload == null) {
      final res = await supabaseLU
          .from('video_genero')
          .update(
            {
              'name': name.toString(),
            },
          )
          .eq('id', idCategory)
          .select();

      if (res == null) {
        print("Error al registrar updateCategory1");
        print(res.error!.message);
        return false;
      }
      return true;
    }
//---------------------------------------------------------------
    final getFileName = await supabaseLU
        .from('video_genero')
        .select('poster_image_file')
        .eq('id', idCategory)
        .single();

    if (getFileName['poster_image_file'] != null &&
        categoryImageToUpload != null) {
      await supabase.storage
          .from('lectores_urb/imagenes/videos/categories')
          .updateBinary(
            getFileName['poster_image_file'],
            categoryImageToUpload!,
            fileOptions: const FileOptions(
              cacheControl: '3600',
              upsert: false,
            ),
          );
    } else {
      print("NO EXISTE SUBIR");
      await supabase.storage
          .from('lectores_urb/imagenes/videos/categories')
          .uploadBinary(
            categoryImgFileName!,
            categoryImageToUpload!,
            fileOptions: const FileOptions(
              cacheControl: '3600',
              upsert: false,
            ),
          );
      await supabaseLU
          .from('video_genero')
          .update(
            {
              'poster_image_file': categoryImgFileName,
            },
          )
          .eq('id', idCategory)
          .select();
    }

//---------------------------------------------------------------
    return true;
  }

/////////////BORRAR CATEGORIA///////////////////////

  Future<bool> deleteCategory(int idCategory, String? filename) async {
    await supabaseLU
        .from('video_in_genero')
        .delete()
        .eq('genero_id', idCategory)
        .select();

    await supabase.storage
        .from('lectores_urb')
        .remove(["imagenes/videos/categories/$filename"]);

    await supabaseLU
        .from('video_genero')
        .delete()
        .eq('id', idCategory)
        .select();
    categoryImgFileName = null;

    resetAllvideoData();
    getCategories();
    refreshVideoTablet();

    return true;
  }

//---------------ATUALIZAR VIDEOS------------------

  Future<bool> updateVideoData(
    int idVideo,
    String title,
    String description,
    String partner,
    String outlink,
    int points,
    List<int> selectedVideoCategoriesId, {
    String? videoImage,
    String? posterImage,
    String? posterFileName,
    List<String>? qrList,
  }) async {
/*     print("updateVideoData");
    print("idVideo: $idVideo");
    print("title: $title");
    print("description: $description");
    print("partner: $partner");
    print("outlink: $outlink");
    print("points: $points");
    print("selectedVideoCategoriesId: $selectedVideoCategoriesId");
    print("posterFileName: $posterFileName");
    print("posterImage: $posterImage");
    print("videoImage: $videoImage");
    print("qrList: $qrList"); */

    if (qrList != null) {
      final existingQrs = await getQrsByVideoId(idVideo);
      // Eliminar los QRs que no están en qrList
      for (String qr in existingQrs) {
        if (!qrList.contains(qr)) {
          await supabaseLU
              .from('video_in_qr')
              .delete()
              .eq('id_qr_fk', qr)
              .eq('id_video_fk', idVideo)
              .select();
        }
      }

      // Agregar nuevos QRs
      for (String qr in qrList) {
        if (!existingQrs.contains(qr)) {
          await supabaseLU.from('video_in_qr').insert({
            'id_qr_fk': qr,
            'id_video_fk': idVideo,
          }).select();
        }
      }
    }

    final priorityrecibe = await getPriorityId(selectePriority);
    final res = await supabaseLU
        .from('videos')
        .update(
          {
            'title': title.toString(),
            'overview': description.toString(),
            'url_ad': outlink.toString(),
            'partner': partner.toString(),
            'points': 1,
            'priority': priorityrecibe,
            'video_status': true,
          },
        )
        .eq('id', idVideo)
        .select();

    if (res == null) {
      print("Error al registrar updateVideoTitulo");
      print(res.error!.message);
      resetAllvideoData();
      return false;
    }

    if (webVideo != null) {
      final getFileName = await supabaseLU
          .from('videos')
          .select('video_file_name')
          .eq('id', idVideo)
          .single();

      print("getFileName: $getFileName");
      if (getFileName['video_file_name'] != null) {
        await supabase.storage
            .from('lectores_urb/videos/cm_videos')
            .updateBinary(
              getFileName['video_file_name'],
              webVideo!,
              fileOptions: const FileOptions(
                cacheControl: '3600',
                upsert: false,
              ),
            );

        webVideo = null;
      }
    }

    if (videoPoster != null) {
      await supabase.storage
          .from('lectores_urb/imagenes/videos/posters')
          .updateBinary(videoCoverFileNameNoModif.toString(), videoPoster!);
    }
    await supabaseLU
        .from('video_in_genero')
        .delete()
        .eq('video_id', idVideo)
        .select();
    await registrarCategoriasDelVideoUsandoId(
        idVideo, selectedVideoCategoriesId);

    resetAllvideoData();

    refreshVideoTablet();
    return true;
  }

/////////////VIDEOS///////////////////////

  getVideoPrioritiesList() async {
    final res = await supabaseLU.from('video_priority').select("name");

    videoPriority = (res as List<dynamic>)
        .map((priority) => priority['name'] as String)
        .toList();

    return videoPriority;
  }

  Future<String?> uploadPosterImage() async {
    if (videoPoster != null && videoCoverFile != null) {
      await supabase.storage
          .from('lectores_urb/imagenes/videos/posters')
          .uploadBinary(
            '$videoName-$videoCoverFile',
            videoPoster!,
            fileOptions: const FileOptions(
              cacheControl: '3600',
              upsert: false,
            ),
          );

      final res = await supabase.storage
          .from('lectores_urb/imagenes/videos/posters')
          .getPublicUrl('$videoName-$videoCoverFile');

      posterPath = res;

      return videoCoverFile;
    }
    return null;
  }

  Future<void> selectPosterImage() async {
    videoCoverFile = null;
    videoPoster = null;
    FilePickerResult? picker = await FilePickerWeb.platform
        .pickFiles(type: FileType.custom, allowedExtensions: ['jpg', 'png']);

    //get and load pdf
    if (picker != null) {
      var now = DateTime.now();
      var formatter = DateFormat('yyyyMMddHHmmss');
      var timestamp = formatter.format(now);

      videoCoverFile = 'poster-$timestamp-${picker.files.single.name}';
      videoPoster = picker.files.single.bytes;
    } else {
      videoCoverFile = null;
      videoPoster = null;
    }

    notifyListeners();
    return;
  }

  Future<bool> selectVideo() async {
    videoName = "";

    final ImagePicker picker = ImagePicker();

    final XFile? pickedVideo = await picker.pickVideo(
      source: ImageSource.gallery,
    );

    if (pickedVideo == null) return false;

    fileExtension = p.extension(pickedVideo.name);

    videoPath = pickedVideo.path;
    videoName = pickedVideo.name;
    videoName = videoName!.replaceAll(fileExtension, "");
    webVideo = await pickedVideo.readAsBytes();

    return true;
  }

  Future<bool> uploadVideo(List<int> categoryID, {List<String>? qrList}) async {
    try {
      if (webVideo != null && videoName != null) {
        final files = await supabase.storage
            .from('lectores_urb')
            .list(path: 'videos/cm_videos');

        // Verificar si el archivo ya existe
        final fileExists =
            files.any((file) => file.name == '$videoName$fileExtension');

        if (fileExists) {
          toastMessage = MsjToast(
            message: 'video already exists',
            color: Color.fromARGB(255, 236, 187, 50),
          );
          return false;
        }

        if (videoCoverFile == null) {
          toastMessage = MsjToast(
            message: 'No poster selected, upload an image to continue',
            color: Color.fromARGB(255, 236, 187, 50),
          );

          return false;
        }

        //check if videoCoverFile  ya existe en storage
        final filesPoster = await supabase.storage
            .from('lectores_urb')
            .list(path: 'imagenes/videos/posters');

        // Verificar si el archivo ya existe
        final fileExistsPoster = filesPoster
            .any((file) => file.name == '$videoName-$videoCoverFile');

        if (fileExistsPoster) {
          toastMessage = MsjToast(
            message: 'poster file name already exists, (change the name)',
            color: Color.fromARGB(255, 236, 187, 50),
          );
          return false;
        }

        final storageResponse = await supabase.storage
            .from('lectores_urb/videos/cm_videos')
            .uploadBinary(
              '$videoName$fileExtension',
              webVideo!,
              fileOptions: const FileOptions(
                cacheControl: '3600',
                upsert: false,
              ),
            );

        if (storageResponse == null) return false;

        dynamic res = supabase.storage
            .from('lectores_urb/videos/cm_videos')
            .getPublicUrl('$videoName$fileExtension');
        videoUrl = res;

        if (await registrarVideo2(categoryID, qrList: qrList)) {
          return true;
        } else {
          return false;
        }
      }
      return false;
    } catch (e) {
      print("Error en uploadVideo: $e");
      return false;
    }
  }

  //get priority id using name
  Future<int> getPriorityId(String priorityName) async {
    final res = await supabaseLU
        .from('video_priority')
        .select("id")
        .eq("name", priorityName)
        .limit(1);

    if (res == null) {
      print("Error al obtener id de prioridad");
      print(res.error!.message);
      return 0;
    }

    return res[0]['id'];
  }

  Future<bool> registrarCategoriasDelVideoUsandoId(
      int idVideo, List<int> listaIdsCategorias) async {
    try {
      await supabaseLU.rpc('lu_añadir_generos_al_video', params: {
        'lista_id_generos': listaIdsCategorias,
        'videoid': idVideo
      }).select();

      return true;
    } catch (e) {
      print("Error al registrar Categorias del video");
      print(e.toString());
      return false;
    }
  }

  Future<bool> obtenerIdVideoUsandoNombreArchivoStorage(
      String videoPath) async {
    //obtiene el id del video recien registrado usando su archivo cargado
    final res = await supabaseLU
        .from('videos')
        .select("id")
        .eq("video_file_name", videoPath)
        .limit(1);

    if (res == null) {
      print("Error al al obtener id del video");
      print(res.error!.message);
      return false;
    }

    await registrarCategoriasDelVideoUsandoId(
        res[0]['id'], selectedVideoCategoriesId);

    return true;
  }

  Future<bool> deleteVideo2(
      int idVideo, String videoFileName, String posterFileName) async {
    try {
      // Llamada al RPC para eliminar el video y obtener los nombres de archivos
      final res = await supabaseLU
          .rpc('lu_borrar_video', params: {'id_video': idVideo});

      // Validar la respuesta
      if (res == null || res.isEmpty) {
        print("El video no pudo ser eliminado o no existe.");
        refreshVideoTablet();
        return false;
      }
      await supabaseLU.from('videos').delete().eq('id', idVideo).select();
      await eliminarVideo(videoFileName, posterFileName);

      refreshVideoTablet();
      return true;
    } catch (e) {
      print("Error al eliminar el video: ${e.toString()}");
      refreshVideoTablet();
      return false;
    }
  }

  Future<bool> eliminarVideo(
      String videoFileName, String posterFileName) async {
    await supabase.storage
        .from('lectores_urb')
        .remove(['videos/cm_videos/$videoFileName']);
    await supabase.storage
        .from('lectores_urb')
        .remove(['imagenes/videos/posters/$posterFileName']);

    return true;
  }

  Future<List<Map<String, dynamic>>> getGroupedQRCodesByCustomer() async {
    try {
      // Llamada al RPC en Supabase
      final res = await supabaseLU.rpc('get_qr_codes_grouped_by_customer');

      // Validar el resultado
      if (res == null || res.isEmpty) {
        print("No se encontraron datos agrupados.");
        return [];
      }

      // Convertir los resultados en una lista de Map
      return List<Map<String, dynamic>>.from(res).map((group) {
        return {
          'row_number': group['row_number'],
          'customer_fk': group['customer_fk'],
          'customer_name': group['customer_name'],
          'details': group['details'], // JSONB con los detalles
        };
      }).toList();
    } catch (e) {
      print("Error en getGroupedQRCodesByCustomer: ${e.toString()}");
      return []; // Retornar una lista vacía en caso de error
    }
  }

  Future<List<String>> getQrsByVideoId(int videoId) async {
    try {
      final response = await supabaseLU
          .from('video_in_qr')
          .select('id_qr_fk')
          .eq('id_video_fk', videoId);

      if (response == null) {
        print('Error al obtener getQrsByCouponId()');
        return [];
      }

      return List<String>.from(
        (response as List<dynamic>).map((item) => item['id_qr_fk']),
      );
    } catch (e) {
      print("Error en getQrsByVideoId: ${e.toString()}");
      return []; // Retornar una lista vacía en caso de error
    }
  }

  void resetAllvideoData() {
    videoPoster = null;
    videoCoverFile = null;
    videoPath = null;
    videoName = null;
    selectedVideoCategoriesId = [];
    selectedVideoCategories = [];
    categoryImgFileName = null;
    categoryImageToUpload = null;
    noImageToUpload = true;
    selectePriority = "baja";
    videoOutlink = "";
    videoPoints = 0;
    descripcionVideo = "";
    videoPatner = "";
    videoUrl = null;
    webVideo = null;
    posterPath = null;
    videoPosterPath = null;
    tituloVideo = "";
    return;
  }

  void clearPosterImage() {
    videoPoster = null;
    videoCoverFile = null;
    videoPosterPath = null;

    notifyListeners();
    return;
  }

  void clearControllers() {
    modeloController.clear();
    notifyListeners();
  }

  void updatestateManager() {
    print(videoName);

    notifyListeners();
  }

  void clearVideo() {
    videoPath = null;
    webVideo = null;
    notifyListeners();
  }

  void refreshVideoTablet() {
    print(showWarningsOnTable);
    if (showWarningsOnTable && warningCountTablaVideos > 0) {
      showFullVideoTable == true
          ? getAllAdsOnOneTableWarnings()
          : getAdsByCategoriesWarnings();
    } else {
      showFullVideoTable == true ? getAllAdsOnOneTable() : getAdsByCategories();
    }
  }

  Future<bool> registrarVideo2(List<int> categoryIds,
      {List<String>? qrList}) async {
    await uploadPosterImage();
    final priorityrecibe = await getPriorityId(selectePriority);

    final res = await supabaseLU.rpc(
      'lu_registrar_videos_master',
      params: {
        'p_title': tituloVideo,
        'p_overview': descripcionVideo,
        'p_video_url': videoUrl,
        'p_url_ad': videoOutlink,
        'p_poster_path': posterPath ??
            "https://u-supabase.virtalus.cbluna-dev.com/storage/v1/object/public/assets/placeholder_no_image.jpg",
        'p_poster_file_name': '$videoName-$videoCoverFile',
        'p_video_file_name': '$videoName$fileExtension',
        'p_duration_video': duratinVideoSeconds,
        'p_partner': videoPatner,
        'p_priority': priorityrecibe,
        'p_qr_list': qrList,
        'p_category_ids': categoryIds
      },
    ).select();

    if (res == null) {
      print("Error al registrar video");
      print(res.error!.message);
      return false;
    }

    if (await obtenerIdVideoUsandoNombreArchivoStorage(
        '$videoName$fileExtension')) {
      videoName = "";
      descripcionVideo = "";
      refreshVideoTablet();
      return true;
    } else {
      videoName = "";
      descripcionVideo = "";
      refreshVideoTablet();
      return false;
    }
  }
}
