@using AIStudio.Provider
@using AIStudio.Provider.HuggingFace
@using AIStudio.Provider.SelfHosted
@inherits MSGComponentBase
<MudDialog>
    <DialogContent>
        <MudForm @ref="@this.form" @bind-IsValid="@this.dataIsValid" @bind-Errors="@this.dataIssues">
            <MudStack Row="@true" AlignItems="AlignItems.Center">
                @* ReSharper disable once CSharpWarnings::CS8974 *@
                <MudSelect T="LLMProviders"
                           Value="@this.DataLLMProvider"
                           ValueChanged="@this.OnProviderChanged"
                           Label="@T("Provider")"
                           Class="mb-3"
                           OpenIcon="@Icons.Material.Filled.AccountBalance"
                           AdornmentColor="Color.Info"
                           Adornment="Adornment.Start"
                           Validation="@this.providerValidation.ValidatingProvider">
                    @foreach (LLMProviders provider in Enum.GetValues(typeof(LLMProviders)))
                    {
                        <MudSelectItem Value="@provider">
                            @provider.ToName()
                        </MudSelectItem>
                    }
                </MudSelect>
                <MudButton Disabled="@(!this.DataLLMProvider.ShowRegisterButton())" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.OpenInBrowser" Href="@this.DataLLMProvider.GetCreationURL()" Target="_blank">
                    @T("Create account")
                </MudButton>
            </MudStack>
            
            @if (this.DataLLMProvider.IsAPIKeyNeeded(this.DataHost))
            {
                <SecretInputField Secret="@this.dataAPIKey" SecretChanged="@this.OnAPIKeyChanged" Label="@this.APIKeyText" Validation="@this.providerValidation.ValidatingAPIKey"/>
            }

            @if (this.DataLLMProvider.IsHostnameNeeded())
            {
                <MudTextField
                    T="string"
                    @bind-Text="@this.DataHostname"
                    Label="@T("Hostname")"
                    Class="mb-3"
                    Adornment="Adornment.Start"
                    AdornmentIcon="@Icons.Material.Filled.Dns"
                    AdornmentColor="Color.Info"
                    Validation="@this.providerValidation.ValidatingHostname"
                    UserAttributes="@SPELLCHECK_ATTRIBUTES"/>
            }

            @if (this.DataLLMProvider.IsHostNeeded())
            {
                <MudSelect T="Host" Value="@this.DataHost" ValueChanged="@this.OnHostChanged" Label="@T("Host")" Class="mb-3" OpenIcon="@Icons.Material.Filled.ExpandMore" AdornmentColor="Color.Info" Adornment="Adornment.Start" Validation="@this.providerValidation.ValidatingHost">
                    @foreach (Host host in Enum.GetValues(typeof(Host)))
                    {
                        @if (host.IsChatSupported())
                        {
                            <MudSelectItem Value="@host">
                                @host.Name()
                            </MudSelectItem>
                        }
                    }
                </MudSelect>
            }

            @if (this.DataLLMProvider.IsHFInstanceProviderNeeded())
            {
                <MudSelect @bind-Value="@this.HFInferenceProviderId" Label="@T("Hugging Face Inference Provider")" Class="mb-3" OpenIcon="@Icons.Material.Filled.Dns" AdornmentColor="Color.Info" Adornment="Adornment.Start" Validation="@this.providerValidation.ValidatingHFInstanceProvider">
                    @foreach (HFInferenceProvider inferenceProvider in Enum.GetValues(typeof(HFInferenceProvider)))
                    {
                        <MudSelectItem Value="@inferenceProvider">
                            @inferenceProvider.ToName()
                        </MudSelectItem>
                    }             
                </MudSelect>
                @* ReSharper disable Asp.Entity *@
                <MudJustifiedText Class="mb-3">
                    Please double-check if your model name matches the curl specifications provided by the inference provider. If it doesn't, you might get a <b>Not Found</b> error when trying to use the model. Here's a <MudLink Href="https://huggingface.co/meta-llama/Llama-3.1-8B-Instruct?inference_api=true&inference_provider=novita&language=sh" Target="_blank">curl example</MudLink>.
                </MudJustifiedText>
                @* ReSharper restore Asp.Entity *@
            }       

            @if (!this.IsLLMModelSelectionHidden)
            {
                <MudField FullWidth="true" Label="@T("Model selection")" Variant="Variant.Outlined" Class="mb-3">
                    <MudStack Row="@true" AlignItems="AlignItems.Center" StretchItems="StretchItems.End">
                        @if (this.DataLLMProvider.IsLLMModelProvidedManually())
                        {
                            <MudButton Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.OpenInBrowser" Href="@this.DataLLMProvider.GetModelsOverviewURL(this.HFInferenceProviderId)" Target="_blank">
                                @T("Show available models")
                            </MudButton>
                            <MudTextField
                                T="string"
                                @bind-Text="@this.dataManuallyModel"
                                Label="@T("Model")"
                                Adornment="Adornment.Start"
                                AdornmentIcon="@Icons.Material.Filled.FaceRetouchingNatural"
                                AdornmentColor="Color.Info"
                                Validation="@this.ValidateManuallyModel"
                                UserAttributes="@SPELLCHECK_ATTRIBUTES"
                                HelperText="@T("Currently, we cannot query the models for the selected provider and/or host. Therefore, please enter the model name manually.")"
                            />
                        }
                        else
                        {
                            <MudButton Disabled="@(!this.DataLLMProvider.CanLoadModels(this.DataHost, this.dataAPIKey))" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Refresh" OnClick="@this.ReloadModels">
                                @T("Load models")
                            </MudButton>
                            @if(this.availableModels.Count is 0)
                            {
                                <MudText Typo="Typo.body1">
                                    @T("No models loaded or available.")
                                </MudText>
                            }
                            else
                            {
                                <MudSelect T="Provider.Model"
                                           Value="@this.DataModel"
                                           ValueChanged="@(async model => await this.OnModelChanged(model))"
                                           OpenIcon="@Icons.Material.Filled.FaceRetouchingNatural" AdornmentColor="Color.Info"
                                           Adornment="Adornment.Start" Validation="@this.providerValidation.ValidatingModel">
                                    @foreach (var model in this.availableModels)
                                    {
                                        <MudSelectItem Value="@model">
                                            @model
                                        </MudSelectItem>
                                    }
                                </MudSelect>
                            }
                        }
                    </MudStack>
                    @if (!string.IsNullOrWhiteSpace(this.dataLoadingModelsIssue))
                    {
                        <MudAlert Severity="Severity.Error" Class="mt-3">
                            @this.dataLoadingModelsIssue
                        </MudAlert>
                    }
                </MudField>
            }
            else
            {
                <MudField FullWidth="true" Label="@T("Model selection")" Variant="Variant.Outlined" Class="mb-3">
                    <MudText Typo="Typo.body1">
                        @T("This host uses the model configured at the provider level. No model selection is available.")
                    </MudText>
                </MudField>
            }

            @* ReSharper disable once CSharpWarnings::CS8974 *@
            <MudTextField
                T="string"
                @bind-Text="@this.DataInstanceName"
                Label="@T("Instance Name")"
                Class="mb-3"
                MaxLength="40"
                Counter="40"
                Immediate="@true"
                Adornment="Adornment.Start"
                AdornmentIcon="@Icons.Material.Filled.Lightbulb"
                AdornmentColor="Color.Info"
                Validation="@this.providerValidation.ValidatingInstanceName"
                UserAttributes="@SPELLCHECK_ATTRIBUTES"
            />
            
            <MudStack>
                <MudButton OnClick="@this.ToggleExpertSettings">
                    @(this.showExpertSettings ? T("Hide Expert Settings") : T("Show Expert Settings"))
                </MudButton>
                <MudDivider />
                <MudCollapse Expanded="@this.showExpertSettings" Class="@this.GetExpertStyles">
                    <MudAlert Severity="Severity.Warning" Class="mb-4">
                        @T("Please be careful: wrong expert settings can break model usage, disable supported features, or make unsupported features appear available.")
                    </MudAlert>
                    <MudText Typo="Typo.subtitle2" Class="mb-2">
                        @T("Override Model Capabilities")
                    </MudText>
                    <MudJustifiedText Typo="Typo.body2" Class="mb-4">
                        @T("Stored default model capabilities may not reflect its full range. Override them here if needed.")
                    </MudJustifiedText>
                    <MudStack Class="mb-4" Spacing="2">
                        @foreach (var capability in SWITCH_CAPABILITY_OVERRIDES)
                        {
                            <MudPaper Outlined="@true" Class="pa-3">
                                <MudStack Row="@true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Wrap="Wrap.Wrap">
                                    <MudStack Spacing="0">
                                        <MudText Typo="Typo.body2">
                                            @this.GetCapabilityOverrideLabel(capability)
                                        </MudText>
                                        <MudText Typo="Typo.caption" Color="Color.Secondary">
                                            @this.GetCapabilityEffectiveLabel(capability)
                                        </MudText>
                                    </MudStack>
                                    <MudStack Row="@true" AlignItems="AlignItems.Center" Spacing="2">
                                        <MudSwitch T="bool"
                                                   Value="@this.IsCapabilityEnabled(capability)"
                                                   ValueChanged="@(value => this.OnCapabilitySwitchChanged(capability, value))"
                                                   Color="Color.Primary" />
                                        <MudButton Variant="Variant.Outlined"
                                                   Color="Color.Default"
                                                   Size="Size.Small"
                                                   StartIcon="@Icons.Material.Filled.RestartAlt"
                                                   Disabled="@(!this.HasCapabilityOverride(capability))"
                                                   OnClick="@(() => this.ResetCapabilityOverride(capability))">
                                            @T("Reset")
                                        </MudButton>
                                    </MudStack>
                                </MudStack>
                            </MudPaper>
                        }
                        <MudPaper Outlined="@true" Class="pa-3">
                            <MudSelect T="ReasoningOverrideMode"
                                       Value="@this.GetReasoningOverrideMode()"
                                       ValueChanged="@this.SetReasoningOverrideMode"
                                       Label="@T("Reasoning (thinking) behavior")"
                                       HelperText="@this.GetReasoningOverrideModeDescription(this.GetReasoningOverrideMode())"
                                       Variant="Variant.Outlined"
                                       Margin="Margin.Dense"
                                       OpenIcon="@Icons.Material.Filled.Psychology"
                                       AdornmentColor="Color.Info"
                                       Adornment="Adornment.Start">
                                @foreach (var mode in REASONING_OVERRIDE_MODES)
                                {
                                    <MudSelectItem Value="@mode">
                                        @this.GetReasoningOverrideModeLabel(mode)
                                    </MudSelectItem>
                                }
                            </MudSelect>
                        </MudPaper>
                    </MudStack>
                    <MudJustifiedText Typo="Typo.body2" Class="mb-4">
                        @string.Format(T("The current model uses the {0}."), this.GetCurrentModelApiLabel())
                    </MudJustifiedText>
                    <MudTextField T="string" Label=@T("Additional API parameters") Variant="Variant.Outlined" Lines="4" AutoGrow="true" MaxLines="10" HelperText=@T("""Add the parameters in proper JSON formatting, e.g., "temperature": 0.5. Remove trailing commas. The usual surrounding curly brackets {} must not be used, though.""") Placeholder="@GetPlaceholderExpertSettings" @bind-Value="@this.AdditionalJsonApiParameters" Immediate="true" Validation="@this.ValidateAdditionalJsonApiParameters" OnBlur="@this.OnInputChangeExpertSettings"/>
                </MudCollapse>
            </MudStack>
        </MudForm>
        <Issues IssuesData="@this.dataIssues"/>
    </DialogContent>
    <DialogActions>
        <MudButton OnClick="@this.Cancel" Variant="Variant.Filled">
            @T("Cancel")
        </MudButton>
        <MudButton OnClick="@this.Store" Variant="Variant.Filled" Color="Color.Primary">
            @if(this.IsEditing)
            {
                @T("Update")
            }
            else
            {
                @T("Add")
            }
        </MudButton>
    </DialogActions>
</MudDialog>
