@page "/notes"
@rendermode InteractiveServer
@using Freman.Sample.Web.Data
@using Microsoft.EntityFrameworkCore
@using System.ComponentModel.DataAnnotations
@inject AppDbContext Db

<PageTitle>Notes</PageTitle>

<h1>Notes</h1>

<p class="text-muted">
    A tiny EF Core + PostgreSQL demo: type a note, save it, refresh, it’s still there.
</p>

@if (_isLoading)
{
    <div class="d-flex align-items-center gap-2 mb-3">
        <div class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></div>
        <span>Loading notes…</span>
    </div>
}

@if (!string.IsNullOrWhiteSpace(_error))
{
    <div class="alert alert-danger" role="alert">
        @_error
    </div>
}

<EditForm Model="_model" OnValidSubmit="SaveAsync">
    <DataAnnotationsValidator/>
    <ValidationSummary/>

    <div class="mb-3">
        <label class="form-label" for="noteText">New note</label>
        <input id="noteText"
               class="form-control"
               @bind-value="_model.Text"
               @bind-value:event="oninput"
               maxlength="500"
               disabled="@(_isSaving || _isLoading)"/>
        <div class="form-text">Max 500 characters.</div>
        <ValidationMessage For="@(() => _model.Text)"/>
    </div>

    <button class="btn btn-primary"
            type="submit"
            disabled="@(_isSaving || _isLoading || string.IsNullOrWhiteSpace(_model.Text))">
        @if (_isSaving)
        {
            <span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
            <span>Saving…</span>
        }
        else
        {
            <span>Save</span>
        }
    </button>

    <button class="btn btn-outline-secondary ms-2"
            type="button"
            @onclick="LoadAsync"
            disabled="@(_isSaving || _isLoading)">
        Refresh
    </button>
</EditForm>

@if (!string.IsNullOrWhiteSpace(_status))
{
    <div class="mt-3 alert alert-info">@_status</div>
}

<hr/>

<h2>Saved notes</h2>

@if (_notesList.Count == 0)
{
    <p><em>No notes yet.</em></p>
}
else
{
    <ul class="list-group">
        @foreach (var n in _notesList)
        {
            <li class="list-group-item d-flex justify-content-between align-items-center">
                <span>@n.Text</span>
                <small class="text-muted">@n.CreatedUtc.ToLocalTime()</small>
            </li>
        }
    </ul>
}

@code {

    private sealed class NewNoteModel
    {
        [Required(ErrorMessage = "Please enter some text.")]
        [StringLength(500, ErrorMessage = "Notes are limited to 500 characters.")]
        public string Text { get; set; } = "";
    }

    private readonly NewNoteModel _model = new();
    private bool _isSaving;
    private bool _isLoading;
    private string? _status;
    private string? _error;
    private List<Note> _notesList = [];

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

    private async Task LoadAsync()
    {
        _isLoading = true;
        _error = null;
        _status = null;

        try
        {
            _notesList = await Db.Notes
                .OrderByDescending(n => n.CreatedUtc)
                .Take(50)
                .ToListAsync();
        }
        catch (Exception ex)
        {
            _error = $"Load failed: {ex.Message}";
        }
        finally
        {
            _isLoading = false;
        }
    }

    private async Task SaveAsync()
    {
        _isSaving = true;
        _error = null;
        _status = null;

        var note = new Note
        {
            Text = _model.Text.Trim(),
            CreatedUtc = DateTime.UtcNow
        };

        // Optimistic UI: show it immediately
        _notesList.Insert(0, note);

        try
        {
            Db.Notes.Add(note);
            await Db.SaveChangesAsync();

            _model.Text = "";
            _status = "Saved!";
        }
        catch (Exception ex)
        {
            // Roll back optimistic insert
            _notesList.Remove(note);
            _error = $"Save failed: {ex.Message}";
        }
        finally
        {
            _isSaving = false;
        }
    }
}