using System;
using NUnit.Framework;

namespace ServiceStack.OrmLite.Tests.Issues
{
    public class Organization
    {
        public Guid Id { get; set; }
        public bool IsActive { get; set; }
        public string Name { get; set; }
    }

    public class OrganizationMembership
    {
        public Guid Id { get; set; }
        public Guid OrganizationId { get; set; }
        public bool HasA { get; set; }
        public bool HasB { get; set; }
        public bool HasC { get; set; }
    }

    [TestFixtureOrmLiteDialects(Dialect.Sqlite)]
    public class MergingNestedSqlExpressionIssue : OrmLiteProvidersTestBase
    {
        public MergingNestedSqlExpressionIssue(DialectContext context) : base(context) {}

        [Test]
        public void Does_merge_subselect_params_correctly()
        {
            // select a group of ids
            var ids = DialectProvider.SqlExpression<OrganizationMembership>();
            ids.Where(x => x.HasA == true && x.HasB == true && x.HasC == true);
            ids.SelectDistinct(x => x.OrganizationId);

            //0 params
            var q = DialectProvider.SqlExpression<Organization>(); 
            q.Where(x => Sql.In(x.Id, ids));
            Assert.That(q.WhereExpression, Is.EqualTo(
                "WHERE \"Id\" IN (SELECT DISTINCT \"OrganizationId\" \nFROM \"OrganizationMembership\"\nWHERE (((\"HasA\" = @0) AND (\"HasB\" = @1)) AND (\"HasC\" = @2)))"));

            //1 param
            q = DialectProvider.SqlExpression<Organization>();
            q.Where(x => x.IsActive == true);
            q.Where(x => Sql.In(x.Id, ids));
            Assert.That(q.WhereExpression, Is.EqualTo(
                "WHERE (\"IsActive\" = @0) AND \"Id\" IN (SELECT DISTINCT \"OrganizationId\" \nFROM \"OrganizationMembership\"\nWHERE (((\"HasA\" = @1) AND (\"HasB\" = @2)) AND (\"HasC\" = @3)))"));

            //2 params
            q = DialectProvider.SqlExpression<Organization>();
            q.Where(x => x.IsActive == true);
            q.Where(x => x.IsActive == true);
            q.Where(x => Sql.In(x.Id, ids));
            Assert.That(q.WhereExpression, Is.EqualTo(
                "WHERE (\"IsActive\" = @0) AND (\"IsActive\" = @1) AND \"Id\" IN (SELECT DISTINCT \"OrganizationId\" \nFROM \"OrganizationMembership\"\nWHERE (((\"HasA\" = @2) AND (\"HasB\" = @3)) AND (\"HasC\" = @4)))"));

            //3 params
            q = DialectProvider.SqlExpression<Organization>();
            q.Where(x => x.IsActive == true);
            q.Where(x => x.IsActive == true);
            q.Where(x => x.IsActive == true);
            q.Where(x => Sql.In(x.Id, ids));
            Assert.That(q.WhereExpression, Is.EqualTo(
                "WHERE (\"IsActive\" = @0) AND (\"IsActive\" = @1) AND (\"IsActive\" = @2) AND \"Id\" IN (SELECT DISTINCT \"OrganizationId\" \nFROM \"OrganizationMembership\"\nWHERE (((\"HasA\" = @3) AND (\"HasB\" = @4)) AND (\"HasC\" = @5)))"));
        }
    }
}