using System;
using System.Collections.Generic;
using NUnit.Framework;
using ServiceStack.DataAnnotations;

namespace ServiceStack.OrmLite.Tests.Issues
{
    public class Product
    {
        [AutoIncrement]
        public int Id { get; set; }
        public string ProductType { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public int DisplayOrder { get; set; }
        public bool LimitedToStores { get; set; }
        public string Sku { get; set; }
        public decimal Price { get; set; }
        public decimal OldPrice { get; set; }
        public decimal SpecialPrice { get; set; }
        public decimal DiscountPercentage { get; set; }
        public DateTime? DateChanged { get; set; }
        public DateTime? DateCreated { get; set; }

        [Reference]
        public List<StockItem> StockItems { get; set; } = new List<StockItem>();
    }

    public class StockItem
    {
        [AutoIncrement]
        public int Id { get; set; }
        [References(typeof(Product))]
        public int ProductId { get; set; }
        public string Size { get; set; }
        public int TotalStockQuantity { get; set; }
        public string Gtin { get; set; }
        public int DisplayOrder { get; set; }

        [Reference]
        public Product Product { get; set; }
    }
    
    [TestFixtureOrmLite]
    public class AutoQueryJoinTests : OrmLiteProvidersTestBase
    {
        public AutoQueryJoinTests(DialectContext context) : base(context) {}

        [Test]
        public void Can_select_references_with_join()
        {
            using (var db = OpenDbConnection())
            {
                db.DropTable<StockItem>();
                db.DropTable<Product>();
                db.CreateTable<Product>();
                db.CreateTable<StockItem>();

                db.Save(new Product
                {
                    ProductType = "A",
                    Name = "Name A",
                    DisplayOrder = 1,
                    Sku = "SKU A",
                    Price = 1,
                    DateCreated = DateTime.UtcNow,
                    StockItems = new List<StockItem>
                    {
                        new StockItem { Size = "1", TotalStockQuantity = 1, DisplayOrder = 1 },
                        new StockItem { Size = "2", TotalStockQuantity = 2, DisplayOrder = 2 },
                    }
                }, references: true);

                db.Save(new Product
                {
                    ProductType = "B",
                    Name = "Name B",
                    DisplayOrder = 2,
                    Sku = "SKU B",
                    Price = 2,
                    DateCreated = DateTime.UtcNow,
                    StockItems = new List<StockItem>
                    {
                        new StockItem { Size = "3", TotalStockQuantity = 3, DisplayOrder = 3 },
                        new StockItem { Size = "4", TotalStockQuantity = 4, DisplayOrder = 4 },
                    }
                }, references: true);

                db.Insert(new Product
                {
                    ProductType = "C",
                    Name = "Name C",
                    DisplayOrder = 3,
                    Sku = "SKU C",
                    Price = 3,
                    DateCreated = DateTime.UtcNow,
                });

                var results = db.LoadSelect<Product>();
                Assert.That(results.Count, Is.EqualTo(3));

                var q = db.From<Product>().Join<StockItem>();
                var products = db.Select(q.SelectDistinct());
                var stockItems = db.Select<StockItem>();

                products.Merge(stockItems);

                Assert.That(products.Count, Is.EqualTo(2));
                Assert.That(products[0].StockItems.Count, Is.EqualTo(2));
                Assert.That(products[1].StockItems.Count, Is.EqualTo(2));

                db.DropTable<StockItem>();
            }
        }
    }
}