namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    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.ScanClassification;
    using Hims.Shared.UserModels.Scan.ScanMachine;
    using Hims.Shared.UserModels.Scan.ScanTest;


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

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

        public async Task<int> AddAsync(InsertModel model)
        {
            var checkIf = this.unitOfWork.Current.QuerySingleOrDefault<int>($@"Select count(*) from ""ScanClassification"" where upper(""ScanClassificationName"")= upper('{model.ScanClassificationName}')");
            if (checkIf != 0)
            {
                return -1;
            }
            var scanClassification = new ScanClassification
            {
                Active = true,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                ScanClassificationName = model.ScanClassificationName,
                //LocationId = model.LocationId

            };
            scanClassification.ScanClassificationId = await this.unitOfWork.ScanClassifications.InsertAsync(scanClassification);
            return scanClassification.ScanClassificationId;
        }

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

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

            if (model.ScanClassificationId > 0) {
                where += $@" and sc.""ScanClassificationId"" = {model.ScanClassificationId} ";
            }
            if (model.Active != null)
            {
                where += $@" AND sc.""Active"" IS {model.Active}";
            }
            var query = $@"select COUNT(*) OVER () AS ""TotalItems"",sc.""ScanClassificationId"",sc.""ScanClassificationName"",sc.""Active"", sc.""CreatedDate"",sc.""ModifiedDate"",ac.""FullName"" as ""CreatedByName"" ,a.""FullName"" as ""ModifiedByName"" 

                from ""ScanClassification"" sc
                left join ""Account"" ac on ac.""AccountId"" = sc.""CreatedBy""
                left join ""Account"" a on a.""AccountId"" = sc.""ModifiedBy"" {where} order by sc.""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<int> ActivateOrDeactivateClassification(InsertModel model)
        {
            try
            {
                var record = await this.unitOfWork.ScanClassifications.FindAsync(m => m.ScanClassificationId == model.ScanClassificationId);
                
                var item = await this.unitOfWork.ScanSubClassifications.FindAsync(m => m.ScanClassificationId == model.ScanClassificationId);
                
                if (record == null)
                {
                    return -1;
                }
                if (item != null)
                {
                    if(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.ScanClassifications.UpdateAsync(record);
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public async Task<int> UpdateAsync(InsertModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""ScanClassificationId"") FROM ""ScanClassification"" WHERE TRIM(UPPER(""ScanClassificationName"")) = '{model.ScanClassificationName.ToUpper().Trim()}' AND ""ScanClassificationId"" <> {model.ScanClassificationId}");
            if (checkIf > 0)
            {
                return -1;
            }
            var scanClassification = await this.unitOfWork.ScanClassifications.FindAsync(m => m.ScanClassificationId == model.ScanClassificationId);

            scanClassification.Active = true;
            scanClassification.ModifiedBy = model.ModifiedBy;
            scanClassification.ModifiedDate = DateTime.Now;
            scanClassification.ScanClassificationName = model.ScanClassificationName;
            //scanClassification.LocationId = model.LocationId;

            scanClassification.ScanClassificationId = await this.unitOfWork.ScanClassifications.UpdateAsync(scanClassification);
            return scanClassification.ScanClassificationId;


        }
    }
}