using Falcon.SugarApi.Cache;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Diagnostics;

namespace Falcon.SugarApi.Test
{
    [TestClass]
    public class CacheTest
    {
        [TestMethod]
        public void MemoryTest() {
            var services = new ServiceCollection() as IServiceCollection;
            services.AddSugarMemoryCache(op => {

            });
            var sp = services.BuildServiceProvider().CreateScope().ServiceProvider;
            var sc = sp.GetService<ISugarCache>();
            var sca = sp.GetService<ISugarCacheAsync>();
            RunCache(sc, sca);
        }

        [TestMethod]
        public void RedisTest() {
            var sw = new Stopwatch();
            var services = new ServiceCollection() as IServiceCollection;
            services.AddSugarRedisCache(op => {
                op.Configuration = "127.0.0.1:7001,password=123654";
                op.InstanceName = "CacheTest:RedisTest";
            });
            var sp = services.BuildServiceProvider().CreateScope().ServiceProvider;
            var sc = sp.GetService<ISugarCache>();
            var sca = sp.GetService<ISugarCacheAsync>();
            RunCache(sc, sca);
        }

        private static void RunCache(ISugarCache? sc, ISugarCacheAsync? sca) {
            var sw = new Stopwatch();
            var ts = new TimeSpan(0, 1, 0);
            var strResult = "";
            int runTimes = 10000;
            var key = Guid.NewGuid().ToString();
            var strValue = Guid.NewGuid().ToString();
            //字符串同步存储
            Assert.IsNotNull(sc);
            sw.Restart();
            sc.SetStringValue(key, strValue, ts);
            sw.Stop();
            Console.WriteLine($"SetStringValue 一次执行时间{sw.ElapsedMilliseconds}毫秒");
            sw.Restart();
            strResult = sc.GetStringValue(key);
            sw.Stop();
            Console.WriteLine($"GetStringValue 一次执行时间{sw.ElapsedMilliseconds}毫秒");
            Assert.IsTrue(strResult == strValue);
            strValue = Guid.NewGuid().ToString();
            sc.SetStringValue(key, strValue, ts);
            strResult = sc.GetStringValue(key);
            Assert.IsTrue(strResult == strValue);
            sw.Restart();
            for (int i = 0; i < runTimes; i++) {
                strResult = sc.GetStringValue(key);
                Assert.IsTrue(strResult == strValue);
            }
            sw.Stop();
            Console.WriteLine($"GetStringValue {runTimes}次执行时间{sw.ElapsedMilliseconds}毫秒");

            //字符串异步存储
            Assert.IsNotNull(sca);
            sw.Restart();
            sca.SetStringValueAsync(key, strValue, ts).Wait();
            sw.Stop();
            Console.WriteLine($"SetStringValueAsync 一次执行时间{sw.ElapsedMilliseconds}毫秒");

            strResult = Guid.NewGuid().ToString();
            sw.Restart();
            strResult = sca.GetStringValueAsync(key).Result;
            sw.Stop();
            Console.WriteLine($"GetStringValueAsync 一次执行时间{sw.ElapsedMilliseconds}毫秒");
            Assert.IsTrue(strResult == strValue);
            strValue = Guid.NewGuid().ToString();
            sca.SetStringValueAsync(key, strValue, ts).Wait();
            strResult = sca.GetStringValueAsync(key).Result;
            Assert.IsTrue(strResult == strValue);
            sw.Restart();
            for (int i = 0; i < 100; i++) {
                strResult = sca.GetStringValueAsync(key).Result;
                Assert.IsTrue(strResult == strValue);
            }
            sw.Stop();
            Console.WriteLine($"GetStringValueAsync {runTimes}次执行时间{sw.ElapsedMilliseconds}毫秒");

            //对象同步存储
            var obj = new CacheTestModel {
                Id = 1, Name = "name1"
            };
            sw.Restart();
            sc.SetValue(key, obj, ts);
            sw.Stop();
            Console.WriteLine($"SetValue 一次执行时间{sw.ElapsedMilliseconds}毫秒");
            sw.Restart();
            var objResult = sc.GetValue<CacheTestModel>(key);
            sw.Stop();
            Console.WriteLine($"GetValue 一次执行时间{sw.ElapsedMilliseconds}毫秒");
            Assert.IsTrue(obj.Equals(objResult));
            //对象异步存储
            sw.Restart();
            sca.SetValueAsync(key, obj, ts);
            sw.Stop();
            Console.WriteLine($"SetValueAsync 一次执行时间{sw.ElapsedMilliseconds}毫秒");
            objResult = null;
            sw.Restart();
            objResult = sca.GetValueAsync<CacheTestModel>(key).Result;
            sw.Stop();
            Console.WriteLine($"GetValueAsync 一次执行时间{sw.ElapsedMilliseconds}毫秒");
            Assert.IsTrue(obj.Equals(objResult));
        }

        internal class CacheTestModel
        {
            public int Id { get; set; }
            public string Name { get; set; }

            public override bool Equals(object? obj) {
                Console.WriteLine("对象比较");
                if (obj == null) {
                    return false;
                }
                if (obj is CacheTestModel o) {
                    return o.Id == this.Id && o.Name == this.Name;
                }
                else {
                    return false;
                }
            }
        }
    }
}