using Microsoft.Extensions.DependencyInjection;
using SolutionErp.Application.PurchaseEvaluations;
using SolutionErp.Domain.Master;
using SolutionErp.Domain.PurchaseEvaluations;
using SolutionErp.Infrastructure.Tests.Common;

namespace SolutionErp.Infrastructure.Tests.Application;

// [PE D2 — Mig 58 multi-winner] TRANSLATION-SMOKE cho EF subquery
// PurchaseEvaluationListItemDto.WinnerSupplierNames — collection projection trong
// Select (from sw in db.PurchaseEvaluationSuppliers where ...IsWinner join Suppliers
// select sup.Name).ToList(). RỦI RO: collection-projection trong Select có thể KHÔNG
// translate trên 1 số provider → cần CHẠY THẬT trên SQLite provider để chốt.
//
// Target = ListApprovedPurchaseEvaluationsQuery (CreateContractFromEvaluationFeatures.cs:158)
// — sạch nhất (chỉ filter Phase==DaDuyet && ContractId==null, KHÔNG role-paging). Cùng
// subquery xuất hiện ở ListPurchaseEvaluationsQuery (paged) + inbox
// (PurchaseEvaluationFeatures.cs:627/724) → smoke 1 chỗ đủ chứng minh EF translate được.
//
// NẾU EF KHÔNG translate (runtime InvalidOperationException) → test FAIL = blocker
// REPORT em main (fallback 2-pass). Dùng SqliteDbFixture (KHÔNG cần Identity — query
// chỉ đọc, DrafterUserId LEFT-join Users nullable).
//
// [multi-NCC 2026-07-12 cardinality-change] Winner-truth chuyển whole-supplier IsWinner →
// per-(Detail×Supplier) Quote.IsSelected; NHƯNG Supplier.IsWinner GIỮ là cột PERSISTED
// (BE tự derive = Any quote IsSelected trong SelectWinner/UpsertQuote handler). WinnerSupplierNames
// projection ĐỌC THẲNG cột IsWinner đã persist (`where sw.IsWinner`) → KHÔNG đổi theo cardinality.
// Seed IsWinner trực tiếp = hợp lệ cho translation-smoke (không cần seed quote — projection không đọc quote).
public class PeListWinnerNamesProjectionTests
{
    private static (Project project, Supplier[] suppliers) SeedMasters(TestApplicationDbContext db, int supplierCount)
    {
        var project = new Project { Id = Guid.NewGuid(), Code = "FLOCK01", Name = "Dự án FLOCK 01" };
        db.Projects.Add(project);
        var suppliers = new Supplier[supplierCount];
        for (var i = 0; i < supplierCount; i++)
        {
            suppliers[i] = new Supplier
            {
                Id = Guid.NewGuid(),
                Code = $"NCC{i + 1}",
                Name = $"Nhà cung cấp {i + 1}",
                Type = SupplierType.NhaThauPhu,
            };
            db.Suppliers.Add(suppliers[i]);
        }
        return (project, suppliers);
    }

    // Seed 1 DaDuyet PE (ContractId=null để lọt ListApproved filter) + supplier-rows;
    // winnerIndexes = đơn vị IsWinner. Trả PE id.
    private static Guid SeedPe(
        TestApplicationDbContext db, Project project, Supplier[] suppliers,
        int[] winnerIndexes, string maPhieu)
    {
        var peId = Guid.NewGuid();
        var pe = new PurchaseEvaluation
        {
            Id = peId,
            MaPhieu = maPhieu,
            Type = PurchaseEvaluationType.DuyetNcc,
            Phase = PurchaseEvaluationPhase.DaDuyet,
            TenGoiThau = $"Gói {maPhieu}",
            ProjectId = project.Id,
            ContractId = null,                          // chưa gen HĐ → lọt picker
            DrafterUserId = null,
        };
        for (var i = 0; i < suppliers.Length; i++)
        {
            pe.Suppliers.Add(new PurchaseEvaluationSupplier
            {
                Id = Guid.NewGuid(),
                PurchaseEvaluationId = peId,
                SupplierId = suppliers[i].Id,
                Order = i,
                IsWinner = winnerIndexes.Contains(i),
            });
        }
        db.PurchaseEvaluations.Add(pe);
        return peId;
    }

    [Fact]
    public async Task ListApproved_WinnerSupplierNames_Translates_AndReturnsBothNames()
    {
        using var fix = new SqliteDbFixture();
        var db = fix.Db;

        var (project, suppliers) = SeedMasters(db, supplierCount: 3);
        // PE-A: 2 winner (idx 0 + 2 → "Nhà cung cấp 1" + "Nhà cung cấp 3"), idx 1 loser.
        var peTwo = SeedPe(db, project, suppliers, new[] { 0, 2 }, "PE-TWO");
        // PE-B: 1 winner (idx 1 → "Nhà cung cấp 2").
        var peOne = SeedPe(db, project, suppliers, new[] { 1 }, "PE-ONE");
        // PE-C: 0 winner.
        var peNone = SeedPe(db, project, suppliers, Array.Empty<int>(), "PE-NONE");
        await db.SaveChangesAsync(CancellationToken.None);

        var handler = new ListApprovedPurchaseEvaluationsQueryHandler(db);

        // Nếu subquery KHÔNG translate → dòng này ném InvalidOperationException = FAIL (blocker).
        var result = await handler.Handle(new ListApprovedPurchaseEvaluationsQuery(), CancellationToken.None);

        var two = result.Single(x => x.Id == peTwo);
        two.WinnerSupplierNames.Should().HaveCount(2);
        two.WinnerSupplierNames.Should().Contain("Nhà cung cấp 1");
        two.WinnerSupplierNames.Should().Contain("Nhà cung cấp 3");
        two.WinnerSupplierNames.Should().NotContain("Nhà cung cấp 2");   // loser excluded
        // orderby sup.Name → deterministic thứ tự ("1" < "3").
        two.WinnerSupplierNames.Should().Equal("Nhà cung cấp 1", "Nhà cung cấp 3");

        var one = result.Single(x => x.Id == peOne);
        one.WinnerSupplierNames.Should().ContainSingle().Which.Should().Be("Nhà cung cấp 2");

        var none = result.Single(x => x.Id == peNone);
        none.WinnerSupplierNames.Should().BeEmpty();
    }
}
