using SQLite;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using MauiAppStock.Models;

namespace MauiAppStock.Data
{
    public class Database
    {
        private static SingletonConnection db;

        public static async Task InitializeAsync()
        {
            if (db == null)
            {
                string dbPath = Path.Combine(FileSystem.AppDataDirectory, "MauiAppStock.db3");
                db = SingletonConnection.GetInstance(dbPath);
                // Création des tables si elles n'existent pas
                await db.CreateTableAsync<Appareil>();
                await db.CreateTableAsync<Piece>();
                await db.CreateTableAsync<AppareilPiece>(); // Table de liaison
                await db.CreateTableAsync<Fournisseur>();
            }
        }

        // CRUD pour Appareil
        public static Task<int> AddAppareilAsync(Appareil appareil)
        {
            return db.InsertAsync(appareil);
        }

        public static Task<List<Appareil>> GetAppareilsAsync()
        {
            return db.Table<Appareil>().ToListAsync();
        }

        public static Task<int> UpdateAppareilAsync(Appareil appareil)
        {
            return db.UpdateAsync(appareil);
        }

        public static Task<int> DeleteAppareilAsync(Appareil appareil)
        {
            return db.DeleteAsync(appareil);
        }

        // CRUD pour Piece
        public static Task<int> AddPieceAsync(Piece piece)
        {
            return db.InsertAsync(piece);
        }

        public static Task<List<Piece>> GetPiecesAsync()
        {
            return db.Table<Piece>().ToListAsync();
        }

        public static Task<int> UpdatePieceAsync(Piece piece)
        {
            return db.UpdateAsync(piece);
        }

        public static Task<int> DeletePieceAsync(Piece piece)
        {
            return db.DeleteAsync(piece);
        }

        
        // CRUD pour Fournisseur
        public static Task<int> AddFournisseurAsync(Fournisseur fournisseur)
        {
            return db.InsertAsync(fournisseur);
        }

        public static Task<List<Fournisseur>> GetFournisseursAsync()
        {
            return db.Table<Fournisseur>().ToListAsync();
        }

        public static Task<int> UpdateFournisseursync(Fournisseur fournisseur)
        {
            return db.UpdateAsync(fournisseur);
        }

        public static Task<int> DeleteFournisseurAsync(Fournisseur fournisseur)
        {
            return db.DeleteAsync(fournisseur);
        }
        
        
        // Liaison entre Appareil et Piece
        public static Task<int> AddAppareilPieceAsync(AppareilPiece appareilPiece)
        {
            return db.InsertAsync(appareilPiece);
        }
        
        // CRUD pour MouvementStock
        public static Task<int> AddMouvementStockAsync(MouvementStock mouvement)
        {
            return db.InsertAsync(mouvement);
        }

        public static Task<List<MouvementStock>> GetMouvementsStockAsync()
        {
            return db.Table<MouvementStock>().OrderByDescending(m => m.DateMouvement).ToListAsync();
        }

        public static async Task<List<MouvementStock>> GetMouvementsStockForPieceAsync(int pieceId)
        {
            return await db.Table<MouvementStock>()
                .Where(m => m.PieceId == pieceId)
                .OrderByDescending(m => m.DateMouvement)
                .ToListAsync();
        }

        public static Task<int> UpdateMouvementStockAsync(MouvementStock mouvement)
        {
            return db.UpdateAsync(mouvement);
        }

        public static Task<int> DeleteMouvementStockAsync(MouvementStock mouvement)
        {
            return db.DeleteAsync(mouvement);
        }
        
        // Met à jour une association existante
        public static Task<int> UpdateAppareilPieceAsync(AppareilPiece appareilPiece)
        {
            return db.UpdateAsync(appareilPiece);
        }

        // Supprime une association existante
        public static Task<int> DeleteAppareilPieceAsync(AppareilPiece appareilPiece)
        {
            return db.DeleteAsync(appareilPiece);
        }

        // Récupérer toutes les pièces associées à un appareil
        public static async Task<List<Piece>> GetPiecesForAppareilAsync(int appareilId)
        {
            var associations = await db.Table<AppareilPiece>().Where(ap => ap.AppareilId == appareilId).ToListAsync();
            var pieces = new List<Piece>();
            foreach (var assoc in associations)
            {
                var piece = await db.Table<Piece>().Where(p => p.Id == assoc.PieceId).FirstOrDefaultAsync();
                if (piece != null)
                {
                    // Assigner le flag de recommandation provenant de la table de liaison
                    piece.EstRecommandee = assoc.EstRecommandee;
                    pieces.Add(piece);
                }
            }
            // Trier pour que les pièces recommandées apparaissent en premier
            return pieces.OrderByDescending(p => p.EstRecommandee).ToList();
        }

        // Récupérer uniquement les pièces recommandées pour un appareil
        public static async Task<List<Piece>> GetPiecesRecommandeesForAppareilAsync(int appareilId)
        {
            var associations = await db.Table<AppareilPiece>()
                .Where(ap => ap.AppareilId == appareilId && ap.EstRecommandee)
                .ToListAsync();
            var pieces = new List<Piece>();
            foreach (var assoc in associations)
            {
                var piece = await db.Table<Piece>().Where(p => p.Id == assoc.PieceId).FirstOrDefaultAsync();
                if (piece != null)
                    pieces.Add(piece);
            }
            return pieces;
        }
        
        public static async Task<List<AppareilPiece>> GetAppareilPiecesForAppareilAsync(int appareilId)
        {
            var associations = await db.Table<AppareilPiece>().Where(ap => ap.AppareilId == appareilId).ToListAsync();
            foreach (var assoc in associations)
            {
                var piece = await db.Table<Piece>().Where(p => p.Id == assoc.PieceId).FirstOrDefaultAsync();
                if (piece != null)
                {
                    assoc.NomPiece = piece.Nom;
                    assoc.DescriptionPiece = piece.Description;
                }
            }
            return associations.OrderByDescending(a => a.EstRecommandee).ToList();
        }
        
        public static async Task<AppareilPiece> GetAppareilPieceAsync(int appareilId, int pieceId)
        {
            return await db.Table<AppareilPiece>()
                .Where(ap => ap.AppareilId == appareilId && ap.PieceId == pieceId)
                .FirstOrDefaultAsync();
        }
    }
}
