using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Collections.Generic;

namespace DaireApplication.DataBase
{
    public static class DataPathManager
    {
        private static readonly string AppName = "DaireApplication";
        private static string _dataDirectory;

        // Expected CSV headers for each file
        private static readonly string UsersCsvHeader = "ID,UserName,Password,CanEdit,IsAdmin,IsActive";
        private static readonly string RecipeCsvHeader = "ID,Name,TankTemp,FountainTemp,Mixer,Fountain,MoldHeater,Vibration,VibHeater,Pedal,PedalOnTime,PedalOffTime,HeatingGoal,CoolingGoal,PouringGoal";
        private static readonly string MachineCsvHeader = "ID,TankMaxHeat,PumbMaxHeat,PumbDelay,MixerDelay,HeatingDelay,CoolingDelay,PouringDelay,PumbMinHeat,AbsMaxTemp,AbsMinTemp,PreHeatingTemp,SetTemp1,SetTemp2,SetTemp3,SetTemp4";
        private static readonly string MappingCsvHeader = "Id,Name,Address,IsRead,BitNumbers";
        private static readonly string ConfigrationCsvHeader = "Id,Max,Min,H_out,FC_out,SC_out,kp,ki,kd,kl,Name,I_Nuet,I_Mot1,I_Mot2,FC_Threshold,HeatConRange";
        private static readonly string ErrorSettingsCsvHeader = "Id,gridFreq,phaseNumber,extPower,phaseVoltage";
        private static readonly string ScreenCsvHeader = "Id,Brightness,DimSec,OffSec,Port,BoundRate,Parity,StopBits,SendingTime,WarningLimit,ErrorLimit";

        static DataPathManager()
        {
            try
            {
                // Determine the data directory based on the OS
                if (OperatingSystem.IsWindows())
                {
                    // Windows: Use LocalApplicationData
                    string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
                    _dataDirectory = Path.Combine(appDataPath, AppName);
                }
                else
                {
                    // Linux/macOS: Use ~/.local/share/DaireApplication
                    string home = Environment.GetEnvironmentVariable("HOME") ?? "/tmp";
                    _dataDirectory = Path.Combine(home, ".local", "share", AppName);
                }

                // Ensure the directory exists
                Directory.CreateDirectory(_dataDirectory);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed to CreateDirectory: {ex.Message}");
                Console.WriteLine($"_dataDirectory: {_dataDirectory}");
            }
        }

        /// <summary>
        /// Returns the full path for a data file, ensuring the directory exists.
        /// </summary>
        public static string GetDataFilePath(string fileName)
        {
            try
            {
                // Ensure the directory exists before returning the file path
                Directory.CreateDirectory(_dataDirectory);
                return Path.Combine(_dataDirectory, fileName);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed to GetDataFilePath: {ex.Message}");
                return string.Empty;
            }
        }

        /// <summary>
        /// Migrates legacy data files from the application's base directory to the new data directory.
        /// </summary>
        public static void MigrateLegacyData()
        {
            try
            {
                string[] csvFiles = { "Users.csv", "Recipe.csv", "Machine.csv", "Mapping.csv",
                                "Configration.csv", "ErrorSettings.csv", "Screen.csv" };

                foreach (string file in csvFiles)
                {
                    string legacyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file);
                    string newPath = GetDataFilePath(file);

                    // If the file exists in the old location but not in the new location, move it
                    if (File.Exists(legacyPath) && !File.Exists(newPath))
                    {
                        // Ensure the target directory exists
                        Directory.CreateDirectory(Path.GetDirectoryName(newPath) ?? _dataDirectory);
                        File.Move(legacyPath, newPath);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed to MigrateLegacyData: {ex.Message}");
            }
        }

        /// <summary>
        /// Migrates CSV files by adding missing columns with default values instead of deleting them.
        /// </summary>
        public static void MigrateCsvFiles()
        {
            MigrateCsvFile("Users.csv", UsersCsvHeader, GetUsersDefaultValues);
            MigrateCsvFile("Recipe.csv", RecipeCsvHeader, GetRecipeDefaultValues);
            MigrateCsvFile("Machine.csv", MachineCsvHeader, GetMachineDefaultValues);
            MigrateCsvFile("Mapping.csv", MappingCsvHeader, GetMappingDefaultValues);
            MigrateCsvFile("Configration.csv", ConfigrationCsvHeader, GetConfigrationDefaultValues);
            MigrateCsvFile("ErrorSettings.csv", ErrorSettingsCsvHeader, GetErrorSettingsDefaultValues);
            MigrateCsvFile("Screen.csv", ScreenCsvHeader, GetScreenDefaultValues);
        }

        /// <summary>
        /// Migrates a CSV file by adding missing columns with default values.
        /// </summary>
        private static void MigrateCsvFile(string fileName, string expectedHeader, Func<string, string> getDefaultValue)
        {
            try
            {
                string filePath = GetDataFilePath(fileName);
                if (!File.Exists(filePath))
                    return;

                string[] lines = File.ReadAllLines(filePath);
                if (lines.Length == 0)
                    return;

                string actualHeader = lines[0];
                if (string.Equals(actualHeader.Trim(), expectedHeader.Trim(), StringComparison.OrdinalIgnoreCase))
                    return; // No migration needed

                string[] expectedColumns = expectedHeader.Split(',');
                string[] actualColumns = actualHeader.Split(',');

                // Find missing columns
                var missingColumns = new List<(int index, string columnName)>();
                for (int i = 0; i < expectedColumns.Length; i++)
                {
                    if (i >= actualColumns.Length || !string.Equals(actualColumns[i].Trim(), expectedColumns[i].Trim(), StringComparison.OrdinalIgnoreCase))
                    {
                        missingColumns.Add((i, expectedColumns[i]));
                    }
                }

                if (missingColumns.Count == 0)
                    return;

                // Migrate the file
                var migratedLines = new List<string>();
                
                // Add new header
                migratedLines.Add(expectedHeader);

                // Migrate data rows
                for (int i = 1; i < lines.Length; i++)
                {
                    string[] dataColumns = lines[i].Split(',');
                    var newDataColumns = new List<string>(dataColumns);

                    // Add missing columns with default values
                    foreach (var missing in missingColumns)
                    {
                        if (missing.index >= newDataColumns.Count)
                        {
                            newDataColumns.Add(getDefaultValue(missing.columnName));
                        }
                        else
                        {
                            newDataColumns.Insert(missing.index, getDefaultValue(missing.columnName));
                        }
                    }

                    migratedLines.Add(string.Join(",", newDataColumns));
                }

                // Write the migrated file
                File.WriteAllLines(filePath, migratedLines);
                Console.WriteLine($"Migrated {fileName} - added {missingColumns.Count} missing columns");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed to migrate {fileName}: {ex.Message}");
            }
        }

        // Default value providers for each file type
        private static string GetUsersDefaultValues(string columnName)
        {
            return columnName switch
            {
                "IsActive" => "0",
                _ => ""
            };
        }

        private static string GetRecipeDefaultValues(string columnName)
        {
            return columnName switch
            {
                "TankTemp" => "0",
                "FountainTemp" => "0",
                "Mixer" => "0",
                "Fountain" => "0",
                "MoldHeater" => "0",
                "Vibration" => "0",
                "VibHeater" => "0",
                "Pedal" => "0",
                "PedalOnTime" => "0",
                "PedalOffTime" => "0",
                "HeatingGoal" => "46",
                "CoolingGoal" => "27",
                "PouringGoal" => "30",
                _ => ""
            };
        }

        private static string GetMachineDefaultValues(string columnName)
        {
            return columnName switch
            {
                "TankMaxHeat" => "50",
                "PumbMaxHeat" => "50",
                "PumbDelay" => "60",
                "MixerDelay" => "60",
                "HeatingDelay" => "60",
                "CoolingDelay" => "60",
                "PouringDelay" => "60",
                "PumbMinHeat" => "-10",
                "AbsMaxTemp" => "65",
                "AbsMinTemp" => "-14",
                "PreHeatingTemp" => "5",
                "SetTemp1" => "0",
                "SetTemp2" => "-10",
                "SetTemp3" => "5",
                "SetTemp4" => "0",
                _ => ""
            };
        }

        private static string GetMappingDefaultValues(string columnName)
        {
            return columnName switch
            {
                "BitNumbers" => "",
                _ => ""
            };
        }

        private static string GetConfigrationDefaultValues(string columnName)
        {
            return columnName switch
            {
                "Max" => "0",
                "Min" => "0",
                "H_out" => "",
                "FC_out" => "",
                "SC_out" => "",
                "kp" => "0",
                "ki" => "0",
                "kd" => "0",
                "kl" => "0",
                "Name" => "",
                "I_Nuet" => "0",
                "I_Mot1" => "0",
                "I_Mot2" => "0",
                "FC_Threshold" => "3",
                "HeatConRange" => "50",
                _ => ""
            };
        }

        private static string GetErrorSettingsDefaultValues(string columnName)
        {
            return columnName switch
            {
                "gridFreq" => "50",
                "phaseNumber" => "3",
                "extPower" => "1",
                "phaseVoltage" => "220",
                _ => ""
            };
        }

        private static string GetScreenDefaultValues(string columnName)
        {
            return columnName switch
            {
                "Brightness" => "100",
                "DimSec" => "3300",
                "OffSec" => "3600",
                "Port" => "",
                "BoundRate" => "19200",
                "Parity" => "1",
                "StopBits" => "0",
                "SendingTime" => "50",
                "WarningLimit" => "0.5",
                "ErrorLimit" => "2",
                _ => ""
            };
        }

        // Legacy delete methods (kept for backward compatibility but now call migration)
        public static void DeleteUsersCsv() => MigrateCsvFile("Users.csv", UsersCsvHeader, GetUsersDefaultValues);
        public static void DeleteRecipeCsv() => MigrateCsvFile("Recipe.csv", RecipeCsvHeader, GetRecipeDefaultValues);
        public static void DeleteMachineCsv() => MigrateCsvFile("Machine.csv", MachineCsvHeader, GetMachineDefaultValues);
        public static void DeleteMappingCsv() => MigrateCsvFile("Mapping.csv", MappingCsvHeader, GetMappingDefaultValues);
        public static void DeleteConfigrationCsv() => MigrateCsvFile("Configration.csv", ConfigrationCsvHeader, GetConfigrationDefaultValues);
        public static void DeleteErrorSettingsCsv() => MigrateCsvFile("ErrorSettings.csv", ErrorSettingsCsvHeader, GetErrorSettingsDefaultValues);
        public static void DeleteScreenCsv() => MigrateCsvFile("Screen.csv", ScreenCsvHeader, GetScreenDefaultValues);
    }
} 