using Brizco.Domain.Entities.Tasks;
using Task = Brizco.Domain.Entities.Tasks.Task;

namespace Brizco.Core.CoreServices;

public class PageService : IPageService
{
    private readonly ICurrentUserService _currentUserService;
    private readonly IRepositoryWrapper _repositoryWrapper;
    private readonly RoleManager<ApplicationRole> _roleManager;
    private readonly IMediator _mediator;

    public PageService(
        ICurrentUserService currentUserService,
        IRepositoryWrapper repositoryWrapper,
        RoleManager<ApplicationRole> roleManager,
        IMediator mediator)
    {
        _currentUserService = currentUserService;
        _repositoryWrapper = repositoryWrapper;
        _roleManager = roleManager;
        _mediator = mediator;
    }
    public async Task<AppDashboardPageDto> GetAppDashboardAsync(CancellationToken cancellationToken = default)
    {
        if (_currentUserService.UserId == null)
            throw new AppException("User id is null ");
        if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
            throw new AppException("User id is wrong");
        if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
            throw new AppException("Complex id is wrong");

        var todayActivities = await _repositoryWrapper.SetRepository<Activity>()
            .TableNoTracking
            .Where(a => a.ComplexId == complexId && a.SetFor.Date == DateTime.Today.Date)
            .ToListAsync(cancellationToken);
        var todayShiftPlans = await _repositoryWrapper.SetRepository<ShiftPlan>()
            .TableNoTracking
            .Where(a => a.PlanFor.Date == DateTime.Today.Date && a.ComplexId == complexId)
            .Select(ShiftPlanMapper.ProjectToSDto)
            .ToListAsync(cancellationToken);

        foreach (var shiftPlan in todayShiftPlans)
        {
            shiftPlan.DoneActivitiesCount = todayActivities.Count(a=>a.ShiftPlanId == shiftPlan.Id && a.IsDone);
            shiftPlan.UndoneActivitiesCount = todayActivities.Count(a=>a.ShiftPlanId == shiftPlan.Id && !a.IsDone);
            shiftPlan.TotalActivitiesCount = todayActivities.Count(a=>a.ShiftPlanId == shiftPlan.Id );
        }

        var names = new List<string>();
        names.AddRange(todayShiftPlans.SelectMany(sp => sp.Users).Select(s => s.UserFullName).ToList());
        var page = new AppDashboardPageDto
        {
            DoneActivitiesToday = todayActivities.Count(t => t.IsDone),
            TotalActivitiesToday = todayActivities.Count,
            UnDoneActivitiesToday = todayActivities.Count(t => t.IsDone!),
            TotalShiftToday = todayShiftPlans.Count,
            TodayStaffNames = names,
            TotalStaffToday = todayShiftPlans.SelectMany(sp => sp.Users).GroupBy(u=>u.UserId).Count(),
            ShiftPlans = todayShiftPlans
        };

        var currentShift = todayShiftPlans.FirstOrDefault(s => s.EndAt >= DateTime.Now.TimeOfDay && s.StartAt <= DateTime.Now.TimeOfDay);
        if (currentShift != null)
        {
            page.CurrentShift = currentShift.ShiftTitle;
            page.CurrentShiftId = currentShift.Id;
            page.CurrentPosition = currentShift.Users.FirstOrDefault(f => f.UserId == userId)?.PositionName ?? string.Empty;
        }

        if (_currentUserService.Permissions != null)
        {
            int totalStepCount = 0;
            int completeStepCount = 0;
            string currentStep = string.Empty;
            if (_currentUserService.Permissions.Exists(s => s == ApplicationPermission.ManageRoutines))
            {
                totalStepCount++;
                var hasRoutine = await _repositoryWrapper.SetRepository<Routine>()
                    .TableNoTracking
                    .AnyAsync(r => r.ComplexId == complexId, cancellationToken);
                if (hasRoutine)
                    completeStepCount++;
                else
                {
                    if (currentStep.IsNullOrEmpty())
                        currentStep = "تکمیل بخش روتین ها";
                }
            }
            if (_currentUserService.Permissions.Exists(s => s == ApplicationPermission.ManageSections))
            {
                totalStepCount++;
                var hasSection = await _repositoryWrapper.SetRepository<Section>()
                    .TableNoTracking
                    .AnyAsync(r => r.ComplexId == complexId, cancellationToken);
                if (hasSection)
                    completeStepCount++;
                else
                {
                    if (currentStep.IsNullOrEmpty())
                        currentStep = "تکمیل بخش سکشن ها";
                }
            }
            if (_currentUserService.Permissions.Exists(s => s == ApplicationPermission.ManagePositions))
            {
                totalStepCount++;
                var hasPosition = await _repositoryWrapper.SetRepository<Position>()
                    .TableNoTracking
                    .AnyAsync(r => r.ComplexId == complexId, cancellationToken);
                if (hasPosition)
                    completeStepCount++;
                else
                {
                    if (currentStep.IsNullOrEmpty())
                        currentStep = "تکمیل بخش پوزیشن ها";
                }
            }
            if (_currentUserService.Permissions.Exists(s => s == ApplicationPermission.ManageStaffs))
            {
                totalStepCount++;
                var hasStaff = await _repositoryWrapper.SetRepository<ComplexUser>()
                    .TableNoTracking
                    .AnyAsync(r => r.ComplexId == complexId, cancellationToken);
                if (hasStaff)
                    completeStepCount++;
                else
                {
                    if (currentStep.IsNullOrEmpty())
                        currentStep = "تکمیل بخش کاربر ها";
                }
            }
            if (_currentUserService.Permissions.Exists(s => s == ApplicationPermission.ManageShifts))
            {
                totalStepCount++;
                var hasShift = await _repositoryWrapper.SetRepository<Shift>()
                    .TableNoTracking
                    .AnyAsync(r => r.ComplexId == complexId, cancellationToken);
                if (hasShift)
                    completeStepCount++;
                else
                {
                    if (currentStep.IsNullOrEmpty())
                        currentStep = "تکمیل بخش شیفت ها";
                }
            }
            if (_currentUserService.Permissions.Exists(s => s == ApplicationPermission.ManageTasks))
            {
                totalStepCount++;
                var hasTask = await _repositoryWrapper.SetRepository<Task>()
                    .TableNoTracking
                    .AnyAsync(r => r.ComplexId == complexId, cancellationToken);
                if (hasTask)
                    completeStepCount++;
                else
                {
                    if (currentStep.IsNullOrEmpty())
                        currentStep = "تکمیل بخش تسک ها";
                }
            }
            if (_currentUserService.Permissions.Exists(s => s == ApplicationPermission.ManageShiftPlans))
            {
                totalStepCount++;
                var hasStaff = await _repositoryWrapper.SetRepository<ShiftPlan>()
                    .TableNoTracking
                    .AnyAsync(r => r.ComplexId == complexId, cancellationToken);
                if (hasStaff)
                    completeStepCount++;
                else
                {
                    if (currentStep.IsNullOrEmpty())
                        currentStep = "تکمیل بخش شیفت بندی ها";
                }
            }

            page.SignUpCompletePercent = completeStepCount != 0 ? ((totalStepCount * 100) / completeStepCount) : 0;
            page.CurrentSignUpStep = currentStep;

        }

        return page;
    }

    public async Task<List<AppShiftingPageDayDto>> GetShiftingPageAsync(Guid routineId,CancellationToken cancellationToken = default)
    {
        if (_currentUserService.ComplexId == null)
            throw new AppException("ComplexId is null", ApiResultStatusCode.NotFound);
        if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
            throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);

        var days = new List<AppShiftingPageDayDto>();
        DateTime day = DateTime.Today;

        var shifts = await _mediator.Send(new GetRoutineShiftsQuery(routineId, 0),
            cancellationToken);

        for (int i = 0 ; i < 15; i++ , day = day.AddDays(1))
        {
            var item = new AppShiftingPageDayDto
            {
                DateTime = DateTimeExtensions.DateTimeToUnixTimeStamp(day)
            };
            shifts.Where(s=>s.Day == day.DayOfWeek)
                .SelectMany(s=>s.Shifts).OrderBy(s=>s.StartAt).ToList().ForEach(s=>item.Shifts.Add(s.Clone()));
            foreach (var shift in item.Shifts)
            {
                var existedShiftPlan = await _repositoryWrapper.SetRepository<ShiftPlan>()
                    .TableNoTracking
                    .FirstOrDefaultAsync(s => s.ShiftId == shift.Id && s.PlanFor.Date == day.Date, cancellationToken);
                shift.CurrentShiftPlanId = existedShiftPlan?.Id ?? default;
                shift.HasCurrentShiftPlan = shift.CurrentShiftPlanId != default;
            }
            item.TotalShifts = item.Shifts.Count;
            item.TotalShiftPlans = item.Shifts.Count(s => s.CurrentShiftPlanId != default);
            days.Add(item);
        }

        return days;
    }
}