@page "/utilisateur"
@page "/utilisateur.html"
@using System.ComponentModel.DataAnnotations
@using System.Net
@using System.Net.Http.Json
@using ChessCubing.App.Models.Users
@implements IDisposable
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject HttpClient Http

<PageTitle>ChessCubing Arena | Utilisateur</PageTitle>
<PageBody BodyClass="home-body" />

<div class="ambient ambient-left"></div>
<div class="ambient ambient-right"></div>

<div class="rules-shell">
    <header class="hero hero-home user-hero">
        <div class="hero-copy">
            <p class="eyebrow">Espace utilisateur</p>
            <h1>Gerer les donnees du site pour chaque joueur</h1>
            <p class="lead">
                Cette page relie le compte connecte a une fiche utilisateur stockee
                cote serveur en MySQL. L'authentification reste geree par Keycloak,
                mais les informations metier du site sont maintenant pretes pour des
                evolutions futures.
            </p>
            <div class="hero-actions">
                <a class="button secondary" href="application.html">Ouvrir l'application</a>
                <a class="button ghost" href="reglement.html">Voir les formats</a>
            </div>
        </div>

        <aside class="hero-preview">
            <div class="preview-card">
                <p class="micro-label">Persistance</p>
                <strong>Profil du site stocke en MySQL</strong>
                <p>
                    Username et email restent lies au compte authentifie, pendant que
                    le profil ChessCubing ajoute les donnees utiles au site.
                </p>
            </div>
            <div class="preview-banner">
                <span class="mini-chip">Etat du compte</span>
                <strong>@HeroStatusTitle</strong>
                <p>@HeroStatusDescription</p>
            </div>
        </aside>
    </header>

    <main class="rules-grid">
        @if (!IsAuthenticated)
        {
            <section class="panel panel-wide cta-panel">
                <div class="section-heading">
                    <div>
                        <p class="eyebrow">Connexion requise</p>
                        <h2>Connecte-toi pour gerer ton profil</h2>
                    </div>
                    <p class="section-copy">
                        Utilise les boutons Se connecter ou Creer un compte dans le menu
                        en haut de page, puis reviens ici pour enregistrer tes informations.
                    </p>
                </div>

                <div class="source-grid">
                    <a class="source-card" href="index.html">
                        <span class="micro-label">Accueil</span>
                        <strong>Retourner au site</strong>
                        <p>Revenir a la presentation generale de ChessCubing Arena.</p>
                    </a>
                    <a class="source-card" href="application.html">
                        <span class="micro-label">Application</span>
                        <strong>Ouvrir l'arbitrage</strong>
                        <p>Configurer un match pendant que le compte reste disponible dans le menu.</p>
                    </a>
                    <a class="source-card" href="reglement.html">
                        <span class="micro-label">Reglement</span>
                        <strong>Relire les formats</strong>
                        <p>Retrouver rapidement les differences entre Twice et Time.</p>
                    </a>
                </div>
            </section>
        }
        else if (IsLoading)
        {
            <section class="panel panel-wide">
                <p class="eyebrow">Chargement</p>
                <h2>Recuperation du profil utilisateur</h2>
                <p class="section-copy">Le serveur recharge les donnees enregistrees pour ce compte.</p>
            </section>
        }
        else if (!string.IsNullOrWhiteSpace(LoadError))
        {
            <section class="panel panel-wide">
                <p class="eyebrow">Serveur</p>
                <h2>Impossible de charger le profil</h2>
                <p class="profile-feedback error">@LoadError</p>
                <div class="hero-actions">
                    <button class="button secondary" type="button" @onclick="LoadProfileAsync">Reessayer</button>
                </div>
            </section>
        }
        else if (Profile is not null)
        {
            <section class="panel panel-half">
                <div class="section-heading">
                    <div>
                        <p class="eyebrow">Compte relie</p>
                        <h2>@Profile.DisplayName</h2>
                    </div>
                    <p class="section-copy">
                        Le compte connecte pilote l'identite, et cette page ajoute les donnees metier du site.
                    </p>
                </div>

                <div class="profile-meta-grid">
                    <article class="profile-meta-card">
                        <span class="micro-label">Username</span>
                        <strong>@Profile.Username</strong>
                    </article>
                    <article class="profile-meta-card">
                        <span class="micro-label">Email</span>
                        <strong>@(Profile.Email ?? "Non renseigne")</strong>
                    </article>
                    <article class="profile-meta-card">
                        <span class="micro-label">Cree le</span>
                        <strong>@FormatDate(Profile.CreatedUtc)</strong>
                    </article>
                    <article class="profile-meta-card">
                        <span class="micro-label">Mis a jour</span>
                        <strong>@FormatDate(Profile.UpdatedUtc)</strong>
                    </article>
                </div>
            </section>

            <section class="panel panel-half">
                <div class="section-heading">
                    <div>
                        <p class="eyebrow">Resume du profil</p>
                        <h2>Informations visibles pour le site</h2>
                    </div>
                </div>

                <div class="home-mini-grid two-columns profile-highlights">
                    <article class="mini-panel">
                        <span class="micro-label">Club</span>
                        <strong>@(Profile.Club ?? "A definir")</strong>
                    </article>
                    <article class="mini-panel">
                        <span class="micro-label">Ville</span>
                        <strong>@(Profile.City ?? "A definir")</strong>
                    </article>
                    <article class="mini-panel">
                        <span class="micro-label">Format prefere</span>
                        <strong>@(Profile.PreferredFormat ?? "A definir")</strong>
                    </article>
                    <article class="mini-panel">
                        <span class="micro-label">Cube favori</span>
                        <strong>@(Profile.FavoriteCube ?? "A definir")</strong>
                    </article>
                </div>

                <div class="callout profile-callout">
                    <span class="micro-label">Bio</span>
                    <p>@(Profile.Bio ?? "Aucune bio enregistree pour le moment.")</p>
                </div>
            </section>

            <section class="panel panel-wide">
                <div class="section-heading">
                    <div>
                        <p class="eyebrow">Edition</p>
                        <h2>Mettre a jour le profil du site</h2>
                    </div>
                    <p class="section-copy">
                        Les champs ci-dessous sont stockes dans MySQL et pourront ensuite
                        servir a enrichir les pages, les inscriptions ou les statistiques.
                    </p>
                </div>

                @if (!string.IsNullOrWhiteSpace(SaveError))
                {
                    <p class="profile-feedback error">@SaveError</p>
                }

                @if (!string.IsNullOrWhiteSpace(SaveMessage))
                {
                    <p class="profile-feedback success">@SaveMessage</p>
                }

                <EditForm Model="@Form" OnValidSubmit="SaveProfileAsync">
                    <DataAnnotationsValidator />

                    <div class="profile-form-grid">
                        <label class="field">
                            <span>Nom affiche</span>
                            <InputText @bind-Value="Form.DisplayName" />
                            <ValidationMessage For="@(() => Form.DisplayName)" />
                        </label>

                        <label class="field">
                            <span>Club</span>
                            <InputText @bind-Value="Form.Club" />
                            <ValidationMessage For="@(() => Form.Club)" />
                        </label>

                        <label class="field">
                            <span>Ville</span>
                            <InputText @bind-Value="Form.City" />
                            <ValidationMessage For="@(() => Form.City)" />
                        </label>

                        <label class="field">
                            <span>Format prefere</span>
                            <InputSelect @bind-Value="Form.PreferredFormat">
                                <option value="">Aucune preference</option>
                                <option value="Twice">Twice</option>
                                <option value="Time">Time</option>
                                <option value="Les deux">Les deux</option>
                            </InputSelect>
                            <ValidationMessage For="@(() => Form.PreferredFormat)" />
                        </label>

                        <label class="field span-2">
                            <span>Cube favori</span>
                            <InputText @bind-Value="Form.FavoriteCube" />
                            <ValidationMessage For="@(() => Form.FavoriteCube)" />
                        </label>

                        <label class="field span-2">
                            <span>Bio</span>
                            <InputTextArea @bind-Value="Form.Bio" />
                            <ValidationMessage For="@(() => Form.Bio)" />
                        </label>
                    </div>

                    <div class="profile-actions">
                        <button class="button secondary" type="submit" disabled="@IsSaving">
                            @(IsSaving ? "Enregistrement..." : "Enregistrer le profil")
                        </button>
                        <p class="section-copy">Les champs vides restent facultatifs et peuvent etre completes plus tard.</p>
                    </div>
                </EditForm>
            </section>
        }
    </main>
</div>

@code {
    private readonly UserProfileFormModel Form = new();

    private UserProfileResponse? Profile;
    private bool IsAuthenticated;
    private bool IsLoading = true;
    private bool IsSaving;
    private string? LoadError;
    private string? SaveError;
    private string? SaveMessage;

    private string HeroStatusTitle
        => !IsAuthenticated
            ? "Connexion requise"
            : IsLoading
                ? "Chargement du profil"
                : Profile?.DisplayName ?? "Profil utilisateur";

    private string HeroStatusDescription
        => !IsAuthenticated
            ? "Le profil du site apparait des qu'un compte joueur est connecte."
            : IsLoading
                ? "Le serveur verifie la fiche utilisateur associee a ce compte."
                : $"Compte lie a {Profile?.Username ?? "l'utilisateur connecte"} et stocke en base MySQL.";

    protected override async Task OnInitializedAsync()
    {
        AuthenticationStateProvider.AuthenticationStateChanged += HandleAuthenticationStateChanged;
        await LoadProfileAsync();
    }

    private void HandleAuthenticationStateChanged(Task<AuthenticationState> authenticationStateTask)
        => _ = InvokeAsync(LoadProfileAsync);

    private async Task LoadProfileAsync()
    {
        LoadError = null;
        SaveError = null;
        SaveMessage = null;
        IsLoading = true;

        try
        {
            var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            if (authState.User.Identity?.IsAuthenticated != true)
            {
                ResetProfileState();
                return;
            }

            IsAuthenticated = true;

            var response = await Http.GetAsync("api/users/me");
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                ResetProfileState();
                return;
            }

            if (!response.IsSuccessStatusCode)
            {
                LoadError = await ReadErrorAsync(response, "Le profil utilisateur n'a pas pu etre charge.");
                Profile = null;
                return;
            }

            Profile = await response.Content.ReadFromJsonAsync<UserProfileResponse>();
            if (Profile is null)
            {
                LoadError = "Le serveur a retourne une reponse vide.";
                return;
            }

            FillForm(Profile);
        }
        catch (HttpRequestException)
        {
            LoadError = "Le service utilisateur est temporairement indisponible.";
            Profile = null;
        }
        catch (TaskCanceledException)
        {
            LoadError = "La reponse du service utilisateur a pris trop de temps.";
            Profile = null;
        }
        finally
        {
            IsLoading = false;
            StateHasChanged();
        }
    }

    private async Task SaveProfileAsync()
    {
        if (IsSaving || !IsAuthenticated)
        {
            return;
        }

        IsSaving = true;
        SaveError = null;
        SaveMessage = null;

        try
        {
            var payload = new UpdateUserProfileRequest
            {
                DisplayName = Form.DisplayName,
                Club = Form.Club,
                City = Form.City,
                PreferredFormat = Form.PreferredFormat,
                FavoriteCube = Form.FavoriteCube,
                Bio = Form.Bio,
            };

            var response = await Http.PutAsJsonAsync("api/users/me", payload);
            if (!response.IsSuccessStatusCode)
            {
                SaveError = await ReadErrorAsync(response, "L'enregistrement du profil a echoue.");
                return;
            }

            Profile = await response.Content.ReadFromJsonAsync<UserProfileResponse>();
            if (Profile is null)
            {
                SaveError = "Le serveur a retourne une reponse vide apres la sauvegarde.";
                return;
            }

            FillForm(Profile);
            SaveMessage = "Le profil utilisateur a bien ete enregistre.";
        }
        catch (HttpRequestException)
        {
            SaveError = "Le service utilisateur est temporairement indisponible.";
        }
        catch (TaskCanceledException)
        {
            SaveError = "La sauvegarde a pris trop de temps.";
        }
        finally
        {
            IsSaving = false;
        }
    }

    private void ResetProfileState()
    {
        IsAuthenticated = false;
        Profile = null;
        Form.Reset();
    }

    private void FillForm(UserProfileResponse profile)
    {
        Form.DisplayName = profile.DisplayName;
        Form.Club = profile.Club;
        Form.City = profile.City;
        Form.PreferredFormat = profile.PreferredFormat;
        Form.FavoriteCube = profile.FavoriteCube;
        Form.Bio = profile.Bio;
    }

    private static async Task<string> ReadErrorAsync(HttpResponseMessage response, string fallbackMessage)
    {
        try
        {
            var error = await response.Content.ReadFromJsonAsync<ApiErrorMessage>();
            if (!string.IsNullOrWhiteSpace(error?.Message))
            {
                return error.Message;
            }
        }
        catch
        {
        }

        return response.StatusCode switch
        {
            HttpStatusCode.Unauthorized => "La session a expire. Reconnecte-toi puis recharge la page.",
            _ => fallbackMessage,
        };
    }

    private static string FormatDate(DateTime value)
        => value.ToLocalTime().ToString("dd MMM yyyy 'a' HH:mm", CultureInfo.GetCultureInfo("fr-FR"));

    public void Dispose()
        => AuthenticationStateProvider.AuthenticationStateChanged -= HandleAuthenticationStateChanged;

    private sealed class ApiErrorMessage
    {
        public string? Message { get; set; }
    }

    private sealed class UserProfileFormModel
    {
        [MaxLength(120, ErrorMessage = "Le nom affiche doit rester sous 120 caracteres.")]
        public string? DisplayName { get; set; }

        [MaxLength(120, ErrorMessage = "Le club doit rester sous 120 caracteres.")]
        public string? Club { get; set; }

        [MaxLength(120, ErrorMessage = "La ville doit rester sous 120 caracteres.")]
        public string? City { get; set; }

        [MaxLength(40, ErrorMessage = "Le format prefere doit rester sous 40 caracteres.")]
        public string? PreferredFormat { get; set; }

        [MaxLength(120, ErrorMessage = "Le cube favori doit rester sous 120 caracteres.")]
        public string? FavoriteCube { get; set; }

        [MaxLength(1200, ErrorMessage = "La bio doit rester sous 1200 caracteres.")]
        public string? Bio { get; set; }

        public void Reset()
        {
            DisplayName = string.Empty;
            Club = string.Empty;
            City = string.Empty;
            PreferredFormat = string.Empty;
            FavoriteCube = string.Empty;
            Bio = string.Empty;
        }
    }
}
