using MainShell.Common;
using MainShell.Filewritable;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace MainShell.Process
{
    public class WaferHandlingFlowNodeRule
    {
        public string Key { get; set; }
        public string DisplayName { get; set; }
        public List<string> ActivityKeywords { get; set; } = new List<string>();
        public List<string> WorkflowKeywords { get; set; } = new List<string>();
        public List<string> ParentKeywords { get; set; } = new List<string>();
    }

    public class WaferHandlingFlowConfig
    {
        public List<WaferHandlingFlowNodeRule> Nodes { get; } = new List<WaferHandlingFlowNodeRule>();

        public static string DefaultConfigPath => Path.Combine(Paths.BasePath, "Configuration", "WaferHandlingFlow.json");

        public static WaferHandlingFlowConfig LoadOrCreate(string filePath = null)
        {
            var path = string.IsNullOrWhiteSpace(filePath) ? DefaultConfigPath : filePath;
            var dir = Path.GetDirectoryName(path);
            if (!string.IsNullOrWhiteSpace(dir))
            {
                Directory.CreateDirectory(dir);
            }

            if (!File.Exists(path))
            {
                var def = CreateDefault();
                def.Save(path);
                return def;
            }

            try
            {
                var loaded = Load(path);
                if (loaded == null || loaded.Nodes.Count == 0)
                {
                    throw new InvalidDataException("WaferHandlingFlow config is empty.");
                }
                loaded.Normalize();
                return loaded;
            }
            catch
            {
                var def = CreateDefault();
                def.Save(path);
                return def;
            }
        }

        public static WaferHandlingFlowConfig Load(string filePath)
        {
            var json = File.ReadAllText(filePath);
            var data = JsonConvert.DeserializeObject<WaferHandlingFlowFile>(json);

            var cfg = new WaferHandlingFlowConfig();
            if (data?.Nodes != null)
            {
                cfg.Nodes.AddRange(data.Nodes);
            }

            cfg.Normalize();
            return cfg;
        }

        public void Save(string filePath = null)
        {
            var path = string.IsNullOrWhiteSpace(filePath) ? DefaultConfigPath : filePath;
            Normalize();

            var data = new WaferHandlingFlowFile
            {
                Nodes = Nodes.ToList()
            };

            var json = JsonConvert.SerializeObject(data, Formatting.Indented);
            File.WriteAllText(path, json);
        }

        public string ResolveNodeKey(string workflowName, string parentActivityName, string activityName)
        {
            var activity = activityName ?? string.Empty;
            var workflow = workflowName ?? string.Empty;
            var parent = parentActivityName ?? string.Empty;

            var rule = Nodes.FirstOrDefault(n => IsMatch(n, activity, workflow, parent));
            return rule?.Key;
        }

        private static bool IsMatch(WaferHandlingFlowNodeRule node, string activity, string workflow, string parent)
        {
            if (node == null) return false;

            return ContainsAny(activity, node.ActivityKeywords) ||
                   ContainsAny(workflow, node.WorkflowKeywords) ||
                   ContainsAny(parent, node.ParentKeywords);
        }

        private static bool ContainsAny(string source, List<string> keywords)
        {
            if (keywords == null || keywords.Count == 0) return false;

            foreach (var keyword in keywords)
            {
                if (string.IsNullOrWhiteSpace(keyword)) continue;
                if ((source ?? string.Empty).IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    return true;
                }
            }

            return false;
        }

        private void Normalize()
        {
            Nodes.RemoveAll(n => n == null || string.IsNullOrWhiteSpace(n.Key));

            foreach (var node in Nodes)
            {
                if (string.IsNullOrWhiteSpace(node.DisplayName))
                {
                    node.DisplayName = node.Key;
                }

                node.ActivityKeywords = node.ActivityKeywords ?? new List<string>();
                node.WorkflowKeywords = node.WorkflowKeywords ?? new List<string>();
                node.ParentKeywords = node.ParentKeywords ?? new List<string>();
            }
        }

        public static WaferHandlingFlowConfig CreateDefault()
        {
            var cfg = new WaferHandlingFlowConfig();

            cfg.Nodes.Add(new WaferHandlingFlowNodeRule
            {
                Key = "WaferLoad",
                DisplayName = "晶圆上料",
                ActivityKeywords = new List<string> { "ChipLoad", ProcessFlowName.ChipLoadExecuteActivity }
            });

            cfg.Nodes.Add(new WaferHandlingFlowNodeRule
            {
                Key = "WaferSupply",
                DisplayName = "晶片准备",
                WorkflowKeywords = new List<string>
                {
                    ProcessFlowName.ChipStraighteningFlow,
                    ProcessFlowName.DiePositionFlow,
                    ProcessFlowName.DieTransferFlow,
                    ProcessFlowName.DieRecheckFlow
                },
                ParentKeywords = new List<string> { "DieAlign", "DieBond", "Inspect" }
            });

            cfg.Nodes.Add(new WaferHandlingFlowNodeRule
            {
                Key = "WaferUnload",
                DisplayName = "晶圆下料",
                ActivityKeywords = new List<string> { "ChipUnload", ProcessFlowName.ChipUnloadExecuteActivity }
            });

            return cfg;
        }

        public class WaferHandlingFlowFile
        {
            public List<WaferHandlingFlowNodeRule> Nodes { get; set; } = new List<WaferHandlingFlowNodeRule>();
        }
    }
}
