@namespace Lumeo

@{
    var status = GetStatus();
    var isHorizontal = Context?.Orientation != Steps.StepsOrientation.Vertical;
    var isError = Status == StepsItemStatus.Error && status == StepStatus.Current;
}

@if (isHorizontal)
{
    <div class="@HorizontalCssClass" role="listitem" @attributes="AdditionalAttributes">
        <div class="flex flex-col items-center">
            <button type="button"
                    class="@GetIndicatorClasses(status, isError)"
                    disabled="@(!IsClickable)"
                    @onclick="HandleClick">
                @if (IconContent is not null)
                {
                    @IconContent
                }
                else if (isError)
                {
                    <Blazicon Svg="Lucide.X" class="h-4 w-4" />
                }
                else if (status == StepStatus.Completed)
                {
                    <Blazicon Svg="Lucide.Check" class="h-4 w-4" />
                }
                else
                {
                    <span>@(_index + 1)</span>
                }
            </button>
            <div class="mt-2 text-center">
                @if (!string.IsNullOrEmpty(Title))
                {
                    <p class="@GetTitleClasses(status, isError)">@Title</p>
                }
                @if (!string.IsNullOrEmpty(Description))
                {
                    <p class="text-xs text-muted-foreground">@Description</p>
                }
            </div>
        </div>
        <div class="mx-2 mt-4 h-px flex-1 @GetLineClasses(status)" @key="@($"line-h-{_index}-{status}")"></div>
    </div>
}
else
{
    <div class="@VerticalCssClass" role="listitem" @attributes="AdditionalAttributes">
        <div class="flex flex-col items-center">
            <button type="button"
                    class="@GetIndicatorClasses(status, isError)"
                    disabled="@(!IsClickable)"
                    @onclick="HandleClick">
                @if (IconContent is not null)
                {
                    @IconContent
                }
                else if (isError)
                {
                    <Blazicon Svg="Lucide.X" class="h-4 w-4" />
                }
                else if (status == StepStatus.Completed)
                {
                    <Blazicon Svg="Lucide.Check" class="h-4 w-4" />
                }
                else
                {
                    <span>@(_index + 1)</span>
                }
            </button>
            <div class="my-1 w-px flex-1 @GetLineClasses(status)" @key="@($"line-v-{_index}-{status}")"></div>
        </div>
        <div class="ml-3 pb-6">
            @if (!string.IsNullOrEmpty(Title))
            {
                <p class="@GetTitleClasses(status, isError)">@Title</p>
            }
            @if (!string.IsNullOrEmpty(Description))
            {
                <p class="text-xs text-muted-foreground">@Description</p>
            }
        </div>
    </div>
}

@code {
    [CascadingParameter] public Steps.StepsContext? Context { get; set; }
    [Parameter] public string? Title { get; set; }
    [Parameter] public string? Description { get; set; }
    [Parameter] public StepsItemStatus Status { get; set; } = StepsItemStatus.Default;

    /// <summary>Icon slot. Named <c>IconContent</c> to avoid shadowing the <c>&lt;Icon&gt;</c> component.</summary>
    [Parameter] public RenderFragment? IconContent { get; set; }

    [Parameter] public string? Class { get; set; }
    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }

    private int _index;

    protected override void OnParametersSet()
    {
        if (Context?.Parent is not null)
        {
            _index = Context.Parent.GetNextIndex();
        }
    }

    private bool IsClickable => Context?.Clickable == true;
    private bool IsAnimated => Context?.Animated == true;

    private StepStatus GetStatus()
    {
        var current = Context?.CurrentStep ?? 0;
        if (_index < current) return StepStatus.Completed;
        if (_index == current) return StepStatus.Current;
        return StepStatus.Future;
    }

    private string GetIndicatorClasses(StepStatus status, bool isError)
    {
        var baseClasses = isError
            ? "flex h-8 w-8 shrink-0 items-center justify-center rounded-full border-2 border-destructive bg-background text-destructive"
            : status switch
            {
                StepStatus.Completed => "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground",
                StepStatus.Current => "flex h-8 w-8 shrink-0 items-center justify-center rounded-full border-2 border-primary bg-background text-sm font-semibold text-primary",
                _ => "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground"
            };

        // Only the Current (active) indicator pulses, and only when not in an error state.
        if (IsAnimated && status == StepStatus.Current && !isError)
        {
            baseClasses += " lumeo-steps-pulse";
        }

        baseClasses += IsClickable
            ? " cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
            : " cursor-default";

        return baseClasses;
    }

    private string GetTitleClasses(StepStatus status, bool isError) =>
        isError
            ? "text-sm font-semibold text-destructive"
            : status switch
            {
                StepStatus.Completed => "text-sm font-medium text-foreground",
                StepStatus.Current => "text-sm font-semibold text-foreground",
                _ => "text-sm text-muted-foreground"
            };

    private string GetLineClasses(StepStatus status)
    {
        var defaultColor = status switch
        {
            StepStatus.Completed => "bg-primary",
            _ => "bg-border"
        };

        if (!IsAnimated)
        {
            return defaultColor;
        }

        var isVertical = Context?.Orientation == Steps.StepsOrientation.Vertical;
        var isBackward = Context?.Direction == Steps.StepsDirection.Backward;

        // Only animate the SINGLE connector that just transitioned state.
        // Forward: connector at _index becomes completed when CurrentStep advances past it.
        // Backward: connector at _index == new CurrentStep was just un-completed.
        var current = Context?.CurrentStep ?? 0;

        // Forward draw-in: this connector is now completed AND was just lit up
        // (i.e. its index equals the new-current-1 — the one we just crossed).
        if (!isBackward && status == StepStatus.Completed && _index == current - 1)
        {
            return $"{defaultColor} " + (isVertical ? "lumeo-steps-line-draw-y" : "lumeo-steps-line-draw-x");
        }

        // Backward unwind: connector at new CurrentStep was completed, now pending.
        // Force bg-primary during the animation so the user sees a coloured
        // line retracting (otherwise it's a bg-border grey line shrinking
        // — invisible against the muted background).
        if (isBackward && status != StepStatus.Completed && _index == current)
        {
            return "bg-primary " + (isVertical ? "lumeo-steps-line-unwind-y" : "lumeo-steps-line-unwind-x");
        }

        return defaultColor;
    }

    private async Task HandleClick()
    {
        if (Context is not null && IsClickable)
        {
            await Context.OnStepClick.InvokeAsync(_index);
        }
    }

    private string HorizontalCssClass => $"flex flex-1 flex-row last:flex-initial {Class}".Trim();
    private string VerticalCssClass => $"flex flex-row {Class}".Trim();

    private enum StepStatus { Completed, Current, Future }

    public enum StepsItemStatus { Default, Error }
}
