using MySql.Data.MySqlClient;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Aberwyn.Models;
using System.Globalization;

namespace Aberwyn.Data
{
    public class MenuService
    {
        private readonly IConfiguration _configuration;
        private readonly IHostEnvironment _env;

        public MenuService(IConfiguration configuration, IHostEnvironment env)
        {
            _configuration = configuration;
            _env = env;
        }

        private MySqlConnection GetConnection()
        {
            var connectionString = _env.IsDevelopment()
                ? _configuration.GetConnectionString("DefaultConnection")
                : _configuration.GetConnectionString("ProductionConnection");

            return new MySqlConnection(connectionString);
        }
        public List<User> GetUsers()
        {
            var users = new List<User>();
            using (var connection = GetConnection())
            {
                connection.Open();
                string query = @"SELECT userID, Username, Name FROM Nevyn.tblUsers WHERE Chef = 1";

                using (var cmd = new MySqlCommand(query, connection))
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        users.Add(new User
                        {
                            UserID = reader.GetInt32("userID"),
                            Username = reader.GetString("Username"),
                            Name = reader.GetString("Name")
                        });
                    }
                }
            }
            return users;
        }

        public void SaveMeal(Meal meal)
        {
            if (string.IsNullOrWhiteSpace(meal?.Name))
                return;

            meal.Name = meal.Name.Trim();

            using var connection = GetConnection();
            connection.Open();

            var query = @"
        INSERT INTO Meals
        (Name, Description, RecipeUrl, CreatedAt)
        VALUES (@name, @desc, @url, CURRENT_TIMESTAMP);";

            using var cmd = new MySqlCommand(query, connection);
            cmd.Parameters.AddWithValue("@name", meal.Name);
            cmd.Parameters.AddWithValue("@desc", meal.Description ?? "");
            cmd.Parameters.AddWithValue("@url", meal.RecipeUrl ?? "");

            try
            {
                cmd.ExecuteNonQuery();
                meal.Id = (int)cmd.LastInsertedId;
            }
            catch (MySqlException ex) when (ex.Number == 1062)
            {
                Console.WriteLine($"⚠️ Måltiden '{meal.Name}' finns redan i databasen.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"❌ Fel vid sparning av måltid '{meal.Name}': {ex.Message}");
            }
        }

        public List<WeeklyMenu> GetWeeklyMenu(int weekNumber, int year)
        {
            var weeklyMenu = new List<WeeklyMenu>();
            using (var connection = GetConnection())
            {
                connection.Open();
                string query = @"
            SELECT wm.Id, wm.DayOfWeek, wm.DinnerMealId, wm.LunchMealId, wm.BreakfastMealId,
                   wm.WeekNumber, wm.Year, wm.Cook,
                   dm.Name AS DinnerMealName,
                   lm.Name AS LunchMealName,
                   bm.Name AS BreakfastMealName
            FROM WeeklyMenu wm
            LEFT JOIN Meals dm ON wm.DinnerMealId = dm.Id
            LEFT JOIN Meals lm ON wm.LunchMealId = lm.Id
            LEFT JOIN Meals bm ON wm.BreakfastMealId = bm.Id
            WHERE wm.WeekNumber = @weekNumber AND wm.Year = @year";

                using (var cmd = new MySqlCommand(query, connection))
                {
                    cmd.Parameters.AddWithValue("@weekNumber", weekNumber);
                    cmd.Parameters.AddWithValue("@year", year);

                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            weeklyMenu.Add(new WeeklyMenu
                            {
                                Id = reader.GetInt32("Id"),
                                DayOfWeek = reader.GetInt32("DayOfWeek"),
                                DinnerMealId = reader.IsDBNull(reader.GetOrdinal("DinnerMealId")) ? (int?)null : reader.GetInt32(reader.GetOrdinal("DinnerMealId")),
                                LunchMealId = reader.IsDBNull(reader.GetOrdinal("LunchMealId")) ? (int?)null : reader.GetInt32(reader.GetOrdinal("LunchMealId")),
                                BreakfastMealId = reader.IsDBNull(reader.GetOrdinal("BreakfastMealId")) ? (int?)null : reader.GetInt32(reader.GetOrdinal("BreakfastMealId")),
                                WeekNumber = reader.GetInt32("WeekNumber"),
                                Year = reader.GetInt32("Year"),
                                Cook = reader.IsDBNull(reader.GetOrdinal("Cook")) ? null : reader.GetString(reader.GetOrdinal("Cook")),
                                DinnerMealName = reader.IsDBNull(reader.GetOrdinal("DinnerMealName")) ? null : reader.GetString(reader.GetOrdinal("DinnerMealName")),
                                LunchMealName = reader.IsDBNull(reader.GetOrdinal("LunchMealName")) ? null : reader.GetString(reader.GetOrdinal("LunchMealName")),
                                BreakfastMealName = reader.IsDBNull(reader.GetOrdinal("BreakfastMealName")) ? null : reader.GetString(reader.GetOrdinal("BreakfastMealName"))
                            });
                        }
                    }
                }
            }
            return weeklyMenu;
        }


        public List<Meal> GetMeals()
        {
            var meals = new List<Meal>();
            using (var connection = GetConnection())
            {
                connection.Open();
                string query = "SELECT Id, Name FROM Meals";
                using (var cmd = new MySqlCommand(query, connection))
                {
                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            meals.Add(new Meal
                            {
                                Id = reader.GetInt32("Id"),
                                Name = reader.GetString("Name")
                            });
                        }
                    }
                }
            }
            return meals;
        }
        public List<Meal> GetMealsDetailed()
        {
            var meals = new List<Meal>();

            using (var connection = GetConnection())
            {
                connection.Open();
                string query = @"
            SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt
            FROM Meals
            ORDER BY CreatedAt DESC";

                using (var cmd = new MySqlCommand(query, connection))
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        meals.Add(new Meal
                        {
                            Id = reader.GetInt32(reader.GetOrdinal("Id")),
                            Name = reader.GetString(reader.GetOrdinal("Name")),
                            Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString(reader.GetOrdinal("Description")),
                            ProteinType = reader.IsDBNull(reader.GetOrdinal("ProteinType")) ? null : reader.GetString(reader.GetOrdinal("ProteinType")),
                            CarbType = reader.IsDBNull(reader.GetOrdinal("CarbType")) ? null : reader.GetString(reader.GetOrdinal("CarbType")),
                            RecipeUrl = reader.IsDBNull(reader.GetOrdinal("RecipeUrl")) ? null : reader.GetString(reader.GetOrdinal("RecipeUrl")),
                            CreatedAt = reader.GetDateTime(reader.GetOrdinal("CreatedAt"))
                        });
                    }
                }
            }

            return meals;
        }

        public Meal GetMealById(int id)
        {
            using var connection = GetConnection();
            connection.Open();

            string query = @"SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt, ImageUrl
                     FROM Meals WHERE Id = @id";

            using var cmd = new MySqlCommand(query, connection);
            cmd.Parameters.AddWithValue("@id", id);

            using var reader = cmd.ExecuteReader();
            if (reader.Read())
            {
                return new Meal
                {
                    Id = reader.GetInt32(reader.GetOrdinal("Id")),
                    Name = reader.GetString(reader.GetOrdinal("Name")),
                    Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString(reader.GetOrdinal("Description")),
                    ProteinType = reader.IsDBNull(reader.GetOrdinal("ProteinType")) ? null : reader.GetString(reader.GetOrdinal("ProteinType")),
                    CarbType = reader.IsDBNull(reader.GetOrdinal("CarbType")) ? null : reader.GetString(reader.GetOrdinal("CarbType")),
                    RecipeUrl = reader.IsDBNull(reader.GetOrdinal("RecipeUrl")) ? null : reader.GetString(reader.GetOrdinal("RecipeUrl")),
                    ImageUrl = reader.IsDBNull(reader.GetOrdinal("ImageUrl")) ? null : reader.GetString(reader.GetOrdinal("ImageUrl")),
                    CreatedAt = reader.GetDateTime(reader.GetOrdinal("CreatedAt"))
                };

            }

            return null;
        }

        public void DeleteMeal(int id)
        {
            using var connection = GetConnection();
            connection.Open();
            string query = "DELETE FROM Meals WHERE Id = @id";
            using var cmd = new MySqlCommand(query, connection);
            cmd.Parameters.AddWithValue("@id", id);
            cmd.ExecuteNonQuery();
        }

        public void SaveOrUpdateMeal(Meal meal)
        {
            using var conn = new MySqlConnection(_configuration.GetConnectionString("DefaultConnection"));
            conn.Open();

            using var cmd = conn.CreateCommand();
            if (meal.Id == 0)
            {
                cmd.CommandText = @"INSERT INTO Meals 
            (Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt, ImageUrl)
            VALUES (@Name, @Description, @ProteinType, @CarbType, @RecipeUrl, @CreatedAt, @ImageUrl);
            SELECT LAST_INSERT_ID();";
            }
            else
            {
                cmd.CommandText = @"UPDATE Meals 
            SET Name = @Name, Description = @Description, ProteinType = @ProteinType, 
                CarbType = @CarbType, RecipeUrl = @RecipeUrl, ImageUrl = @ImageUrl 
            WHERE Id = @Id";
                cmd.Parameters.AddWithValue("@Id", meal.Id);
            }

            cmd.Parameters.AddWithValue("@Name", meal.Name ?? "");
            cmd.Parameters.AddWithValue("@Description", meal.Description ?? "");
            cmd.Parameters.AddWithValue("@ProteinType", meal.ProteinType ?? "");
            cmd.Parameters.AddWithValue("@CarbType", meal.CarbType ?? "");
            cmd.Parameters.AddWithValue("@RecipeUrl", meal.RecipeUrl ?? "");
            cmd.Parameters.AddWithValue("@CreatedAt", meal.CreatedAt == default ? DateTime.Now : meal.CreatedAt);
            cmd.Parameters.AddWithValue("@ImageUrl", meal.ImageUrl ?? "");

            if (meal.Id == 0)
            {
                var insertedId = Convert.ToInt32(cmd.ExecuteScalar());
                meal.Id = insertedId; // ← Sätt ID direkt på objektet
            }
            else
            {
                cmd.ExecuteNonQuery();
            }
        }




        public void UpdateWeeklyMenu(MenuViewModel menuData)
        {
            if (menuData == null || menuData.WeeklyMenus == null)
                throw new ArgumentNullException(nameof(menuData), "Menu data or weekly menus cannot be null.");

            using (var connection = GetConnection())
            {
                connection.Open();
                using (var transaction = connection.BeginTransaction())
                {
                    try
                    {
                        foreach (var menu in menuData.WeeklyMenus)
                        {
                            int dayOfWeek = menu.DayOfWeek;

                            string updateQuery = @"
                        UPDATE WeeklyMenu
                        SET 
                            BreakfastMealId = @breakfastMealId,
                            LunchMealId = @lunchMealId,
                            DinnerMealId = @dinnerMealId,
                            Cook = @cook
                        WHERE DayOfWeek = @dayOfWeek 
                        AND WeekNumber = @weekNumber 
                        AND Year = @year;";

                            using (var cmd = new MySqlCommand(updateQuery, connection, transaction))
                            {
                                cmd.Parameters.AddWithValue("@dayOfWeek", dayOfWeek);
                                cmd.Parameters.AddWithValue("@breakfastMealId", menu.BreakfastMealId ?? (object)DBNull.Value);
                                cmd.Parameters.AddWithValue("@lunchMealId", menu.LunchMealId ?? (object)DBNull.Value);
                                cmd.Parameters.AddWithValue("@dinnerMealId", menu.DinnerMealId ?? (object)DBNull.Value);
                                cmd.Parameters.AddWithValue("@weekNumber", menu.WeekNumber);
                                cmd.Parameters.AddWithValue("@year", menu.Year);
                                cmd.Parameters.AddWithValue("@cook", menu.Cook ?? (object)DBNull.Value);

                                int rowsAffected = cmd.ExecuteNonQuery();

                                if (rowsAffected == 0)
                                {
                                    string insertQuery = @"
                                INSERT INTO WeeklyMenu 
                                (DayOfWeek, WeekNumber, Year, BreakfastMealId, LunchMealId, DinnerMealId, Cook)
                                VALUES (@dayOfWeek, @weekNumber, @year, @breakfastMealId, @lunchMealId, @dinnerMealId, @cook);";

                                    using var insertCmd = new MySqlCommand(insertQuery, connection, transaction);
                                    insertCmd.Parameters.AddWithValue("@dayOfWeek", dayOfWeek);
                                    insertCmd.Parameters.AddWithValue("@breakfastMealId", menu.BreakfastMealId ?? (object)DBNull.Value);
                                    insertCmd.Parameters.AddWithValue("@lunchMealId", menu.LunchMealId ?? (object)DBNull.Value);
                                    insertCmd.Parameters.AddWithValue("@dinnerMealId", menu.DinnerMealId ?? (object)DBNull.Value);
                                    insertCmd.Parameters.AddWithValue("@weekNumber", menu.WeekNumber);
                                    insertCmd.Parameters.AddWithValue("@year", menu.Year);
                                    insertCmd.Parameters.AddWithValue("@cook", menu.Cook ?? (object)DBNull.Value);
                                    insertCmd.ExecuteNonQuery();
                                }
                            }
                        }

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        Console.WriteLine($"Error updating weekly menu: {ex.Message}");
                        throw;
                    }
                }
            }
        }


        public int AddMeal(Meal meal)
        {
            using (var connection = GetConnection())
            {
                connection.Open();
                string query = @"
            INSERT INTO Meals (Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt)
            VALUES (@name, @description, @proteinType, @carbType, @recipeUrl, NOW());
            SELECT LAST_INSERT_ID();";

                using (var cmd = new MySqlCommand(query, connection))
                {
                    cmd.Parameters.AddWithValue("@name", meal.Name);
                    cmd.Parameters.AddWithValue("@description", string.IsNullOrWhiteSpace(meal.Description) ? (object)DBNull.Value : meal.Description);
                    cmd.Parameters.AddWithValue("@proteinType", string.IsNullOrWhiteSpace(meal.ProteinType) ? (object)DBNull.Value : meal.ProteinType);
                    cmd.Parameters.AddWithValue("@carbType", string.IsNullOrWhiteSpace(meal.CarbType) ? (object)DBNull.Value : meal.CarbType);
                    cmd.Parameters.AddWithValue("@recipeUrl", string.IsNullOrWhiteSpace(meal.RecipeUrl) ? (object)DBNull.Value : meal.RecipeUrl);

                    var result = cmd.ExecuteScalar();
                    return result != null ? Convert.ToInt32(result) : 0;
                }
            }
        }



        private int GetDayOfWeek(string day)
        {
            return day switch
            {
                "Monday" => 1,
                "Tuesday" => 2,
                "Wednesday" => 3,
                "Thursday" => 4,
                "Friday" => 5,
                "Saturday" => 6,
                "Sunday" => 7,
                _ => throw new System.ArgumentException("Invalid day name")
            };
        }
        public List<WeeklyMenu> GetMenuEntriesByDateRange(DateTime startDate, DateTime endDate)
        {
            var results = new List<WeeklyMenu>();

            // Hitta start- och slut-år/veckonummer
            int startWeek = ISOWeek.GetWeekOfYear(startDate);
            int startYear = startDate.Year;
            int endWeek = ISOWeek.GetWeekOfYear(endDate);
            int endYear = endDate.Year;

            // Loopar över alla veckor från start → slut
            var allMenus = new List<WeeklyMenu>();
            int w = startWeek, y = startYear;
            while (y < endYear || (y == endYear && w <= endWeek))
            {
                allMenus.AddRange(GetWeeklyMenu(w, y));

                // öka vecka, hantera årsskifte
                int weeksInYear = ISOWeek.GetWeeksInYear(y);
                if (w == weeksInYear)
                {
                    w = 1;
                    y++;
                }
                else
                {
                    w++;
                }
            }

            // Filtrera på datumintervall
            foreach (var menu in allMenus)
            {
                // Konvertera DayOfWeek (1=Mon…7=Sun) till System.DayOfWeek
                var dow = (DayOfWeek)(menu.DayOfWeek % 7);
                var date = ISOWeek.ToDateTime(menu.Year, menu.WeekNumber, dow);

                if (date.Date >= startDate.Date && date.Date <= endDate.Date)
                {
                    menu.Date = date;  // Se till att WeeklyMenu har en Date-property
                    results.Add(menu);
                }
            }

            return results;
        }


    }
}

// Models for Meals and WeeklyMenu
