using Bunit;
using Microsoft.AspNetCore.Components;
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;

namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;

/// <summary>
/// bUnit tests for the <see cref="OffsetPager"/> reusable pagination bar (T35a).
/// The component is purely presentational — it emits <c>PageChanged</c> callbacks
/// and renders disabled states; the host page owns page-number and query state.
/// </summary>
public class OffsetPagerTests : BunitContext
{
    // ── PrevDisabled_OnFirstPage ──────────────────────────────────────────────

    [Fact]
    public void PrevDisabled_OnFirstPage()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 1)
            .Add(p => p.HasNextPage, true));

        var prev = cut.Find("[data-test='pager-prev']");

        Assert.NotNull(prev.GetAttribute("disabled"));
    }

    // ── NextDisabled_WhenNoNextPage ───────────────────────────────────────────

    [Fact]
    public void NextDisabled_WhenNoNextPage()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 3)
            .Add(p => p.HasNextPage, false));

        var next = cut.Find("[data-test='pager-next']");

        Assert.NotNull(next.GetAttribute("disabled"));
    }

    // ── Next_Click_EmitsPagePlusOne ───────────────────────────────────────────

    [Fact]
    public void Next_Click_EmitsPagePlusOne()
    {
        int? emitted = null;
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 2)
            .Add(p => p.HasNextPage, true)
            .Add(p => p.PageChanged,
                EventCallback.Factory.Create<int>(this, v => emitted = v)));

        cut.Find("[data-test='pager-next']").Click();

        Assert.Equal(3, emitted);
    }

    // ── Prev_Click_EmitsPageMinusOne ─────────────────────────────────────────

    [Fact]
    public void Prev_Click_EmitsPageMinusOne()
    {
        int? emitted = null;
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 2)
            .Add(p => p.HasNextPage, false)
            .Add(p => p.PageChanged,
                EventCallback.Factory.Create<int>(this, v => emitted = v)));

        cut.Find("[data-test='pager-prev']").Click();

        Assert.Equal(1, emitted);
    }

    // ── Summary_RendersPageOfTotal ────────────────────────────────────────────

    [Fact]
    public void Summary_RendersPageOfTotal()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 2)
            .Add(p => p.PageSize, 50)
            .Add(p => p.TotalCount, 230)
            .Add(p => p.HasNextPage, true));

        var summary = cut.Find("[data-test='pager-summary']");

        Assert.Contains("Page 2 of 5", summary.TextContent);
        Assert.Contains("230 total", summary.TextContent);
    }

    // ── HideWhenSinglePage_HidesBar_OnSinglePage ──────────────────────────────

    [Fact]
    public void HideWhenSinglePage_HidesBar_OnSinglePage()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 1)
            .Add(p => p.PageSize, 50)
            .Add(p => p.TotalCount, 12)
            .Add(p => p.HasNextPage, false)
            .Add(p => p.HideWhenSinglePage, true));

        Assert.Empty(cut.FindAll("[data-test='pager-prev']"));
        Assert.Empty(cut.FindAll("[data-test='pager-next']"));
        Assert.Empty(cut.FindAll("[data-test='pager-summary']"));
    }

    // ── HideWhenSinglePage_HidesBar_OnEmptyResult ─────────────────────────────

    [Fact]
    public void HideWhenSinglePage_HidesBar_OnEmptyResult()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 1)
            .Add(p => p.PageSize, 50)
            .Add(p => p.TotalCount, 0)
            .Add(p => p.HasNextPage, false)
            .Add(p => p.HideWhenSinglePage, true));

        Assert.Empty(cut.FindAll("[data-test='pager-summary']"));
    }

    // ── HideWhenSinglePage_ShowsBar_WhenMultiplePages ─────────────────────────

    [Fact]
    public void HideWhenSinglePage_ShowsBar_WhenMultiplePages()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 1)
            .Add(p => p.PageSize, 50)
            .Add(p => p.TotalCount, 120)
            .Add(p => p.HasNextPage, true)
            .Add(p => p.HideWhenSinglePage, true));

        Assert.Contains("Page 1 of 3", cut.Find("[data-test='pager-summary']").TextContent);
    }

    // ── HideWhenSinglePage_ShowsBar_WhenTotalCountUnknown ─────────────────────
    // TotalCount is null (the host cannot count), so single-page-ness is not
    // provable — the bar must stay so the user can still reach a further page.

    [Fact]
    public void HideWhenSinglePage_ShowsBar_WhenTotalCountUnknown()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 1)
            .Add(p => p.PageSize, 50)
            .Add(p => p.HasNextPage, false)
            .Add(p => p.HideWhenSinglePage, true));

        Assert.NotNull(cut.Find("[data-test='pager-summary']"));
    }

    // ── HideWhenSinglePage_Off_KeepsBarVisible_OnSinglePage ───────────────────
    // Default (opt-out) behaviour: consumers that use the summary as their only
    // "N total" readout keep the bar on a single page.

    [Fact]
    public void HideWhenSinglePage_Off_KeepsBarVisible_OnSinglePage()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 1)
            .Add(p => p.PageSize, 50)
            .Add(p => p.TotalCount, 3)
            .Add(p => p.HasNextPage, false));

        Assert.Contains("3 total", cut.Find("[data-test='pager-summary']").TextContent);
    }

    // ── BothDisabled_WhenDisabled ─────────────────────────────────────────────

    [Fact]
    public void BothDisabled_WhenDisabled()
    {
        var cut = Render<OffsetPager>(ps => ps
            .Add(p => p.Page, 3)
            .Add(p => p.HasNextPage, true)
            .Add(p => p.Disabled, true));

        var prev = cut.Find("[data-test='pager-prev']");
        var next = cut.Find("[data-test='pager-next']");

        Assert.NotNull(prev.GetAttribute("disabled"));
        Assert.NotNull(next.GetAttribute("disabled"));
    }
}
