using BVC.SpotBuyCenter.Core.Case;
using BVC.SpotBuyCenter.Core.Case.Cache;
using BVC.SpotBuyCenter.Core.Crm.Client;
using BVC.SpotBuyCenter.Core.Incoming;
using BVC.SpotBuyCenter.Core.Infrastructure;
using BVC.SpotBuyCenter.Core.Infrastructure.Database;
using BVC.SpotBuyCenter.Services.Account;
using Funq;
using NLog;
using NLog.Config;
using NLog.Targets;
using NUnit.Framework;
using Raven.Abstractions.Data;
using Raven.Client;
using Raven.Client.Embedded;
using Raven.Client.Indexes;
using Raven.Client.Listeners;
using ServiceStack.CacheAccess;
using ServiceStack.CacheAccess.Providers;
using ServiceStack.ServiceClient.Web;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.Auth;
using ServiceStack.WebHost.Endpoints;
using ServiceStack.WebHost.Endpoints.Support;
 
namespace BVC.SpotBuyCenter.Tests.Integration
{
    [SetUpFixture]
    public class GlobalSetupFixture
    {
        public const string HostUrl = "http://localhost:9987/";
        public static HttpListenerBase Host;
        public static JsonServiceClient Client;
 
        public static IDocumentStore Store
        {
            get { return Host.Container.Resolve<IDocumentStore>(); }
        }
 
        public static IUserAuthRepository AuthRepository
        {
            get { return Host.Container.Resolve<IUserAuthRepository>(); }
        }
 
        public static ICacheClient CacheClient
        {
            get { return Host.Container.Resolve<ICacheClient>(); }
        }
 
        [SetUp]
        public void GlobalSetup()
        {
            Host = new SelfAppHost();
            Host.Init();
            Host.Start(HostUrl);
 
            Client = new JsonServiceClient(HostUrl);            
        }
 
        [TearDown]
        public void GlobalTearDown()
        {
            Host.Dispose();
            Host = null;
        }
    }
 
    public class SelfAppHost : AppHostHttpListenerBase
    {
        public SelfAppHost() : base("BVC Web Services Test Host", typeof(AccountService).Assembly) { }
 
        public override void Configure(Container container)
        {
            container.RegisterAs<TestStorageConfig, IStorageConfig>().ReusedWithin(ReuseScope.Container);
 
            container.Resolve<IStorageConfig>().Init(container);
 
            MainAppHostConfiguration.Apply(this, container);
 
            ConfigureLogging();
 
            Plugins.Add(new AuthFeature(() => new AuthUserSession(), new[] { new CredentialsAuthProvider() }));
        }
 
        private static void ConfigureLogging()
        {
            var config = new LoggingConfiguration();
            ColoredConsoleTarget consoleTarget = new ColoredConsoleTarget();
            config.AddTarget("console", consoleTarget);
            consoleTarget.Layout = @"${date:format=HH\:MM\:ss} ${logger} ${message}";
            config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
            LogManager.Configuration = config;
        }
    }
 
    public class TestStorageConfig : IStorageConfig
    {
        public IDocumentStore Store { get; set; }
 
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
 
        public void Init(Container container)
        {
            var store = new EmbeddableDocumentStore { RunInMemory = true };
 
            logger.Debug("Initializing in-memory document store...");
 
            store.Initialize();
            store.RegisterListener(new NoStaleQueriesListener());
            Store = store;
 
            logger.Debug("Document store created.");
 
            IndexCreation.CreateIndexes(typeof(ClientsByDivisionId).Assembly, Store);
 
            container.Register(Store);
 
            container.Register(c => c.Resolve<IDocumentStore>().OpenSession()).ReusedWithin(ReuseScope.Request);
 
            container.RegisterAs<CaseCacheManager, ICaseCacheManager>().ReusedWithin(ReuseScope.Request);
            container.RegisterAs<CreateCaseFromIncomingRfpHandler, ICreateCaseFromIncomingRfpHandler>().ReusedWithin(ReuseScope.Request);
            container.RegisterAs<CreateCaseFromIncomingPoHandler, ICreateCaseFromIncomingPoHandler>().ReusedWithin(ReuseScope.Request);
            container.RegisterAs<CaseFactory, ICaseFactory>().ReusedWithin(ReuseScope.Request);
 
            container.Register<ICacheClient>(new MemoryCacheClient());
            container.Register<IUserAuthRepository>(new RavenUserAuthRepository(Store));
        }
 
        public DatabaseStatistics GetDbStats()
        {
            return null;
        }
    }
 
    public class NoStaleQueriesListener : IDocumentQueryListener
    {
        public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization)
        {
            queryCustomization.WaitForNonStaleResults();
        }
    }
}