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 Shared.EntityModels;
    using Shared.UserModels.Filters;

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

        /// <inheritdoc cref="IInsuranceCompanyService" />
        public InsuranceCompanyServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public Task<IEnumerable<InsuranceCompanyModel>> FetchAsync(InsuranceCompanyFilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            if (model.AdmissionId != null)
            {
                where += $@" AND ins.""AdmissionId"" = {model.AdmissionId}";
            }
            if (model.InsuranceCompanyId != null)
            {
                where += $@" AND ins.""InsuranceCompanyId"" = {model.InsuranceCompanyId}";
            }
            if (!string.IsNullOrEmpty(model.FullName))
            {
                where += $@" AND TRIM(UPPER(ins.""FullName"")) ilike '%{model.FullName.Trim().ToUpper()}%'";
            }

            if (!string.IsNullOrEmpty(model.ContactPersonName))
            {
                where += $@" AND TRIM(UPPER(ins.""ContactPersonName"")) ilike '%{model.ContactPersonName.Trim().ToUpper()}%'";
            }

            if (!string.IsNullOrEmpty(model.Mobile))
            {
                where += $@" AND TRIM(UPPER(ins.""ContactPersonMobile"")) ilike '%{model.Mobile.Trim().ToUpper()}%'";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND ins.""ContactPeriodFrom""::DATE >= '{model.FromDate}'::DATE";
                where += $@" AND ins.""ContactPeriodTo""::DATE <= '{model.ToDate}'::DATE";
            }

            if (model.CountryId != null)
            {
                where += $@" AND ins.""CountryId"" = '{model.CountryId}'";
            }
            //if (model.InsuranceCompanyId > 0)
            //{
            //    where += $@" AND ins.""InsuranceCompanyId"" = {model.InsuranceCompanyId}";
            //}
            if (model.Active != null)
            {
                where += $@" AND ins.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
            }

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", ins.""InsuranceCompanyId"", ins.""FullName"", ins.""CountryId"", cun.""CountryName"", cun.""CountryCode"", ins.""ContactPersonName"", ins.""ContactPeriodFrom"", ins.""ContactPeriodTo"", ins.""ContactPersonMobile"", ins.""Active"", ins.""CreatedDate"", ins.""ModifiedDate""
                                FROM ""InsuranceCompany"" ins
                                JOIN ""Country"" cun ON cun.""CountryId"" = ins.""CountryId"" AND cun.""Active"" IS TRUE
                                {where} Order by ins.""InsuranceCompanyId"" DESC";

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

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

        /// <inheritdoc />
        public async Task<int> AddAsync(InsuranceCompanyModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""InsuranceCompanyId"") FROM ""InsuranceCompany"" WHERE TRIM(UPPER(""FullName"")) = '{model.FullName.ToUpper().Trim()}' AND ""CountryId"" = '{model.CountryId}'");
            if (checkIf > 0)
            {
                return -1;
            }

            var insuranceCompany = new InsuranceCompany
            {
                Active = true,
                FullName = model.FullName.Trim(),
                ContactPeriodFrom = model.ContactPeriodFrom,
                ContactPeriodTo = model.ContactPeriodTo,
                ContactPersonMobile = model.ContactPersonMobile,
                ContactPersonName = model.ContactPersonName,
                CountryId = model.CountryId,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.UtcNow
            };

            return await this.unitOfWork.InsuranceCompanies.InsertAsync(insuranceCompany);
        }

        /// <inheritdoc />
        public async Task<int> UpdateAsync(InsuranceCompanyModel model)
        {
            var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""InsuranceCompanyId"") FROM ""InsuranceCompany"" WHERE TRIM(UPPER(""FullName"")) = '{model.FullName.ToUpper().Trim()}' AND ""CountryId"" = '{model.CountryId}' AND ""InsuranceCompanyId"" <> {model.InsuranceCompanyId}");
            if (checkIf > 0)
            {
                return -1;
            }

            var insuranceCompany = await this.unitOfWork.InsuranceCompanies.FindAsync(m => m.InsuranceCompanyId == model.InsuranceCompanyId);
            insuranceCompany.FullName = model.FullName.Trim();

            insuranceCompany.CountryId = model.CountryId;
            insuranceCompany.ContactPeriodTo = model.ContactPeriodTo;
            insuranceCompany.ContactPeriodFrom = model.ContactPeriodFrom;
            insuranceCompany.ContactPersonMobile = model.ContactPersonMobile;
            insuranceCompany.ContactPersonName = model.ContactPersonName;
            insuranceCompany.ModifiedBy = model.ModifiedBy;
            insuranceCompany.ModifiedDate = DateTime.UtcNow;

            return await this.unitOfWork.InsuranceCompanies.UpdateAsync(insuranceCompany);
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int insuranceCompanyId)
        {
            var query = $@"DELETE FROM ""InsuranceCompany"" WHERE ""InsuranceCompanyId""= {insuranceCompanyId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public Task<int> ModifyStatusAsync(int insuranceCompanyId, int modifiedBy, bool status)
        {
            var query = $@"UPDATE ""InsuranceCompany"" SET ""Active"" = {status}, ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""InsuranceCompanyId""= {insuranceCompanyId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public async Task<string> FindNameByInsuranceId(int insuranceCompanyId)
        {
            var query = $@"SELECT ""FullName"" FROM ""InsuranceCompany""  WHERE ""InsuranceCompanyId"" = {insuranceCompanyId} ";
            var response = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>(query);
            return response;
        }
    }
}