using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
using System.Collections.Generic;

namespace HMIWeb
{
    // Important: Allows JavaScript to see this class
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(true)]
    public class MachineBridge
    {
        // Reference to the main form to update logic
        private MainForm _host;

        // Data folder paths
        private readonly string _dataFolder;
        private readonly string _settingsPath;
        private readonly string _recipeFolder;

        public MachineBridge(MainForm host)
        {
            _host = host;

            // Initialize data folder paths
            _dataFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data");
            _settingsPath = Path.Combine(_dataFolder, "settings.json");
            _recipeFolder = Path.Combine(_dataFolder, "recipe");

            // Ensure folders exist
            EnsureDataFoldersExist();
        }

        private void EnsureDataFoldersExist()
        {
            try
            {
                if (!Directory.Exists(_dataFolder))
                    Directory.CreateDirectory(_dataFolder);

                if (!Directory.Exists(_recipeFolder))
                    Directory.CreateDirectory(_recipeFolder);

                // Initialize default settings if not exists
                if (!File.Exists(_settingsPath))
                    InitializeDefaultSettings();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to create data folders: {ex.Message}");
            }
        }

        private void InitializeDefaultSettings()
        {
            var defaultSettings = new List<object>
            {
                new { Key = "Site Name", Value = "Smart Factory A-1", Group = "System Information", Type = "String", Description = "The display name of the factory site." },
                new { Key = "Line ID", Value = "L-2024-001", Group = "System Information", Type = "String", Description = "Unique identifier for this production line." },
                new { Key = "API Endpoint", Value = "https://api.factory.local/v1", Group = "Network Configuration", Type = "String", Description = "Base URL for the backend API." },
                new { Key = "Support Contact", Value = "010-1234-5678", Group = "System Information", Type = "String", Description = "Emergency contact number for maintenance." },
                new { Key = "Debug Mode", Value = "false", Group = "System Information", Type = "Boolean", Description = "Enable detailed logging for debugging." },
                new { Key = "Max Speed", Value = "1500", Group = "Motion Control", Type = "Number", Description = "Maximum velocity in mm/s." },
                new { Key = "Acceleration", Value = "500", Group = "Motion Control", Type = "Number", Description = "Acceleration ramp in mm/s²." }
            };

            for (int i = 1; i <= 5; i++)
            {
                defaultSettings.Add(new
                {
                    Key = $"Sensor_{i}_Threshold",
                    Value = (i * 10).ToString(),
                    Group = "Sensor Calibration",
                    Type = "Number",
                    Description = $"Trigger threshold for Sensor {i}."
                });
            }

            for (int i = 1; i <= 3; i++)
            {
                defaultSettings.Add(new
                {
                    Key = $"Safety_Zone_{i}",
                    Value = "true",
                    Group = "Safety Settings",
                    Type = "Boolean",
                    Description = $"Enable monitoring for Safety Zone {i}."
                });
            }

            File.WriteAllText(_settingsPath, JsonConvert.SerializeObject(defaultSettings, Formatting.Indented));
            Console.WriteLine("[INFO] Default settings.json created");
        }

        // --- Methods called from React (App.tsx) ---

        public void MoveAxis(string axis, double value)
        {
            // In real app, call DLL here: Motion.Move(axis, value)
            Console.WriteLine($"[C#] Moving {axis} to {value}");

            // For simulation, update host state directly
            _host.SetTargetPosition(axis, value);
        }

        public void SetIO(int id, bool isInput, bool state)
        {
            Console.WriteLine($"[C#] Set IO {id} to {state}");
            _host.SetOutput(id, state);
        }

        public void SystemControl(string command)
        {
            Console.WriteLine($"[C#] CMD: {command}");
            _host.HandleCommand(command);
        }

        public string SelectRecipe(string recipeId)
        {
            Console.WriteLine($"[C#] Selecting Recipe: {recipeId}");

            try
            {
                string recipePath = Path.Combine(_recipeFolder, $"{recipeId}.json");

                if (!File.Exists(recipePath))
                {
                    var response = new { success = false, message = "Recipe not found" };
                    return JsonConvert.SerializeObject(response);
                }

                // Load recipe data from file
                string json = File.ReadAllText(recipePath);
                var recipeData = JsonConvert.DeserializeObject<dynamic>(json);

                // Set as current recipe
                _host.SetCurrentRecipe(recipeId);

                Console.WriteLine($"[INFO] Recipe {recipeId} selected successfully");

                var response2 = new { success = true, message = "Recipe selected successfully", recipeId = recipeId, recipe = recipeData };
                return JsonConvert.SerializeObject(response2);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to select recipe: {ex.Message}");
                var response = new { success = false, message = ex.Message };
                return JsonConvert.SerializeObject(response);
            }
        }

        public string GetConfig()
        {
            try
            {
                if (!File.Exists(_settingsPath))
                {
                    InitializeDefaultSettings();
                }

                string json = File.ReadAllText(_settingsPath);
                Console.WriteLine($"[INFO] Loaded settings from {_settingsPath}");
                return json;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to load settings: {ex.Message}");
                return "[]";
            }
        }

        public void SaveConfig(string configJson)
        {
            try
            {
                Console.WriteLine($"[Backend] SAVE CONFIG REQUEST RECEIVED");

                // Validate JSON format
                var settings = JsonConvert.DeserializeObject(configJson);

                // Save to file with formatting
                File.WriteAllText(_settingsPath, JsonConvert.SerializeObject(settings, Formatting.Indented));

                Console.WriteLine($"[INFO] Settings saved successfully to {_settingsPath}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to save settings: {ex.Message}");
            }
        }
        public string GetIOList()
        {
            var ioList = new System.Collections.Generic.List<object>();

            Console.WriteLine("GetIOList");
            // Outputs (0-31)
            for (int i = 0; i < 32; i++)
            {
                string name = $"DOUT_{i:D2}";
                if (i == 0) name = "Tower Lamp Red";
                if (i == 1) name = "Tower Lamp Yel";
                if (i == 2) name = "Tower Lamp Grn";
                
                ioList.Add(new { id = i, name = name, type = "output", state = false });
            }

            // Inputs (0-31)
            for (int i = 0; i < 32; i++)
            {
                string name = $"DIN_{i:D2}";
                bool initialState = false;
                if (i == 0) name = "Front Door Sensor";
                if (i == 1) name = "Right Door Sensor";
                if (i == 2) name = "Left Door Sensor";
                if (i == 3) name = "Back Door Sensor";
                if (i == 4) { name = "Main Air Pressure"; initialState = true; }
                if (i == 5) { name = "Vacuum Generator"; initialState = true; }
                if (i == 6) { name = "Emergency Stop Loop"; initialState = true; }

                ioList.Add(new { id = i, name = name, type = "input", state = initialState });
            }

            return Newtonsoft.Json.JsonConvert.SerializeObject(ioList);
        }
        public string GetRecipeList()
        {
            try
            {
                var recipes = new List<object>();

                if (!Directory.Exists(_recipeFolder))
                {
                    Directory.CreateDirectory(_recipeFolder);
                    return JsonConvert.SerializeObject(recipes);
                }

                var jsonFiles = Directory.GetFiles(_recipeFolder, "*.json");

                foreach (var filePath in jsonFiles)
                {
                    try
                    {
                        string fileName = Path.GetFileNameWithoutExtension(filePath);
                        string json = File.ReadAllText(filePath);
                        var recipeData = JsonConvert.DeserializeObject<dynamic>(json);

                        var lastModified = File.GetLastWriteTime(filePath).ToString("yyyy-MM-dd");

                        recipes.Add(new
                        {
                            id = fileName,
                            name = recipeData?.name ?? fileName,
                            lastModified = lastModified
                        });
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"[ERROR] Failed to read recipe {filePath}: {ex.Message}");
                    }
                }

                Console.WriteLine($"[INFO] Loaded {recipes.Count} recipes from {_recipeFolder}");
                return JsonConvert.SerializeObject(recipes);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to get recipe list: {ex.Message}");
                return "[]";
            }
        }

        public string GetRecipe(string recipeId)
        {
            try
            {
                string recipePath = Path.Combine(_recipeFolder, $"{recipeId}.json");

                if (!File.Exists(recipePath))
                {
                    var response = new { success = false, message = "Recipe not found" };
                    return JsonConvert.SerializeObject(response);
                }

                string json = File.ReadAllText(recipePath);
                Console.WriteLine($"[INFO] Loaded recipe {recipeId}");
                return json;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to get recipe {recipeId}: {ex.Message}");
                var response = new { success = false, message = ex.Message };
                return JsonConvert.SerializeObject(response);
            }
        }

        public string SaveRecipe(string recipeId, string recipeData)
        {
            try
            {
                string recipePath = Path.Combine(_recipeFolder, $"{recipeId}.json");

                // Validate JSON format
                var recipe = JsonConvert.DeserializeObject(recipeData);

                // Save to file with formatting
                File.WriteAllText(recipePath, JsonConvert.SerializeObject(recipe, Formatting.Indented));

                Console.WriteLine($"[INFO] Recipe {recipeId} saved successfully to {recipePath}");

                var response = new { success = true, message = "Recipe saved successfully", recipeId = recipeId };
                return JsonConvert.SerializeObject(response);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to save recipe {recipeId}: {ex.Message}");
                var response = new { success = false, message = ex.Message };
                return JsonConvert.SerializeObject(response);
            }
        }

        public string CopyRecipe(string recipeId, string newName)
        {
            Console.WriteLine($"[C#] Copying Recipe: {recipeId} as {newName}");

            try
            {
                string sourcePath = Path.Combine(_recipeFolder, $"{recipeId}.json");

                if (!File.Exists(sourcePath))
                {
                    var response = new { success = false, message = "Source recipe not found" };
                    return JsonConvert.SerializeObject(response);
                }

                // Generate new ID
                string newId = Guid.NewGuid().ToString().Substring(0, 8);
                string destPath = Path.Combine(_recipeFolder, $"{newId}.json");

                // Read source recipe
                string json = File.ReadAllText(sourcePath);
                var recipeData = JsonConvert.DeserializeObject<dynamic>(json);

                // Update name in recipe data
                recipeData.name = newName;

                // Save to new file
                File.WriteAllText(destPath, JsonConvert.SerializeObject(recipeData, Formatting.Indented));

                string timestamp = DateTime.Now.ToString("yyyy-MM-dd");

                Console.WriteLine($"[INFO] Recipe copied from {recipeId} to {newId}");

                var response2 = new {
                    success = true,
                    message = "Recipe copied successfully",
                    newRecipe = new {
                        id = newId,
                        name = newName,
                        lastModified = timestamp
                    }
                };
                return JsonConvert.SerializeObject(response2);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to copy recipe: {ex.Message}");
                var response = new { success = false, message = ex.Message };
                return JsonConvert.SerializeObject(response);
            }
        }

        public string DeleteRecipe(string recipeId)
        {
            Console.WriteLine($"[C#] Deleting Recipe: {recipeId}");

            try
            {
                // Check if recipe is in use
                if (recipeId == _host.GetCurrentRecipe())
                {
                    var response1 = new { success = false, message = "Cannot delete currently selected recipe" };
                    return JsonConvert.SerializeObject(response1);
                }

                string recipePath = Path.Combine(_recipeFolder, $"{recipeId}.json");

                if (!File.Exists(recipePath))
                {
                    var response = new { success = false, message = "Recipe not found" };
                    return JsonConvert.SerializeObject(response);
                }

                // Delete the file
                File.Delete(recipePath);

                Console.WriteLine($"[INFO] Recipe {recipeId} deleted successfully");

                var response2 = new { success = true, message = "Recipe deleted successfully", recipeId = recipeId };
                return JsonConvert.SerializeObject(response2);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Failed to delete recipe: {ex.Message}");
                var response = new { success = false, message = ex.Message };
                return JsonConvert.SerializeObject(response);
            }
        }
    }
}
