@page "/models"
@attribute [Authorize]
@inject IOllamaService OllamaService
@inject NavigationManager Navigation
@inject ILocalizationService Loc


<PageTitle>@Loc["page.title.models"]</PageTitle>

<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
    <h3>@Loc["models.heading"]</h3>
    <button @onclick="RefreshModels" disabled="@isLoading">@Loc["models.button.refresh"]</button>
</div>

@if (isLoading)
{
    <p>@Loc["models.status.loading"]</p>
}
else if (!string.IsNullOrEmpty(errorMessage))
{
    <div style="color: red; margin-bottom: 12px;">@errorMessage</div>
}
else
{
    <div class="model-list">
        @foreach (var model in localModels)
        {
            <div class="model-card">
                <div class="model-name">@model.Name</div>
                <div class="model-details">
                    @Loc["models.label.size"] @FormatSize(model.Size) |
                    @Loc["models.label.modified"] @model.ModifiedAt?.ToString("g")
                </div>
            </div>
        }
    </div>
}

<div style="margin-top: 24px; border-top: 1px solid var(--border-color); padding-top: 16px;">
    <h4 style="margin-bottom: 8px;">@Loc["models.pull.heading"]</h4>
    <div style="display: flex; gap: 8px; align-items: flex-end;">
        <div class="form-group" style="flex: 1; margin-bottom: 0;">
            <label for="pullModelName">@Loc["models.pull.label.name"]</label>
            <input id="pullModelName" @bind="modelToPull" placeholder="@Loc["models.pull.placeholder"]" />
        </div>
        <button @onclick="PullModel" disabled="@(isPulling || string.IsNullOrWhiteSpace(modelToPull))">
            @Loc["models.pull.button.download"]
        </button>
    </div>
    @if (isPulling)
    {
        <div style="margin-top: 8px;">
            <div class="progress-bar">
                <div class="progress-fill" style="width: @pullPercentDisplay"></div>
            </div>
            <div style="font-size: 12px; margin-top: 4px;">@pullStatus (@pullPercentDisplay)</div>
        </div>
    }
</div>

@if (pullResult != null)
{
    <div style="margin-top: 12px; padding: 8px; background: var(--card-bg); border: 1px solid var(--accent-color); font-size: 13px;">
        @pullResult
    </div>
}

@code {
    private List<LLM_Model> localModels = new();
    private bool isLoading;
    private string? errorMessage;
    private string modelToPull = string.Empty;
    private bool isPulling;
    private double pullProgress;
    private string pullStatus = string.Empty;
    private string? pullResult;
    private string pullPercentDisplay => $"{pullProgress:F0}%";

    protected override async Task OnInitializedAsync()
    {
        await RefreshModels();
    }

    private async Task RefreshModels()
    {
        isLoading = true;
        errorMessage = null;

        try
        {
            var models = await OllamaService.GetLocalModelsAsync();
            localModels = models.ToList();
        }
        catch (Exception ex)
        {
            errorMessage = $"{Loc["models.error.loading"]} {ex.Message}";
            localModels = new();
        }
        finally
        {
            isLoading = false;
        }
    }

    private async Task PullModel()
    {
        if (string.IsNullOrWhiteSpace(modelToPull)) return;

        isPulling = true;
        pullProgress = 0;
        pullStatus = Loc["models.pull.status.starting"];
        pullResult = null;

        try
        {
            var progress = new Progress<string>(status =>
            {
                pullStatus = status;
                InvokeAsync(StateHasChanged);
            });

            await OllamaService.PullModelAsync(modelToPull, progress);
            pullResult = $"{Loc["models.pull.status.model"]} '{modelToPull}' {Loc["models.pull.status.success"]}";
            modelToPull = string.Empty;
            await RefreshModels();
        }
        catch (Exception ex)
        {
            pullResult = $"{Loc["common.error"]} {ex.Message}";
        }
        finally
        {
            isPulling = false;
        }
    }

    private static string FormatSize(long? bytes)
    {
        if (!bytes.HasValue) return "---";
        if (bytes < 1024 * 1024) return $"{bytes / 1024.0:F1} KB";
        if (bytes < 1024 * 1024 * 1024) return $"{bytes / (1024.0 * 1024):F1} MB";
        return $"{bytes / (1024.0 * 1024 * 1024):F1} GB";
    }
}
