using MediatR;
using Microsoft.EntityFrameworkCore;
using SolutionErp.Application.Common.Interfaces;

namespace SolutionErp.Application.Office;

// Phase 10.2 G-O1 (S34) — Danh bạ nội bộ.
// 1 endpoint readonly query JOIN Users + EmployeeProfiles + Departments.
// FE card grid hiển thị avatar/name/dept/position/email/phone/internal-phone.
// Reuse existing data — KHÔNG mở schema mới.

public sealed record DirectoryItemDto(
    Guid UserId,
    string FullName,
    string? Position,
    string? PhotoUrl,
    Guid? DepartmentId,
    string? DepartmentName,
    string? EmployeeCode,
    string? Email,
    string? Phone,
    string? InternalPhone,
    string? PersonalEmail,
    string? WorkLocation);

public sealed record GetDirectoryQuery(
    string? Search = null,
    Guid? DepartmentId = null) : IRequest<List<DirectoryItemDto>>;

public sealed class GetDirectoryQueryHandler(IApplicationDbContext db)
    : IRequestHandler<GetDirectoryQuery, List<DirectoryItemDto>>
{
    public async Task<List<DirectoryItemDto>> Handle(GetDirectoryQuery request, CancellationToken ct)
    {
        // Active users only — Department LEFT join (admin/system user có thể null dept).
        // EmployeeProfile LEFT join (user chưa được seed EmployeeProfile vẫn hiện trong danh bạ
        // với phone/internalPhone null — sau Phase 10.1 G-H1 thì tất cả 33 prod user đều có).
        var query =
            from u in db.Users.AsNoTracking().Where(x => x.IsActive)
            join d in db.Departments.AsNoTracking() on u.DepartmentId equals d.Id into deptJoin
            from d in deptJoin.DefaultIfEmpty()
            join ep in db.EmployeeProfiles.AsNoTracking() on u.Id equals ep.UserId into epJoin
            from ep in epJoin.DefaultIfEmpty()
            select new
            {
                u.Id,
                u.FullName,
                u.Position,
                u.Email,
                u.DepartmentId,
                DepartmentName = d != null ? d.Name : null,
                EmployeeCode = ep != null ? ep.EmployeeCode : null,
                Phone = ep != null ? ep.Phone : null,
                InternalPhone = ep != null ? ep.InternalPhone : null,
                PersonalEmail = ep != null ? ep.PersonalEmail : null,
                PhotoUrl = ep != null ? ep.PhotoUrl : null,
                WorkLocation = ep != null ? ep.WorkLocation : null,
            };

        if (request.DepartmentId is Guid deptId)
        {
            query = query.Where(x => x.DepartmentId == deptId);
        }

        if (!string.IsNullOrWhiteSpace(request.Search))
        {
            var term = request.Search.Trim();
            query = query.Where(x =>
                x.FullName.Contains(term) ||
                (x.Email != null && x.Email.Contains(term)) ||
                (x.Phone != null && x.Phone.Contains(term)) ||
                (x.InternalPhone != null && x.InternalPhone.Contains(term)) ||
                (x.EmployeeCode != null && x.EmployeeCode.Contains(term)));
        }

        var rows = await query
            .OrderBy(x => x.DepartmentName)
            .ThenBy(x => x.FullName)
            .ToListAsync(ct);

        return rows
            .Select(x => new DirectoryItemDto(
                x.Id,
                x.FullName,
                x.Position,
                x.PhotoUrl,
                x.DepartmentId,
                x.DepartmentName,
                x.EmployeeCode,
                x.Email,
                x.Phone,
                x.InternalPhone,
                x.PersonalEmail,
                x.WorkLocation))
            .ToList();
    }
}
