namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Transactions;
    using Dapper;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Hims.Domain.Entities;
    using Hims.Shared.EntityModels;
    using Hims.Shared.UserModels;
    using Hims.Shared.UserModels.Scan.ScanSubClassification;


    /// <inheritdoc />
    public class ScanSubClassificationService : IScanSubClassificationService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IScanTestService" />
        public ScanSubClassificationService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        public async Task<int> AddAsync(InsertModel model)
        {
            using (var transaction = this.unitOfWork.BeginTransaction())
            {

                foreach (var record in model.Details)
                {
                    var checkIf = this.unitOfWork.Current.QuerySingleOrDefault<int>($@"Select count(*) from ""ScanSubClassification"" where upper(""ScanSubClassificationName"")= upper('{record.ScanSubClassificationName}')");
                    if (checkIf != 0)
                    {
                        return -1;
                    }
                    var details = new ScanSubClassification
                    {
                        ScanSubClassificationName = record.ScanSubClassificationName,
                        Active = true,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        ScanClassificationId = model.ScanClassificationId,
                        //LocationId = model.LocationId
                    };
                    details.ScanSubClassificationId = await this.unitOfWork.ScanSubClassifications.InsertAsync(details, transaction);

                }

                transaction.Commit();
                return 1;
            }


        }

        public Task<int> DeleteAsync(int scanSubClassificationId)
        {
            var query = $@"DELETE FROM ""ScanSubClassification"" WHERE ""ScanSubClassificationId""= {scanSubClassificationId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<IEnumerable<FetchModel>> FetchAll(FetchModel model)
        {
            var where = $@"where 1=1";  

            if (model.ScanSubClassificationId > 0)
            {
                where += $@" and s.""ScanSubClassificationId"" = {model.ScanSubClassificationId} ";
            }

            if (model.ScanClassificationId > 0)
            {
                where += $@" and sc.""ScanClassificationId"" = {model.ScanClassificationId} ";
            }
            if (model.Active != null)
            {
                where += $@" AND s.""Active"" IS {model.Active}";
            }
            var query = $@"select COUNT(*) OVER () AS ""TotalItems"",s.""ScanSubClassificationId"",s.""ScanSubClassificationName"",s.""ScanClassificationId"",sc.""ScanClassificationName"",s.""Active"",s.""CreatedBy""
                                            ,s.""CreatedDate"",s.""ModifiedBy"",s.""ModifiedDate"",cs.""FullName"" as ""CreatedByName"",
                                            sa.""FullName"" as ""ModifiedByName""
                                                        from ""ScanSubClassification"" s
                                            left join ""ScanClassification"" sc on sc.""ScanClassificationId"" = s.""ScanClassificationId""
                                            left join ""Account"" cs on cs.""AccountId"" = s.""CreatedBy""
                                            left join ""Account"" sa on sa.""AccountId"" = s.""ModifiedBy"" {where} order by s.""CreatedDate"" desc ";

            if (model.PageIndex <= 0 )
            {
                return await this.unitOfWork.Current.QueryAsync<FetchModel>(query);
            }

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
            return await this.unitOfWork.Current.QueryAsync<FetchModel>(query);
        }

        public async Task<IEnumerable<FetchModel>> FetchAltAsync(FetchModel model)
        {
            var where = $@"where 1=1";
            if (model.ScanSubClassificationId != null)
            {
                where += $@" and s.""ScanSubClassificationId"" = {model.ScanSubClassificationId}";
            }
            var query = $@"select s.""ScanSubClassificationId"",s.""ScanSubClassificationName"",s.""ScanClassificationId"",sc.""ScanClassificationName"",s.""CreatedBy"",s.""CreatedDate"",s.""ModifiedBy"",s.""ModifiedDate"",cs.""FullName"" as ""CreatedByName"",
sa.""FullName"" as ""ModifiedByName"" from ""ScanSubClassification"" s
left join ""ScanClassification"" sc on sc.""ScanClassificationId"" = s.""ScanClassificationId""
left join ""Account"" cs on cs.""AccountId"" = s.""CreatedBy""
left join ""Account"" sa on sa.""AccountId"" = s.""ModifiedBy""{where}";


            return await this.unitOfWork.Current.QueryAsync<FetchModel>(query);
        }

        public async Task<int> ActivateOrDeactivateSubClassification(InsertModel model)
        {
            try
            {
                var record = await this.unitOfWork.ScanSubClassifications.FindAsync(m => m.ScanSubClassificationId == model.ScanSubClassificationId);
                var item = await this.unitOfWork.ScanTestMasters.FindAsync(m => m.ScanSubClassificationId == model.ScanSubClassificationId);
                if (record == null || (item != null && item.ScanSubClassificationId > 0 && item.Active == true))
                {
                    return -1;
                }
                record.ModifiedBy = model.ModifiedBy;
                record.ModifiedDate = DateTime.Now;
                record.Active = model.Active == true ? true : false;
                return await this.unitOfWork.ScanSubClassifications.UpdateAsync(record);
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public async Task<int> UpdateAsync(InsertModel model)
        {

            var detail = await this.unitOfWork.ScanSubClassifications.FindAsync(m => m.ScanSubClassificationId == model.ScanSubClassificationId);
            foreach (var record in model.Details)
            {
                var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""ScanSubClassificationId"") FROM ""ScanSubClassification"" where upper(""ScanSubClassificationName"")= upper('{record.ScanSubClassificationName}') AND ""ScanSubClassificationId"" <> {record.ScanSubClassificationId}");
                if (checkIf > 0)
                {
                    return -1;
                }
                if (record.ScanSubClassificationId == 0)
                {
                    var details = new ScanSubClassification
                    {
                        ScanSubClassificationName = record.ScanSubClassificationName,
                        Active = true,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        ScanClassificationId = model.ScanClassificationId,
                        //LocationId = model.LocationId
                    };
                    details.ScanSubClassificationId = await this.unitOfWork.ScanSubClassifications.InsertAsync(details);
                }
                else
                {
                    detail.ScanSubClassificationName = record.ScanSubClassificationName;
                    detail.Active = true;
                    detail.ModifiedBy = model.ModifiedBy;
                    detail.ModifiedDate = DateTime.Now;
                    detail.ScanClassificationId = model.ScanClassificationId;
                    var data = await this.unitOfWork.ScanSubClassifications.UpdateAsync(detail);
                }
            }
            return 1;
        }
    }
}
