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

namespace LSFE.Domain.Services.TimeKeeping
{
    public class AttendanceRepo : GenericRepository<Attendance>, IAttendanceRepo
    {
        private readonly LSFEDbContext _context;
        public AttendanceRepo(LSFEDbContext context) : base(context)
        {
            _context = context;
        }
        public async Task<List<Infrastructure.Entities.TimeKeeping.AttendanceDto>> 
            GetAttendance(Infrastructure.Dto.TimeKeeping.AttendanceDto dto)
        {
            var now = DateTime.UtcNow;
            var startDate = new DateTime(now.Year,now.Month,1,0, 0, 0,DateTimeKind.Utc);
            var endDate = startDate.AddMonths(1);


            var attendance = await _context.AttendanceDto
            .FromSqlRaw(
                "EXEC GetAttendance @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 attendance ?? new List<Infrastructure.Entities.TimeKeeping.AttendanceDto>();
        }

        public async Task<List<Attendance>> GetAttendanceToday(CredentialDto dto)
        {
            var attendance = await _context.Attendances
               .FromSqlRaw("EXEC GetAttendanceToday @UserId",
               new SqlParameter("@UserId", dto.UserId))
               .ToListAsync();

            return attendance ?? new List<Attendance>();
        }

        public async Task<Response> PostPutAttendance(Infrastructure.Dto.TimeKeeping.AttendanceDto dto)
        {
            try
            {
                // Query by AppAttendanceId (the mobile app's ID), not AttendanceId (the DB auto-increment)
                var logs = await _context.Attendances
                    .FirstOrDefaultAsync(a => a.UserId == dto.UserId &&
                                             a.AppAttendanceId == dto.AppAttendanceId);

                if (logs == null)
                {
                    // Create new record - don't set AttendanceId, let the DB auto-increment it
                    var attendance = new Attendance
                    {
                        AppAttendanceId = dto.AppAttendanceId,
                        TimeIn = dto.TimeIn,
                        UserId = dto.UserId,
                        TimeOut = dto.TimeOut,
                        TimeInLocation = dto.TimeInLocation,
                        TimeOutLocation = dto.TimeOutLocation,
                        SignatureFileNameIn = dto.SignatureFileNameIn,
                    };
                    await _context.AddAsync(attendance);
                    await _context.SaveChangesAsync(); // MUST SAVE!
                }
                else
                {
                    // Update existing record
                    logs.TimeIn = dto.TimeIn;
                    logs.TimeOut = dto.TimeOut;
                    logs.TimeInLocation = dto.TimeInLocation;
                    logs.TimeOutLocation = dto.TimeOutLocation;
                    logs.SignatureFileNameOut = dto.SignatureFileNameOut;
                    await _context.SaveChangesAsync();
                }

                return new Response
                {
                    Message = "Sync Successfully",
                    MessCode = 1,
                    Success = true
                };
            }
            catch (Exception ex)
            {
                // Log the actual error
                Debug.WriteLine($"PostPutAttendance Error: {ex.ToString()}");
                throw; // Re-throw so the controller can log it
            }
        }
    }
}
