@using EntKube.Web.Data
@using EntKube.Web.Services
@inject VaultService VaultService
@inject TenantService TenantService
@using EntKube.Web.Components.Pages.Shared

@* ═══════════════════════════════════════════════════════════════════
   App Secrets — customer portal view for managing vault secrets
   scoped to a single app.

   Access rules:
     Viewer+  — list secret names, reveal values on demand
     Admin    — add / update / delete secrets, configure K8s sync
   ═══════════════════════════════════════════════════════════════════ *@

<div class="d-flex align-items-center mb-3">
    <i class="bi bi-shield-lock fs-4 me-2 text-primary"></i>
    <div>
        <h5 class="mb-0">Secrets — @App.Name</h5>
        <small class="text-muted">
            Application secrets stored with AES-256-GCM envelope encryption.
            Values are never transmitted in plain text.
        </small>
    </div>
</div>

@if (!vaultInitialized)
{
    <div class="alert alert-warning py-2 small">
        <i class="bi bi-shield-exclamation me-1"></i>
        No vault has been set up for this tenant. Ask your platform administrator to initialize it.
    </div>
}
else
{
    @* ── Add Secret form (Admin only) ── *@
    @if (AccessRole >= CustomerAccessRole.Admin)
    {
        <div class="card shadow-sm mb-3">
            <div class="card-header bg-white py-2">
                <i class="bi bi-plus-circle me-1 text-primary"></i><strong>Add / Update Secret</strong>
            </div>
            <div class="card-body">
                <div class="row g-2 align-items-end">
                    <div class="col-md-4">
                        <label class="form-label small">Name</label>
                        <input type="text" class="form-control form-control-sm"
                               placeholder="e.g. API_KEY, DB_PASSWORD"
                               @bind="newSecretName" @bind:event="oninput" />
                    </div>
                    <div class="col-md-5">
                        <label class="form-label small">Value</label>
                        <input type="password" class="form-control form-control-sm"
                               placeholder="Secret value"
                               @bind="newSecretValue" @bind:event="oninput" />
                    </div>
                    <div class="col-auto">
                        <button class="btn btn-sm btn-primary" @onclick="AddSecret"
                                disabled="@(string.IsNullOrWhiteSpace(newSecretName) || string.IsNullOrWhiteSpace(newSecretValue) || saving)">
                            @if (saving) { <span class="spinner-border spinner-border-sm me-1"></span> }
                            <i class="bi bi-plus-lg me-1"></i>Set Secret
                        </button>
                    </div>
                </div>
                <div class="form-text">
                    If a secret with this name already exists it will be updated in place.
                </div>
                @if (errorMessage is not null)
                {
                    <div class="alert alert-danger py-1 small mt-2 mb-0">
                        <i class="bi bi-exclamation-triangle me-1"></i>@errorMessage
                    </div>
                }
                @if (successMessage is not null)
                {
                    <div class="alert alert-success py-1 small mt-2 mb-0">
                        <i class="bi bi-check-circle me-1"></i>@successMessage
                    </div>
                }
            </div>
        </div>
    }

    @* ── Secrets list ── *@
    <div class="card shadow-sm">
        <div class="card-header bg-white py-2 d-flex align-items-center justify-content-between">
            <div>
                <i class="bi bi-lock me-2 text-primary"></i>
                <strong>Stored Secrets</strong>
                @if (secrets is not null)
                {
                    <span class="badge bg-secondary ms-1">@secrets.Count</span>
                }
            </div>
            @if (AccessRole >= CustomerAccessRole.Admin && secrets?.Any(s => s.SyncToKubernetes) == true)
            {
                <button class="btn btn-sm btn-outline-success" @onclick="SyncAllToKubernetes" disabled="@syncingSecrets">
                    @if (syncingSecrets) { <span class="spinner-border spinner-border-sm me-1"></span> }
                    else { <i class="bi bi-cloud-arrow-up me-1"></i> }
                    Sync All to K8s
                </button>
            }
        </div>
        <div class="card-body p-0">
            @if (secrets is null)
            {
                <div class="text-center py-4">
                    <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                </div>
            }
            else if (secrets.Count == 0)
            {
                <div class="text-center py-5">
                    <i class="bi bi-lock text-muted" style="font-size: 2rem;"></i>
                    <p class="text-muted small mt-2 mb-0">No secrets stored for this app yet.</p>
                    @if (AccessRole >= CustomerAccessRole.Admin)
                    {
                        <p class="text-muted small mb-0">Use the form above to add one.</p>
                    }
                </div>
            }
            else
            {
                <div class="table-responsive">
                    <table class="table table-hover align-middle mb-0">
                        <thead class="table-light">
                            <tr>
                                <th>Name</th>
                                <th>K8s Sync</th>
                                <th>K8s Secret</th>
                                <th>Namespace</th>
                                <th>Updated</th>
                                <th class="text-end" style="min-width: 120px;">Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            @foreach (VaultSecret secret in secrets)
                            {
                                <tr>
                                    <td><code>@secret.Name</code></td>
                                    <td>
                                        @if (secret.SyncToKubernetes)
                                        {
                                            <span class="badge bg-success"><i class="bi bi-cloud-check me-1"></i>Enabled</span>
                                        }
                                        else
                                        {
                                            <span class="badge bg-secondary">Off</span>
                                        }
                                    </td>
                                    <td><small class="text-muted">@(secret.KubernetesSecretName ?? "—")</small></td>
                                    <td><small class="text-muted">@(secret.KubernetesNamespace ?? "—")</small></td>
                                    <td><small class="text-muted">@secret.UpdatedAt.ToString("MMM d, HH:mm")</small></td>
                                    <td class="text-end">
                                        @* Reveal — available to all roles *@
                                        <button class="btn btn-sm btn-outline-secondary me-1"
                                                @onclick="() => RevealSecret(secret)"
                                                title="@(revealedSecretId == secret.Id ? "Hide value" : "Reveal value")">
                                            <i class="bi @(revealedSecretId == secret.Id ? "bi-eye-slash" : "bi-eye")"></i>
                                        </button>

                                        @* Admin-only: edit, K8s sync, delete *@
                                        @if (AccessRole >= CustomerAccessRole.Admin)
                                        {
                                            <button class="btn btn-sm btn-outline-warning me-1"
                                                    @onclick="() => StartEdit(secret)" title="Update value">
                                                <i class="bi bi-pencil"></i>
                                            </button>
                                            <button class="btn btn-sm btn-outline-info me-1"
                                                    @onclick="() => ToggleSync(secret)"
                                                    title="@(secret.SyncToKubernetes ? "Disable K8s sync" : "Configure K8s sync")">
                                                <i class="bi @(secret.SyncToKubernetes ? "bi-cloud-slash" : "bi-cloud-arrow-up")"></i>
                                            </button>
                                            <button class="btn btn-sm btn-outline-danger"
                                                    @onclick="() => DeleteSecret(secret.Id)" title="Delete secret">
                                                <i class="bi bi-trash"></i>
                                            </button>
                                        }
                                    </td>
                                </tr>

                                @* ── Reveal value row ── *@
                                @if (revealedSecretId == secret.Id)
                                {
                                    <tr class="table-light">
                                        <td colspan="6">
                                            <div class="d-flex align-items-center px-2 py-1 gap-2">
                                                <span class="text-muted small">Value:</span>
                                                @if (revealLoading)
                                                {
                                                    <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                                                }
                                                else
                                                {
                                                    <code class="user-select-all">@revealedValue</code>
                                                }
                                            </div>
                                        </td>
                                    </tr>
                                }

                                @* ── Edit value row ── *@
                                @if (editSecretId == secret.Id)
                                {
                                    <tr class="table-light">
                                        <td colspan="6">
                                            <div class="row g-2 p-2 align-items-center">
                                                <div class="col-md-6">
                                                    <input type="password" class="form-control form-control-sm"
                                                           placeholder="New secret value"
                                                           @bind="editSecretValue" />
                                                </div>
                                                <div class="col-auto">
                                                    <button class="btn btn-sm btn-success" @onclick="SaveEdit"
                                                            disabled="@(string.IsNullOrWhiteSpace(editSecretValue) || saving)">
                                                        @if (saving) { <span class="spinner-border spinner-border-sm me-1"></span> }
                                                        <i class="bi bi-check-lg me-1"></i>Update
                                                    </button>
                                                    <button class="btn btn-sm btn-outline-secondary ms-1" @onclick="CancelEdit">
                                                        Cancel
                                                    </button>
                                                </div>
                                            </div>
                                        </td>
                                    </tr>
                                }

                                @* ── K8s sync config row ── *@
                                @if (syncConfigSecretId == secret.Id)
                                {
                                    <tr class="table-light">
                                        <td colspan="6">
                                            <div class="row g-2 p-2 align-items-center">
                                                @if (clusters is not null)
                                                {
                                                    <div class="col-md-3">
                                                        <select class="form-select form-select-sm" @bind="syncClusterId">
                                                            <option value="@Guid.Empty">Target cluster…</option>
                                                            @foreach (KubernetesCluster cluster in clusters)
                                                            {
                                                                <option value="@cluster.Id">@cluster.Name</option>
                                                            }
                                                        </select>
                                                    </div>
                                                }
                                                <div class="col-md-3">
                                                    <input type="text" class="form-control form-control-sm"
                                                           placeholder="K8s Secret name (e.g. my-app-secrets)"
                                                           @bind="syncSecretName" />
                                                </div>
                                                <div class="col-md-3">
                                                    <input type="text" class="form-control form-control-sm"
                                                           placeholder="Namespace (e.g. my-app)"
                                                           @bind="syncNamespace" />
                                                </div>
                                                <div class="col-auto">
                                                    <button class="btn btn-sm btn-success" @onclick="SaveSync">
                                                        <i class="bi bi-check-lg me-1"></i>Save
                                                    </button>
                                                    <button class="btn btn-sm btn-outline-secondary ms-1"
                                                            @onclick="() => syncConfigSecretId = null">
                                                        Cancel
                                                    </button>
                                                </div>
                                            </div>
                                        </td>
                                    </tr>
                                }
                            }
                        </tbody>
                    </table>
                </div>
            }
            @if (syncOutput is not null)
            {
                <div class="m-3 p-2 bg-dark text-white rounded font-monospace small" style="white-space: pre-wrap; max-height: 200px; overflow-y: auto;">@syncOutput</div>
            }
        </div>
    </div>

    @* ── Docker Registry Credentials ── *@
    <div class="mt-4">
        <div class="d-flex align-items-center mb-2">
            <i class="bi bi-box-seam fs-5 me-2 text-primary"></i>
            <h6 class="mb-0">Docker Registry Credentials</h6>
            <span class="ms-2 text-muted small">Pull secrets for private container registries</span>
        </div>
        <DockerRegistriesPanel
            TenantId="TenantId"
            AppId="App.Id"
            IsAdmin="AccessRole >= CustomerAccessRole.Admin" />
    </div>
}

@code {
    [Parameter] public required Data.App App { get; set; }
    [Parameter] public Guid TenantId { get; set; }
    [Parameter] public CustomerAccessRole AccessRole { get; set; }

    private bool vaultInitialized;
    private List<VaultSecret>? secrets;
    private List<KubernetesCluster>? clusters;

    // Add form
    private string newSecretName = "";
    private string newSecretValue = "";
    private bool saving;
    private string? errorMessage;
    private string? successMessage;

    // Reveal
    private Guid? revealedSecretId;
    private string? revealedValue;
    private bool revealLoading;

    // Edit
    private Guid? editSecretId;
    private string editSecretValue = "";

    // K8s sync config
    private Guid? syncConfigSecretId;
    private string syncSecretName = "";
    private string syncNamespace = "";
    private Guid syncClusterId;

    // Sync-to-K8s state
    private bool syncingSecrets;
    private string? syncOutput;

    protected override async Task OnInitializedAsync()
    {
        SecretVault? vault = await VaultService.GetVaultAsync(TenantId);
        vaultInitialized = vault is not null;

        if (vaultInitialized)
        {
            await LoadSecrets();
        }

        // Load clusters for the K8s sync config dropdown.
        clusters = await TenantService.GetClustersAsync(TenantId);
    }

    private async Task LoadSecrets()
    {
        secrets = await VaultService.GetAppSecretsAsync(TenantId, App.Id);
    }

    // ──────── Add ────────

    private async Task AddSecret()
    {
        errorMessage = null;
        successMessage = null;
        saving = true;

        try
        {
            await VaultService.SetAppSecretAsync(TenantId, App.Id, newSecretName.Trim(), newSecretValue.Trim());
            successMessage = $"Secret '{newSecretName.Trim()}' saved.";
            newSecretName = "";
            newSecretValue = "";
            await LoadSecrets();
        }
        catch (Exception ex)
        {
            errorMessage = ex.Message;
        }
        finally { saving = false; }
    }

    // ──────── Reveal ────────

    private async Task RevealSecret(VaultSecret secret)
    {
        if (revealedSecretId == secret.Id)
        {
            revealedSecretId = null;
            revealedValue = null;
            return;
        }

        revealLoading = true;
        revealedSecretId = secret.Id;
        revealedValue = null;
        revealedValue = await VaultService.GetSecretValueByIdAsync(secret.Id);
        revealLoading = false;
    }

    // ──────── Edit ────────

    private void StartEdit(VaultSecret secret)
    {
        editSecretId = secret.Id;
        editSecretValue = "";
        revealedSecretId = null;
        revealedValue = null;
    }

    private void CancelEdit()
    {
        editSecretId = null;
        editSecretValue = "";
    }

    private async Task SaveEdit()
    {
        if (editSecretId is null || string.IsNullOrWhiteSpace(editSecretValue)) return;

        saving = true;
        errorMessage = null;

        try
        {
            bool updated = await VaultService.UpdateSecretValueAsync(editSecretId.Value, editSecretValue.Trim());
            successMessage = updated ? "Secret value updated." : null;
            errorMessage = updated ? null : "Failed to update secret.";
        }
        finally { saving = false; }

        editSecretId = null;
        editSecretValue = "";
        await LoadSecrets();
    }

    // ──────── Delete ────────

    private async Task DeleteSecret(Guid secretId)
    {
        errorMessage = null;
        (bool canDelete, string? reason) = await VaultService.CanDeleteSecretAsync(secretId);

        if (!canDelete)
        {
            errorMessage = reason;
            return;
        }

        await VaultService.DeleteSecretAsync(secretId);
        revealedSecretId = null;
        editSecretId = null;
        await LoadSecrets();
    }

    // ──────── K8s Sync ────────

    private void ToggleSync(VaultSecret secret)
    {
        if (secret.SyncToKubernetes)
        {
            _ = DisableSync(secret.Id);
        }
        else
        {
            syncConfigSecretId = secret.Id;
            syncSecretName = secret.KubernetesSecretName ?? "";
            syncNamespace = secret.KubernetesNamespace ?? "";
            syncClusterId = secret.KubernetesClusterId ?? Guid.Empty;
        }
    }

    private async Task DisableSync(Guid secretId)
    {
        await VaultService.ConfigureKubernetesSyncAsync(secretId, syncEnabled: false, secretName: null, ns: null);
        await LoadSecrets();
    }

    private async Task SaveSync()
    {
        if (syncConfigSecretId is null) return;

        Guid? clusterId = syncClusterId != Guid.Empty ? syncClusterId : (Guid?)null;

        await VaultService.ConfigureKubernetesSyncAsync(
            syncConfigSecretId.Value,
            syncEnabled: true,
            secretName: syncSecretName.Trim(),
            ns: syncNamespace.Trim(),
            clusterId: clusterId);

        syncConfigSecretId = null;
        await LoadSecrets();
    }

    private async Task SyncAllToKubernetes()
    {
        syncingSecrets = true;
        syncOutput = null;

        try
        {
            HelmExecutionResult result = await VaultService.SyncAppSecretsToKubernetesAsync(TenantId, App.Id);
            syncOutput = result.Output;
        }
        finally
        {
            syncingSecrets = false;
        }
    }
}
