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

import '../models/models.dart';
import '../services/services.dart';

class PedidoViewModel extends ChangeNotifier {
  String _busqueda = "";
  String get busqueda => _busqueda;

  List<Pedido> _pedidos = [];
  Pedido? _selectedPedido;
  bool _isLoading = false;

  int _currentPage = 1;
  int _totalPedidos = 0;
  int _limit = 10;

  int get currentPage => _currentPage;
  int get totalPedidos => _totalPedidos;
  int get totalPages => (_totalPedidos / _limit).ceil();

  List<Pedido> get pedidos => _pedidos;
  Pedido? get selectedPedido => _selectedPedido;
  bool get isLoading => _isLoading;

  void setIsLoading(bool loading) {
    _isLoading = loading;
    notifyListeners();
  }

  Future<bool> guardarPedidoLocal({required Pedido pedido}) async {
    RepoService<Pedido> repoPedido = RepoService<Pedido>();

    int nextFolio = await repoPedido.obtenerProximoFolio();
    pedido.folio = nextFolio;

    int idPedido = await repoPedido.guardarLocal(pedido);
    if (idPedido > 0) {
      pedido.id = idPedido;
      RepoService<PedidoProducto> repoPedidoProducto =
          RepoService<PedidoProducto>();
      RepoService<PedidoProductoTopping> repoPedidoProductoTopping =
          RepoService<PedidoProductoTopping>();

      for (var producto in pedido.productos) {
        PedidoProducto pedidoProducto = PedidoProducto(
          idPedido: idPedido,
          idProducto: producto.idProducto,
          cantidad: producto.cantidad,
          costoUnitario: producto.costoUnitario,
          comentario: producto.comentario,
        );
        int idPedidoProducto =
            await repoPedidoProducto.guardarLocal(pedidoProducto);

        for (var topping in producto.toppings) {
          PedidoProductoTopping pedidoProductoTopping = PedidoProductoTopping(
            idPedidoProducto: idPedidoProducto,
            idTopping: topping.idTopping,
          );
          await repoPedidoProductoTopping.guardarLocal(pedidoProductoTopping);

          // Recuperar detalles completos del topping
          Producto? toppingInfo = await RepoService<Producto>()
              .obtenerProductoPorId(topping.idTopping!);
          if (toppingInfo != null) {
            topping.topping = toppingInfo;
          }
        }
      }
      notifyListeners();
      return true;
    } else {
      return false;
    }
  }

  Future<void> fetchLocalPedidos({int page = 1}) async {
    _isLoading = true;
    _currentPage = page;
    notifyListeners();

    RepoService<Pedido> repoPedido = RepoService<Pedido>();
    _totalPedidos = await repoPedido.contarPedidos();
    int offset = (_limit * (page - 1));
    List<Pedido> paginatedPedidos =
        await repoPedido.obtenerPedidosPaginados(_limit, offset);

    _pedidos = paginatedPedidos;
    _isLoading = false;
    notifyListeners();
  }

  void nextPage() {
    if (_currentPage < totalPages) {
      fetchLocalPedidosForScreen(page: _currentPage + 1);
    }
  }

  void previousPage() {
    if (_currentPage > 1) {
      fetchLocalPedidosForScreen(page: _currentPage - 1);
    }
  }

  Future<void> fetchLocalPedidosForScreen({int page = 1}) async {
    setIsLoading(true);
    RepoService<Pedido> repoPedido = RepoService<Pedido>();
    _currentPage = page;
    var db = await RepoService().db;

    int? count = Sqflite.firstIntValue(
        await db!.rawQuery('SELECT COUNT(*) FROM Pedido'));
    _totalPedidos = count ?? 0;

    int offset = (_limit * (page - 1));

    List<Pedido> localPedidos =
        await repoPedido.obtenerPedidosPaginados(_limit, offset);
    _pedidos = localPedidos;

    setIsLoading(false);
    notifyListeners();
  }

  Future<List<Pedido>> fetchAllLocalPedidos() async {
    setIsLoading(true);
    RepoService<Pedido> repoPedido = RepoService<Pedido>();
    List<Pedido> allPedidos = await repoPedido.obtenerTodos();
    setIsLoading(false);
    return allPedidos;
  }

  Future<List<Pedido>> fetchPedidosPorFechaSinLimit(
      DateTime startDate, DateTime endDate) async {
    setIsLoading(true);
    RepoService<Pedido> repoPedido = RepoService<Pedido>();
    List<Pedido> pedidos = await repoPedido.buscarPorFecha(startDate, endDate);
    setIsLoading(false);
    return pedidos;
  }

  Future<Pedido?> fetchPedidoConProductos(int idPedido) async {
    RepoService<Pedido> repoPedido = RepoService<Pedido>();
    Pedido? pedido = await repoPedido.obtenerPorId(idPedido);

    if (pedido != null) {
      RepoService<PedidoProducto> repoProducto = RepoService<PedidoProducto>();
      RepoService<Producto> repoProductoInfo = RepoService<Producto>();
      List<PedidoProducto> productos =
          await repoProducto.obtenerPorIdPedido(idPedido);

      for (var producto in productos) {
        Producto? prodInfo =
            await repoProductoInfo.obtenerProductoPorId(producto.idProducto!);
        if (prodInfo != null) {
          producto.producto = prodInfo;
        }

        RepoService<PedidoProductoTopping> repoTopping =
            RepoService<PedidoProductoTopping>();
        List<PedidoProductoTopping> toppings =
            await repoTopping.obtenerToppingsPorPedidoProducto(producto.id!);

        for (var topping in toppings) {
          Producto? toppingInfo =
              await repoProductoInfo.obtenerProductoPorId(topping.idTopping!);
          if (toppingInfo != null) {
            topping.topping = toppingInfo;
          }
        }

        producto.toppings = toppings;
      }

      pedido.productos = productos;
    }

    return pedido;
  }

  Future<void> buscarPedidosPorFolio(String folio) async {
    setIsLoading(true);
    RepoService<Pedido> repoPedido = RepoService<Pedido>();
    List<Pedido> localPedidos = await repoPedido.buscarPorFolio(folio);
    _pedidos = localPedidos;

    setIsLoading(false);
    notifyListeners();
  }

  Future<void> buscarPedidosPorFecha(
      DateTime startDate, DateTime endDate) async {
    setIsLoading(true);
    RepoService<Pedido> repoPedido = RepoService<Pedido>();

    List<Pedido> localPedidos =
        await repoPedido.buscarPorFecha(startDate, endDate);
    _pedidos = localPedidos;

    setIsLoading(false);
    notifyListeners();
  }

  Future<List<Pedido>> buscarPorFecha(
      DateTime startDate, DateTime endDate) async {
    setIsLoading(true);
    RepoService<Pedido> repoPedido = RepoService<Pedido>();
    List<Pedido> pedidos = await repoPedido.buscarPorFecha(startDate, endDate);
    setIsLoading(false);
    notifyListeners();
    return pedidos;
  }

  Future<void> cancelarPedido(int idPedido) async {
    var db = await RepoService().db;
    await db?.update('Pedido', {'estatus': 'CANCELADO'},
        where: 'id = ?', whereArgs: [idPedido]);
    fetchLocalPedidosForScreen();
  }
}
