using System;
using System.Reflection;
using System.Text;
using Xunit;
using CncModels.Constants;

namespace CncModels.Tests
{
    /// <summary>
    /// 常量类测试：TableName、SensitiveConfigKey、ErrorCode 的常量值应符合命名约定与格式要求。
    /// </summary>
    public class ConstantsTests
    {
        /// <summary>
        /// 验证 TableName 的 20 个表名常量值与数据库实际表名一致
        /// 覆盖场景：全部20张表的精确值校验
        /// </summary>
        [Fact]
        public void TableName_AllConstants_MatchDatabaseTableNames()
        {
            // 业务库 17 张表
            Assert.Equal("cnc_workshop", TableName.Workshop);
            Assert.Equal("cnc_brand", TableName.Brand);
            Assert.Equal("cnc_brand_field_mapping", TableName.BrandFieldMapping);
            Assert.Equal("cnc_collect_address", TableName.CollectAddress);
            Assert.Equal("cnc_machine", TableName.Machine);
            Assert.Equal("cnc_worker", TableName.Worker);
            Assert.Equal("cnc_worker_machine", TableName.WorkerMachine);
            Assert.Equal("cnc_collect_record", TableName.CollectRecord);
            Assert.Equal("cnc_production_segment", TableName.ProductionSegment);
            Assert.Equal("cnc_machine_daily_status", TableName.MachineDailyStatus);
            Assert.Equal("cnc_daily_production", TableName.DailyProduction);
            Assert.Equal("cnc_worker_daily_summary", TableName.WorkerDailySummary);
            Assert.Equal("cnc_production_adjustment", TableName.ProductionAdjustment);
            Assert.Equal("cnc_alert", TableName.Alert);
            Assert.Equal("cnc_sys_config", TableName.SysConfig);
            Assert.Equal("cnc_screen_config", TableName.ScreenConfig);
            Assert.Equal("cnc_screen_filter", TableName.ScreenFilter);
            // 日志库 3 张表
            Assert.Equal("log_collect_raw", TableName.LogCollectRaw);
            Assert.Equal("log_system", TableName.LogSystem);
            Assert.Equal("log_collector_heartbeat", TableName.LogCollectorHeartbeat);
        }

        /// <summary>
        /// AAA：验证 SensitiveConfigKey 的 3 个敏感键常量值应为 snake_case 风格。
        /// </summary>
        [Fact]
        public void SensitiveConfigKey_Constants_ShouldFollowSnakeCase()
        {
            Type t = typeof(SensitiveConfigKey);
            var fields = t.GetFields(BindingFlags.Public | BindingFlags.Static);
            Assert.Equal(3, fields.Length);
            foreach (var f in fields)
            {
                if (f.FieldType != typeof(string)) continue;
                string value = (string)f.GetValue(null);
                string expected = ToSnakeCase(f.Name);
                Assert.Equal(expected, value);
            }
        }

        /// <summary>
        /// AAA：验证 ErrorCode 的 6 个错误码常量值应为纯数字字符串。
        /// </summary>
        [Fact]
        public void ErrorCode_Constants_ShouldBeNumericStrings()
        {
            Type t = typeof(ErrorCode);
            var fields = t.GetFields(BindingFlags.Public | BindingFlags.Static);
            // 至少应有 6 个错误码常量，若有更多也应遵循数字字符串规则
            Assert.True(fields.Length >= 6, "ErrorCode 至少应包含 6 个常量");
            foreach (var f in fields)
            {
                if (f.FieldType != typeof(string)) continue;
                string value = (string)f.GetValue(null);
                Assert.Matches("^[0-9]+$", value);
            }
        }

        private string ToSnakeCase(string input)
        {
            if (string.IsNullOrEmpty(input)) return input;
            var sb = new StringBuilder();
            for (int i = 0; i < input.Length; i++)
            {
                char c = input[i];
                if (char.IsUpper(c))
                {
                    if (i > 0) sb.Append('_');
                    sb.Append(char.ToLowerInvariant(c));
                }
                else
                {
                    sb.Append(c);
                }
            }
            return sb.ToString();
        }
    }
}
