using System;
using System.Collections.Generic;
using System.Linq;
using StandardScene.Signal.Model;

namespace StandardScene.Signal.Plc
{
    /// <summary>
    /// 加载机构 + 工位。没有工位表时，用旧机构行的 ReadDb/WriteDb/地标合成 default 工位（一字节枚举）。
    /// </summary>
    internal static class PlcConfigLoader
    {
        public const string DefaultDockId = "default";

        public sealed class StationBundle
        {
            public PlcStationModel Station { get; init; }
            public List<PlcStationDockModel> Docks { get; init; }
        }

        public static List<StationBundle> Load(string stationsPath, string docksPath)
        {
            var stations = SignalConfigStore.Load<PlcStationModel>(stationsPath)
                .Where(s => s != null && !string.IsNullOrWhiteSpace(s.JgName))
                .ToList();
            var docks = SignalConfigStore.Load<PlcStationDockModel>(docksPath)
                .Where(d => d != null && !string.IsNullOrWhiteSpace(d.JgName))
                .ToList();

            var byName = docks
                .GroupBy(d => d.JgName.Trim(), StringComparer.OrdinalIgnoreCase)
                .ToDictionary(g => g.Key, g => g.ToList(), StringComparer.OrdinalIgnoreCase);

            var list = new List<StationBundle>();
            foreach (var station in stations)
            {
                if (!byName.TryGetValue(station.JgName.Trim(), out var rows) || rows.Count == 0)
                    rows = HasLegacyIo(station) ? new List<PlcStationDockModel> { Synthesize(station) } : new List<PlcStationDockModel>();
                list.Add(new StationBundle { Station = station, Docks = rows });
            }

            return list;
        }

        public static int ResolveDb(PlcStationModel station)
        {
            if (station == null)
                return 100;
            if (station.DbNumber > 0)
                return station.DbNumber;
            if (PlcAddress.TryParse(station.HeartDb, out var db, out _, out _))
                return db;
            if (PlcAddress.TryParse(station.ReadDb, out db, out _, out _))
                return db;
            if (PlcAddress.TryParse(station.WriteDb, out db, out _, out _))
                return db;
            return 100;
        }

        public static string ResolveHeartAddress(PlcStationModel station)
        {
            if (station == null)
                return "";
            if (!string.IsNullOrWhiteSpace(station.HeartDb))
                return station.HeartDb.Trim();
            return PlcAddress.Bit(ResolveDb(station), station.HeartByte, station.HeartBit);
        }

        private static bool HasLegacyIo(PlcStationModel station) =>
            station != null &&
            (!string.IsNullOrWhiteSpace(station.ReadDb) ||
             !string.IsNullOrWhiteSpace(station.WriteDb) ||
             station.JgPointId > 0 ||
             !string.IsNullOrWhiteSpace(station.JgContains));

        private static PlcStationDockModel Synthesize(PlcStationModel station) => new PlcStationDockModel
        {
            JgName = station.JgName,
            DockId = DefaultDockId,
            UseByteIo = true,
            ReadDb = station.ReadDb,
            WriteDb = station.WriteDb,
            JgInPointId = station.JgInPointId,
            JgInContains = station.JgInContains,
            JgPointId = station.JgPointId,
            JgContains = station.JgContains
        };
    }
}
