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

namespace SolutionErp.Application.PurchaseEvaluations;

// 2-stage department approval list (Phase 9 — Migration 16).
// Query để FE hiển thị progress: phase nào × dept nào đã review/confirm.
//
// FE Workflow Panel sẽ render dạng timeline:
// - Phase ChoPurchasing (PRO):
//   - Stage Review: long.chau (NV) — 14:30
//   - Stage Confirm: tra.bui (TPB) — 14:35 → unlock transition
//
// Insertion + Block logic ở PurchaseEvaluationWorkflowService.TransitionAsync.

public record ListPeDepartmentApprovalsQuery(Guid PurchaseEvaluationId) : IRequest<List<PeDepartmentApprovalDto>>;

public record PeDepartmentApprovalDto(
    Guid Id,
    int PhaseAtApproval,
    Guid DepartmentId,
    string? DepartmentName,
    ApprovalStage Stage,
    Guid ApproverUserId,
    string? ApproverName,
    string? ApproverRoleSnapshot,    // "TPB" / "NV" / "NV(bypass)"
    string? Comment,
    DateTime ApprovedAt,
    bool IsBypassed);

public class ListPeDepartmentApprovalsQueryHandler(IApplicationDbContext db)
    : IRequestHandler<ListPeDepartmentApprovalsQuery, List<PeDepartmentApprovalDto>>
{
    public async Task<List<PeDepartmentApprovalDto>> Handle(
        ListPeDepartmentApprovalsQuery request, CancellationToken ct)
    {
        // Join với Departments để lấy Name. Join với Users để lấy ApproverName denorm.
        var rows = await (
            from a in db.PurchaseEvaluationDepartmentApprovals.AsNoTracking()
            join d in db.Departments.AsNoTracking() on a.DepartmentId equals d.Id into deptJoin
            from d in deptJoin.DefaultIfEmpty()
            where a.PurchaseEvaluationId == request.PurchaseEvaluationId
            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);

        // Lookup approver names (separate query to avoid Identity user join complexity)
        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 PeDepartmentApprovalDto(
            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();
    }
}
