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

    /// <inheritdoc />
    public class MachineService : IMachineService
    {
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IMachineService" />
        public MachineService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        public async Task<int> ActivateOrDeactivateMachine(MachineModel model)
        {
            var query = $@"UPDATE ""Machine""
	                           SET ""ModifiedBy""={model.CreatedBy}, ""ModifiedDate""=now(), ""Active""= {model.Active}
	                           WHERE ""MachineId""= {model.MachineId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

      
        //public async Task<IEnumerable<MachineModel>> FetchActiveAllAsync(MachineModel model)
        //{
        //    var where = "where 1=1";

        //    var query = $@"select count(M.""MachineId"") over() as ""TotalItems"", M.""MachineId"", M.""MachineCode"", M.""MachineName"" ,M.""Active"", M.""CreatedBy"", M.""CreatedDate"",
		      //                  ID.""ModifiedBy"", ID.""ModifiedDate"",IMachin
		      //                  C.""FullName"" as ""CreatedByName"", CR.""RoleName"" as ""CreatedByRole"",M1.""FullName"" as ""ModifiedByName"", MR.""RoleName"" as ""ModifiedByRole""
        //                     FROM ""Machine"" M 
        //                     join ""Account"" C on C.""AccountId"" = m.""CreatedBy""
        //                     join ""Role"" CR on CR.""RoleId"" = C.""RoleId""
        //                     left join ""Account"" M1 on M1.""AccountId"" = M1.""ModifiedBy""
        //                     left join ""Role"" MR on MR.""RoleId"" = M1.""RoleId""
        //                        {where} AND M.""Active"" = true
        //                     order by M.""CreatedDate"" desc";


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

        public async Task<IEnumerable<MachineModel>> FetchAllAsync(MachineModel model)
        {
            var where = "where 1=1";

            if (model.Active != null)
            {
                where += (bool)model.Active ? $@" and M.""Active"" is true " : $@" and M.""Active"" is false ";
            }
            if (!string.IsNullOrEmpty(model.MachineName))
            {
                where += $@" and lower(M.""MachineName"") ilike '%{model.MachineName.ToLower()}%' ";
            }
            if (!string.IsNullOrEmpty(model.MachineCode))
            {
                where += $@" and lower(M.""MachineCode"") ilike '%{model.MachineCode.ToLower()}%' ";
            }
            var query = $@"select count(M.""MachineId"") over() as ""TotalItems"", M.""MachineId"", M.""MachineCode"",M.""MachineName"", M.""Active"", M.""CreatedBy"", M.""CreatedDate"",
		                       M.""ModifiedBy"", M.""ModifiedDate"",
		                        C.""FullName"" as ""CreatedByName"", CR.""RoleName"" as ""CreatedByRole"",M1.""FullName"" as ""ModifiedByName"", MR.""RoleName"" as ""ModifiedByRole""
                             FROM ""Machine"" M 
                             join ""Account"" C on C.""AccountId"" = M.""CreatedBy""
                             join ""Role"" CR on CR.""RoleId"" = C.""RoleId""
                             left join ""Account"" M1 on M1.""AccountId"" = M.""ModifiedBy""
                             left join ""Role"" MR on MR.""RoleId"" = M1.""RoleId""
                                 {where} 
                             order by m.""CreatedDate"" desc";
            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";
            }

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

        }

        public async Task<int> InsertAsync(MachineModel model)
        {
            var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"select count(*) from ""Machine"" where  lower(""MachineName"") = '{model.MachineName.ToLower()}'");
            if (checkIf > 0)
            {
                return -1;
            }
            try
            {
                var machine = new Machine
                {
                    MachineCode = await this.GetLatestMachineNumber(),
                    MachineName = model.MachineName,
                    CreatedBy = model.CreatedBy,
                    Active = true,
                    CreatedDate = DateTime.Now,
                };
                return await this.unitOfWork.Machines.InsertAsync(machine);
            }
            catch(Exception e)
            {
                return 0;
            }
           
        }

        public async Task<int> UpdateAsync(MachineModel model)
        {
            try
            {
                var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"select count(*) from ""Machine"" where  lower (""MachineName"") = '{model.MachineName.ToLower()}' and ""MachineId"" <> {model.MachineId}");
                if (checkIf > 0)
                {
                    return -1;
                }
                var record = await this.unitOfWork.Machines.FindAsync(m => m.MachineId == model.MachineId);
                if (record == null)
                {
                    return -2;
                }
                record.ModifiedBy = model.CreatedBy;
                record.ModifiedDate = DateTime.UtcNow.AddMinutes(330);
                record.MachineName = model.MachineName;
                return await this.unitOfWork.Machines.UpdateAsync(record);
            }
            catch (Exception ex)
            {
                //ignore
            }
            return 1;
        }

        /// <summary>Gets the latest machine number.</summary>
        /// <returns></returns>
        private async Task<string> GetLatestMachineNumber()
        {
            var fixedText = "M";
            var previous = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>($@"select ""MachineCode"" from ""Machine"" order by ""MachineId"" desc limit 1");
            if (previous == null)
            {
                return $@"{fixedText}{DateTime.Now:yyyy}1";
            }
            else
            {
                var numWithoutFixedText = previous.Replace(fixedText, "");
                var getYear = numWithoutFixedText[..4];
                if (getYear != DateTime.Now.ToString("yyyy"))
                {
                    return $@"{fixedText}{DateTime.Now:yyyy}1";
                }
                var getNumber = numWithoutFixedText.Replace(DateTime.Now.ToString("yyyy"), "");
                var getCurrentCount = long.Parse(getNumber) + 1;
                return $@"{fixedText}{DateTime.Now:yyyy}{getCurrentCount}";
            }
        }

    }
}
