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

namespace SolutionErp.Application.Contracts;

// 2-stage department approval list cho HĐ (Phase 9 — Migration 16).
// Mirror PE — query để FE hiển thị progress per phase × dept.
//
// FE Workflow Panel HĐ render dạng timeline:
// - Phase DangGopY (CCM):
//   - Stage Review: nv.cao (NV) — 14:30
//   - Stage Confirm: ccm.tran (TPB) — 14:35 → unlock transition
//
// Insertion + Block logic ở ContractWorkflowService.TransitionAsync.

public record ListContractDepartmentApprovalsQuery(Guid ContractId)
    : IRequest<List<ContractDepartmentApprovalDto>>;

public record ContractDepartmentApprovalDto(
    Guid Id,
    int PhaseAtApproval,
    Guid DepartmentId,
    string? DepartmentName,
    ApprovalStage Stage,
    Guid ApproverUserId,
    string? ApproverName,
    string? ApproverRoleSnapshot,
    string? Comment,
    DateTime ApprovedAt,
    bool IsBypassed);

public class ListContractDepartmentApprovalsQueryHandler(IApplicationDbContext db)
    : IRequestHandler<ListContractDepartmentApprovalsQuery, List<ContractDepartmentApprovalDto>>
{
    public async Task<List<ContractDepartmentApprovalDto>> Handle(
        ListContractDepartmentApprovalsQuery request, CancellationToken ct)
    {
        var rows = await (
            from a in db.ContractDepartmentApprovals.AsNoTracking()
            join d in db.Departments.AsNoTracking() on a.DepartmentId equals d.Id into deptJoin
            from d in deptJoin.DefaultIfEmpty()
            where a.ContractId == request.ContractId
            orderby a.PhaseAtApproval, a.Stage, a.ApprovedAt
            select new
            {
                a.Id,
                a.PhaseAtApproval,
                a.DepartmentId,
                DepartmentName = d != null ? d.Name : null,
                a.Stage,
                a.ApproverUserId,
                a.ApproverRoleSnapshot,
                a.Comment,
                a.ApprovedAt,
                a.IsBypassed,
            }).ToListAsync(ct);

        var userIds = rows.Select(r => r.ApproverUserId).Distinct().ToList();
        var users = await db.Users.AsNoTracking()
            .Where(u => userIds.Contains(u.Id))
            .Select(u => new { u.Id, Name = u.FullName ?? u.Email ?? "" })
            .ToDictionaryAsync(u => u.Id, u => u.Name, ct);

        return rows.Select(r => new ContractDepartmentApprovalDto(
            r.Id,
            r.PhaseAtApproval,
            r.DepartmentId,
            r.DepartmentName,
            r.Stage,
            r.ApproverUserId,
            users.TryGetValue(r.ApproverUserId, out var n) ? n : null,
            r.ApproverRoleSnapshot,
            r.Comment,
            r.ApprovedAt,
            r.IsBypassed)).ToList();
    }
}
