using NavisworksTransport.Utils;
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Linq;

namespace NavisworksTransport.Core.AliasTree
{
    /// <summary>
    /// 别名数据存储 — CRUD 操作 + 与 PathDatabase 对接。
    /// 
    /// 不持有独立 SQLiteConnection，通过 PathDatabase.Connection 操作，
    /// 使别名表与路径/碰撞数据共享同一事务生命周期和备份机制。
    /// 
    /// 线程安全：
    /// - 构造/打开/关闭在主线程（PathDatabase 生命周期同步）
    /// - 后台线程读操作通过 Connection 上的锁保护
    /// </summary>
    public class AliasDataStore
    {
        private readonly SQLiteConnection _connection;
        private readonly object _lock = new object();

        /// <summary>
        /// 构造 AliasDataStore，使用 PathDatabase 的已有连接
        /// </summary>
        public AliasDataStore(SQLiteConnection connection)
        {
            _connection = connection ?? throw new ArgumentNullException(nameof(connection));
        }

        /// <summary>
        /// 确保 AliasMap 表存在（在 PathDatabase.CreateTables 中已自动创建，
        /// 这是提供给独立初始化场景的保障）
        /// </summary>
        public void EnsureTableExists()
        {
            lock (_lock)
            {
                using (var cmd = new SQLiteCommand(@"
                    CREATE TABLE IF NOT EXISTS AliasMap (
                        Id          INTEGER PRIMARY KEY AUTOINCREMENT,
                        NodeKey     TEXT    NOT NULL UNIQUE,
                        AliasText   TEXT    NOT NULL,
                        CreatedAt   TEXT    DEFAULT (datetime('now')),
                        ModifiedAt  TEXT    DEFAULT (datetime('now'))
                    )
                ", _connection))
                {
                    cmd.ExecuteNonQuery();
                }

                using (var cmd = new SQLiteCommand(
                    "CREATE INDEX IF NOT EXISTS idx_alias_key ON AliasMap(NodeKey)", _connection))
                {
                    cmd.ExecuteNonQuery();
                }
            }
        }

        // ── 单条操作 ──

        /// <summary>
        /// 读取别名。返回 null 表示无别名。
        /// </summary>
        public string GetAlias(AliasNodeIdentity id)
        {
            lock (_lock)
            {
                using (var cmd = new SQLiteCommand(
                    "SELECT AliasText FROM AliasMap WHERE NodeKey = @key", _connection))
                {
                    cmd.Parameters.AddWithValue("@key", id.ToKey());
                    var result = cmd.ExecuteScalar();
                    return result as string;
                }
            }
        }

        /// <summary>
        /// 写入别名（Upsert 语义 — 存在则更新，不存在则插入）
        /// </summary>
        public void SetAlias(AliasNodeIdentity id, string alias)
        {
            if (string.IsNullOrWhiteSpace(alias))
            {
                DeleteAlias(id);
                return;
            }

            string key = id.ToKey();

            lock (_lock)
            {
                // 尝试更新
                using (var cmd = new SQLiteCommand(
                    "UPDATE AliasMap SET AliasText = @alias, ModifiedAt = datetime('now') WHERE NodeKey = @key",
                    _connection))
                {
                    cmd.Parameters.AddWithValue("@key", key);
                    cmd.Parameters.AddWithValue("@alias", alias.Trim());
                    int affected = cmd.ExecuteNonQuery();

                    if (affected == 0)
                    {
                        // 不存在，插入
                        using (var insertCmd = new SQLiteCommand(
                            "INSERT INTO AliasMap (NodeKey, AliasText) VALUES (@key, @alias)",
                            _connection))
                        {
                            insertCmd.Parameters.AddWithValue("@key", key);
                            insertCmd.Parameters.AddWithValue("@alias", alias.Trim());
                            insertCmd.ExecuteNonQuery();
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 删除别名
        /// </summary>
        public void DeleteAlias(AliasNodeIdentity id)
        {
            lock (_lock)
            {
                using (var cmd = new SQLiteCommand(
                    "DELETE FROM AliasMap WHERE NodeKey = @key", _connection))
                {
                    cmd.Parameters.AddWithValue("@key", id.ToKey());
                    cmd.ExecuteNonQuery();
                }
            }
        }

        // ── 批量操作 ──

        /// <summary>
        /// 删除指定路径前缀下的所有别名（用于"清除某分支下全部别名"）
        /// </summary>
        public void DeleteAliasesByPathPrefix(string pathPrefix)
        {
            if (string.IsNullOrEmpty(pathPrefix)) return;

            // 使用 LIKE 'prefix%' 匹配所有以该前缀开头的路径
            string escapedPrefix = pathPrefix.Replace("'", "''").Replace("%", "\\%").Replace("_", "\\_");
            string likePattern = escapedPrefix + "%";

            lock (_lock)
            {
                using (var cmd = new SQLiteCommand(
                    "DELETE FROM AliasMap WHERE NodeKey LIKE @pattern ESCAPE '\\'",
                    _connection))
                {
                    cmd.Parameters.AddWithValue("@pattern", likePattern);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        /// <summary>
        /// 全量加载所有别名到内存字典。key=NodeKey, value=AliasText
        /// </summary>
        public Dictionary<string, string> LoadAll()
        {
            var result = new Dictionary<string, string>();

            lock (_lock)
            {
                using (var cmd = new SQLiteCommand(
                    "SELECT NodeKey, AliasText FROM AliasMap", _connection))
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        string key = reader.GetString(0);
                        string alias = reader.GetString(1);
                        result[key] = alias;
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 当前别名总数
        /// </summary>
        public int Count
        {
            get
            {
                lock (_lock)
                {
                    using (var cmd = new SQLiteCommand(
                        "SELECT COUNT(*) FROM AliasMap", _connection))
                    {
                        return Convert.ToInt32(cmd.ExecuteScalar());
                    }
                }
            }
        }

        /// <summary>
        /// 批量导入（合并模式：覆盖已有 key，新增不存在的 key）
        /// </summary>
        public void ImportBatch(Dictionary<string, string> entries)
        {
            if (entries == null || entries.Count == 0) return;

            lock (_lock)
            {
                using (var tx = _connection.BeginTransaction())
                {
                    try
                    {
                        using (var upsertCmd = new SQLiteCommand(
                            @"INSERT INTO AliasMap (NodeKey, AliasText) VALUES (@key, @alias)
                              ON CONFLICT(NodeKey) DO UPDATE SET
                                  AliasText = excluded.AliasText,
                                  ModifiedAt = datetime('now')",
                            _connection))
                        {
                            var keyParam = upsertCmd.Parameters.Add("@key", System.Data.DbType.String);
                            var aliasParam = upsertCmd.Parameters.Add("@alias", System.Data.DbType.String);

                            foreach (var kvp in entries)
                            {
                                keyParam.Value = kvp.Key;
                                aliasParam.Value = kvp.Value;
                                upsertCmd.ExecuteNonQuery();
                            }
                        }

                        tx.Commit();
                    }
                    catch
                    {
                        tx.Rollback();
                        throw;
                    }
                }
            }
        }

        /// <summary>
        /// 清除所有别名（危险操作）
        /// </summary>
        public void ClearAll()
        {
            lock (_lock)
            {
                using (var cmd = new SQLiteCommand("DELETE FROM AliasMap", _connection))
                {
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
}
