using LSFE.Domain.Contracts.Reports;
using LSFE.Infrastructure.Database;
using LSFE.Infrastructure.Dto.Reports;
using LSFE.Infrastructure.Entities.Reports;
using LSFE.Infrastructure.Model;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LSFE.Domain.Services.Reports
{
    public class ReportsRepo : IReportsRepo
    {
        private readonly LSFEDbContext _context;
        public ReportsRepo(LSFEDbContext context) 
        {
            _context = context;
        }
        protected Task<(DateTime StartDate, DateTime EndDate)> 
            GetCurrentWholeMonth()
        {
            var now = DateTime.UtcNow;

            var startDate = new DateTime(
                now.Year,
                now.Month,
                1,
                0, 0, 0,
                DateTimeKind.Utc
            );

            var endDate = startDate.AddMonths(1); 

            return Task.FromResult((startDate, endDate));
        }
        public async Task<List<CallRateReport>> GetCallRateReport(ReportsDto dto)
        {
            var (startDate, endDate) = await GetCurrentWholeMonth();

            var allItems = await _context.CallRateReports
            .FromSqlRaw(
                "EXEC GetCallRateReport @UserId,@StartDate,@EndDate,@Period",
                new SqlParameter("@UserId", dto.UserId),
                new SqlParameter("@StartDate", dto.StartDate ?? startDate),
                 new SqlParameter("@EndDate", dto.EndDate ?? endDate),
                new SqlParameter("@Period", dto.Period ?? "monthly")).ToListAsync();

            return allItems ?? new List<CallRateReport>();
        }

        public async Task<List<CallReachReport>> GetCallReachReport(ReportsDto dto)
        {
            var (startDate, endDate) = await GetCurrentWholeMonth();

            var allItems = await _context.CallReachReports
            .FromSqlRaw(
                "EXEC GetCallReachReport @UserId,@StartDate,@EndDate,@Period",
                new SqlParameter("@UserId", dto.UserId),
                new SqlParameter("@StartDate", dto.StartDate ?? startDate),
                 new SqlParameter("@EndDate", dto.EndDate ?? endDate),
                new SqlParameter("@Period", dto.Period ?? "monthly")).ToListAsync();

            return allItems ?? new List<CallReachReport>();
        }

        public async Task<List<CatchUpCallReport>> GetCatchUpCallReport(ReportsDto dto)
        {
            var (startDate, endDate) = await GetCurrentWholeMonth();

            var allItems = await _context.CatchUpCallReports
            .FromSqlRaw(
                "EXEC GetCatchUpCallReport @UserId,@StartDate,@EndDate,@Period",
                new SqlParameter("@UserId", dto.UserId),
                new SqlParameter("@StartDate", dto.StartDate ?? startDate),
                 new SqlParameter("@EndDate", dto.EndDate ?? endDate),
                new SqlParameter("@Period", dto.Period ?? "monthly")).ToListAsync();

            return allItems ?? new List<CatchUpCallReport>();
        }
        public async Task<List<ActualCoverageReport>> GetActualCoverageReport(ReportsDto dto)
        {
            var (startDate, endDate) = await GetCurrentWholeMonth();

            var allItems = await _context.ActualCoverageReports
            .FromSqlRaw(
                "EXEC GetActualCoverageReport @UserId,@StartDate,@EndDate,@Period",
                new SqlParameter("@UserId", dto.UserId),
                new SqlParameter("@StartDate", dto.StartDate ?? startDate),
                 new SqlParameter("@EndDate", dto.EndDate ?? endDate),
                new SqlParameter("@Period", dto.Period ?? "monthly")).ToListAsync();

            return allItems ?? new List<ActualCoverageReport>();
        }
        public async Task<bool> PutMissedCall(ReportsDto dto)
        {
            try
            {
                var catchUp = await _context.CatchUpCalls
                .SingleOrDefaultAsync(c => c.MRRawPlanId == dto.MRRawPlanId);

                if (catchUp != null)
                {
                    catchUp.MissedReason = dto.MissedReason;
                }

                var plan = await _context.MRRawPlans
                    .SingleOrDefaultAsync(c => c.MRRawPlanId == dto.MRRawPlanId);

                if (plan != null)
                {
                    plan.MissedReason = dto.MissedReason;
                }

                await _context.SaveChangesAsync();

                return plan?.MissedReason != null;
            }
            catch (Exception ex)
            {
                ex.ToString();
                throw;
            }
            
        }
    }
}
