@using EntKube.Web.Data
@using EntKube.Web.Services
@using Microsoft.EntityFrameworkCore
@inject TenantService TenantService
@inject DeploymentService DeploymentService
@inject CnpgService CnpgService

@* ═══════════════════════════════════════════════════════════════════
   App Detail — a full-page view for a single application.
   Shows app info, environment links, and is the extension point
   for future app-level features (config, deployments, secrets, etc.).
   ═══════════════════════════════════════════════════════════════════ *@

@* --- Back button --- *@
<nav class="mb-3">
    <button class="btn btn-sm btn-link text-decoration-none p-0" @onclick="OnBack">
        <i class="bi bi-arrow-left me-1"></i>Back to @CustomerName
    </button>
</nav>

@* --- App header --- *@
<div class="card shadow-sm mb-4">
    <div class="card-body">
        <div class="d-flex align-items-start justify-content-between">
            <div class="d-flex align-items-start">
                <i class="bi bi-app-indicator fs-3 me-3 text-primary"></i>
                <div>
                    <h4 class="mb-1">@App.Name</h4>
                    <div class="d-flex flex-wrap gap-2 text-muted small">
                        <span><i class="bi bi-person me-1"></i>@CustomerName</span>
                        <span><i class="bi bi-calendar me-1"></i>Created @App.CreatedAt.ToString("MMM d, yyyy")</span>
                    </div>
                </div>
            </div>

            @if (!confirmDelete)
            {
                <button class="btn btn-sm btn-outline-danger" @onclick="() => confirmDelete = true" title="Delete app">
                    <i class="bi bi-trash me-1"></i>Delete
                </button>
            }
        </div>

        @if (confirmDelete)
        {
            <div class="mt-3 p-2 bg-danger bg-opacity-10 rounded d-flex align-items-center justify-content-between">
                <span class="text-danger small">
                    <i class="bi bi-exclamation-triangle me-1"></i>
                    Permanently delete <strong>@App.Name</strong> and all its data?
                </span>
                <div>
                    <button class="btn btn-sm btn-danger me-1" @onclick="DeleteApp">Yes, delete</button>
                    <button class="btn btn-sm btn-outline-secondary" @onclick="() => confirmDelete = false">Cancel</button>
                </div>
            </div>
        }
    </div>
</div>

@* --- App sub-sections (tabs for future expansion) --- *@
<ul class="nav nav-pills mb-3 gap-1">
    <li class="nav-item">
        <button class="nav-link @(section == "environments" ? "active" : "")" @onclick='() => section = "environments"'>
            <i class="bi bi-layers me-1"></i>Environments
        </button>
    </li>
    <li class="nav-item">
        <button class="nav-link @(section == "deployments" ? "active" : "")" @onclick="SwitchToDeployments">
            <i class="bi bi-rocket-takeoff me-1"></i>Deployments
            @if (deployments is not null && deployments.Count > 0)
            {
                <span class="badge bg-primary ms-1">@deployments.Count</span>
            }
        </button>
    </li>
</ul>

@if (section == "environments")
{
    <div class="card shadow-sm">
        <div class="card-header bg-white py-2">
            <div class="d-flex align-items-center">
                <i class="bi bi-layers me-2 text-primary"></i>
                <strong>Environment Links</strong>
            </div>
            <small class="text-muted">Select which environments this app is deployed to.</small>
        </div>
        <div class="card-body">
            @if (environments is null)
            {
                <div class="text-center py-3">
                    <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                </div>
            }
            else if (environments.Count == 0)
            {
                <div class="text-center py-4">
                    <i class="bi bi-layers text-muted" style="font-size: 2rem;"></i>
                    <p class="text-muted small mt-2 mb-0">No environments exist for this tenant yet. Create environments first.</p>
                </div>
            }
            else
            {
                <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-2">
                    @foreach (Data.Environment env in environments)
                    {
                        bool isLinked = linkedEnvIds.Contains(env.Id);

                        <div class="col">
                            <div class="card @(isLinked ? "border-success bg-success bg-opacity-10" : "border-light")"
                                 role="button" style="cursor: pointer;"
                                 @onclick="() => ToggleEnvironment(env.Id, isLinked)">
                                <div class="card-body py-2 d-flex align-items-center">
                                    <i class="bi @(isLinked ? "bi-check-circle-fill text-success" : "bi-circle text-muted") me-2 fs-5"></i>
                                    <div class="flex-grow-1">
                                        <span class="fw-medium">@env.Name</span>
                                    </div>
                                    @if (isLinked)
                                    {
                                        <span class="badge bg-success">Active</span>
                                    }
                                </div>
                            </div>
                        </div>
                    }
                </div>
            }
        </div>
    </div>
}

@* ═══════════════════════════════════════════════════════════════════
   Deployments Tab — manage deployments (Manual, YAML, Helm) targeting
   specific clusters. Shows ArgoCD-style sync/health status.
   ═══════════════════════════════════════════════════════════════════ *@
@if (section == "deployments")
{
    @* --- Deployment detail view (drill-down into a single deployment) --- *@
    @if (selectedDeployment is not null)
    {
        <nav class="mb-3">
            <button class="btn btn-sm btn-link text-decoration-none p-0" @onclick="() => selectedDeployment = null">
                <i class="bi bi-arrow-left me-1"></i>Back to deployments
            </button>
        </nav>

        <div class="card shadow-sm mb-3">
            <div class="card-body">
                <div class="d-flex align-items-start justify-content-between">
                    <div>
                        <h5 class="mb-1">
                            <i class="bi bi-rocket-takeoff me-2 text-primary"></i>@selectedDeployment.Name
                        </h5>
                        <div class="d-flex flex-wrap gap-2 text-muted small">
                            <span>@GetTypeBadge(selectedDeployment.Type)</span>
                            <span><i class="bi bi-layers me-1"></i>@selectedDeployment.Environment?.Name</span>
                            <span><i class="bi bi-hdd-network me-1"></i>@selectedDeployment.Cluster?.Name</span>
                            <span><i class="bi bi-box me-1"></i>@selectedDeployment.Namespace</span>
                        </div>
                    </div>
                    <div class="d-flex align-items-start gap-1">
                        @GetSyncBadge(selectedDeployment.SyncStatus)
                        @GetHealthBadge(selectedDeployment.HealthStatus)

                        @if (!confirmDeleteDeployment)
                        {
                            <button class="btn btn-sm btn-outline-danger ms-2" @onclick="() => confirmDeleteDeployment = true" title="Delete deployment">
                                <i class="bi bi-trash"></i>
                            </button>
                        }
                    </div>
                </div>

                @if (confirmDeleteDeployment)
                {
                    <div class="mt-3 p-2 bg-danger bg-opacity-10 rounded d-flex align-items-center justify-content-between">
                        <span class="text-danger small">
                            <i class="bi bi-exclamation-triangle me-1"></i>
                            Permanently delete <strong>@selectedDeployment.Name</strong> and all its manifests and resources?
                        </span>
                        <div>
                            <button class="btn btn-sm btn-danger me-1" @onclick="DeleteDeployment">Yes, delete</button>
                            <button class="btn btn-sm btn-outline-secondary" @onclick="() => confirmDeleteDeployment = false">Cancel</button>
                        </div>
                    </div>
                }

                @if (selectedDeployment.Type == DeploymentType.HelmChart)
                {
                    <div class="mt-3 p-2 bg-light rounded">
                        <small class="text-muted">
                            <i class="bi bi-box-seam me-1"></i>
                            @selectedDeployment.HelmChartName
                            <span class="mx-1">@selectedDeployment.HelmChartVersion</span>
                            <span class="text-muted">from @selectedDeployment.HelmRepoUrl</span>
                        </small>
                    </div>
                }
            </div>
        </div>

        @* --- Sub-tabs: Manifests / Resources / Helm Values --- *@
        <ul class="nav nav-tabs mb-3">
            @if (selectedDeployment.Type != DeploymentType.HelmChart)
            {
                <li class="nav-item">
                    <button class="nav-link @(deploymentSection == "manifests" ? "active" : "")"
                            @onclick='() => deploymentSection = "manifests"'>
                        <i class="bi bi-file-earmark-code me-1"></i>Manifests
                    </button>
                </li>
            }

            @if (selectedDeployment.Type == DeploymentType.HelmChart)
            {
                <li class="nav-item">
                    <button class="nav-link @(deploymentSection == "helm-values" ? "active" : "")"
                            @onclick='() => deploymentSection = "helm-values"'>
                        <i class="bi bi-sliders me-1"></i>Values
                    </button>
                </li>
            }

            <li class="nav-item">
                <button class="nav-link @(deploymentSection == "resources" ? "active" : "")"
                        @onclick="OpenResourcesTab">
                    <i class="bi bi-diagram-3 me-1"></i>Resources
                </button>
            </li>
            <li class="nav-item">
                <button class="nav-link @(deploymentSection == "databases" ? "active" : "")"
                        @onclick="OpenDatabasesTab">
                    <i class="bi bi-database me-1"></i>Databases
                    @if (databaseBindings is not null && databaseBindings.Count > 0)
                    {
                        <span class="badge bg-primary ms-1">@databaseBindings.Count</span>
                    }
                </button>
            </li>
        </ul>

        @* ── Manifests sub-tab ── *@
        @if (deploymentSection == "manifests")
        {
            <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-file-earmark-code me-2 text-primary"></i>
                        <strong>Manifests</strong>
                    </div>
                    <button class="btn btn-sm btn-outline-primary" @onclick="() => showAddManifest = !showAddManifest">
                        <i class="bi bi-plus me-1"></i>Add Manifest
                    </button>
                </div>
                <div class="card-body">
                    @if (showAddManifest)
                    {
                        <div class="card border-primary mb-3">
                            <div class="card-body">
                                <h6 class="mb-3"><i class="bi bi-plus-circle me-1"></i>Add YAML Manifest</h6>
                                <div class="row g-2 mb-2">
                                    <div class="col-md-4">
                                        <label class="form-label small">Kind</label>
                                        <input class="form-control form-control-sm" @bind="newManifestKind" placeholder="e.g. Deployment" />
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label small">Name</label>
                                        <input class="form-control form-control-sm" @bind="newManifestName" placeholder="e.g. billing-api" />
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label small">Sort Order</label>
                                        <input class="form-control form-control-sm" type="number" @bind="newManifestSortOrder" />
                                    </div>
                                </div>
                                <div class="mb-2">
                                    <label class="form-label small">YAML Content</label>
                                    <textarea class="form-control form-control-sm font-monospace" rows="8"
                                              @bind="newManifestYaml" placeholder="apiVersion: v1&#10;kind: Service&#10;..."></textarea>
                                </div>
                                <div class="d-flex gap-1">
                                    <button class="btn btn-sm btn-primary" @onclick="AddManifest"
                                            disabled="@(string.IsNullOrWhiteSpace(newManifestKind) || string.IsNullOrWhiteSpace(newManifestYaml))">
                                        Add
                                    </button>
                                    <button class="btn btn-sm btn-outline-secondary" @onclick="() => showAddManifest = false">Cancel</button>
                                </div>
                            </div>
                        </div>
                    }

                    @if (manifests is null)
                    {
                        <div class="text-center py-3">
                            <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                        </div>
                    }
                    else if (manifests.Count == 0)
                    {
                        <div class="text-center py-4">
                            <i class="bi bi-file-earmark-code text-muted" style="font-size: 2rem;"></i>
                            <p class="text-muted small mt-2 mb-0">No manifests yet. Add YAML manifests to define what gets deployed.</p>
                        </div>
                    }
                    else
                    {
                        @foreach (DeploymentManifest manifest in manifests)
                        {
                            <div class="card mb-2">
                                <div class="card-header bg-white py-2 d-flex align-items-center justify-content-between">
                                    <div>
                                        <span class="badge bg-secondary me-1">@manifest.Kind</span>
                                        <span class="fw-medium">@manifest.Name</span>
                                        <span class="text-muted small ms-2">#@manifest.SortOrder</span>
                                    </div>
                                    <div class="d-flex gap-1">
                                        @if (editingManifestId == manifest.Id)
                                        {
                                            <button class="btn btn-sm btn-primary" @onclick="() => SaveManifest(manifest.Id)">Save</button>
                                            <button class="btn btn-sm btn-outline-secondary" @onclick="() => editingManifestId = null">Cancel</button>
                                        }
                                        else
                                        {
                                            <button class="btn btn-sm btn-outline-primary" @onclick="() => StartEditManifest(manifest)">
                                                <i class="bi bi-pencil"></i>
                                            </button>
                                            <button class="btn btn-sm btn-outline-danger" @onclick="() => DeleteManifest(manifest.Id)">
                                                <i class="bi bi-trash"></i>
                                            </button>
                                        }
                                    </div>
                                </div>

                                @if (editingManifestId == manifest.Id)
                                {
                                    <div class="card-body p-2">
                                        <textarea class="form-control form-control-sm font-monospace" rows="10"
                                                  @bind="editManifestYaml"></textarea>
                                    </div>
                                }
                                else
                                {
                                    <div class="card-body p-2">
                                        <pre class="mb-0 small" style="max-height: 200px; overflow-y: auto;">@manifest.YamlContent</pre>
                                    </div>
                                }
                            </div>
                        }
                    }
                </div>
            </div>
        }

        @* ── Helm Values sub-tab ── *@
        @if (deploymentSection == "helm-values")
        {
            <div class="card shadow-sm">
                <div class="card-header bg-white py-2">
                    <i class="bi bi-sliders me-2 text-primary"></i>
                    <strong>Helm Values</strong>
                </div>
                <div class="card-body">
                    <p class="text-muted small mb-2">Override the chart's default values (YAML format).</p>
                    <textarea class="form-control font-monospace" rows="12"
                              @bind="helmValuesYaml"
                              placeholder="replicas: 3&#10;persistence:&#10;  size: 10Gi"></textarea>
                    <button class="btn btn-sm btn-primary mt-2" @onclick="SaveHelmValues">
                        <i class="bi bi-save me-1"></i>Save Values
                    </button>
                </div>
            </div>
        }

        @* ── Resources sub-tab (ArgoCD-style tree) ── *@
        @if (deploymentSection == "resources")
        {
            <div class="card shadow-sm">
                <div class="card-header bg-white py-2">
                    <i class="bi bi-diagram-3 me-2 text-primary"></i>
                    <strong>Resource Tree</strong>
                </div>
                <div class="card-body">
                    @if (resourceTree is null)
                    {
                        <div class="text-center py-3">
                            <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                        </div>
                    }
                    else if (resourceTree.Count == 0)
                    {
                        <div class="text-center py-4">
                            <i class="bi bi-diagram-3 text-muted" style="font-size: 2rem;"></i>
                            <p class="text-muted small mt-2 mb-0">No tracked resources yet. Resources appear here after the deployment syncs to the cluster.</p>
                        </div>
                    }
                    else
                    {
                        @foreach (DeploymentResource root in resourceTree)
                        {
                            <div class="mb-2">
                                @RenderResource(root, 0)
                            </div>
                        }
                    }
                </div>
            </div>
        }

        @* ── Databases sub-tab ── *@
        @if (deploymentSection == "databases")
        {
            <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-database me-2 text-primary"></i>
                        <strong>Database Bindings</strong>
                    </div>
                    <button class="btn btn-sm btn-outline-primary" @onclick="() => showAddBinding = !showAddBinding">
                        <i class="bi bi-plus me-1"></i>Attach Database
                    </button>
                </div>
                <div class="card-body">
                    @if (!string.IsNullOrEmpty(bindingError))
                    {
                        <div class="alert alert-danger py-1 small mb-2">@bindingError</div>
                    }

                    @* --- Add binding form --- *@
                    @if (showAddBinding)
                    {
                        <div class="card border-primary mb-3">
                            <div class="card-body">
                                <h6 class="mb-3"><i class="bi bi-plus-circle me-1"></i>Attach a PostgreSQL Database</h6>
                                <div class="row g-2 mb-2">
                                    <div class="col-md-6">
                                        <label class="form-label small">Database</label>
                                        <select class="form-select form-select-sm" @bind="newBindingDatabaseId">
                                            <option value="">Select database...</option>
                                            @if (availableCnpgDatabases is not null)
                                            {
                                                @foreach ((CnpgCluster cluster, CnpgDatabase database) in availableCnpgDatabases)
                                                {
                                                    <option value="@database.Id">@cluster.Name / @database.Name</option>
                                                }
                                            }
                                        </select>
                                    </div>
                                    <div class="col-md-6">
                                        <label class="form-label small">Secret name in app namespace</label>
                                        <input class="form-control form-control-sm" @bind="newBindingSecretName"
                                               placeholder="e.g. my-app-db" />
                                        <div class="form-text">The K8s Secret created in <code>@selectedDeployment?.Namespace</code>.</div>
                                    </div>
                                </div>
                                <div class="d-flex gap-1">
                                    <button class="btn btn-sm btn-primary" @onclick="AddDatabaseBinding"
                                            disabled="@(newBindingDatabaseId == Guid.Empty || string.IsNullOrWhiteSpace(newBindingSecretName))">
                                        Attach &amp; Sync
                                    </button>
                                    <button class="btn btn-sm btn-outline-secondary" @onclick="() => showAddBinding = false">Cancel</button>
                                </div>
                            </div>
                        </div>
                    }

                    @* --- Binding list --- *@
                    @if (databaseBindings is null)
                    {
                        <div class="text-center py-3">
                            <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                        </div>
                    }
                    else if (databaseBindings.Count == 0)
                    {
                        <div class="text-center py-4">
                            <i class="bi bi-database text-muted" style="font-size: 2rem;"></i>
                            <p class="text-muted small mt-2 mb-0">No databases attached. Attach a database to have its credentials automatically synced to this deployment's namespace.</p>
                        </div>
                    }
                    else
                    {
                        <table class="table table-sm mb-0">
                            <thead class="table-light">
                                <tr>
                                    <th class="small">Database</th>
                                    <th class="small">Secret name</th>
                                    <th class="small">Last synced</th>
                                    <th></th>
                                </tr>
                            </thead>
                            <tbody>
                                @foreach (DatabaseBinding binding in databaseBindings)
                                {
                                    <tr>
                                        <td class="small">
                                            @if (binding.CnpgDatabase is not null)
                                            {
                                                <i class="bi bi-database me-1 text-primary"></i>
                                                @binding.CnpgDatabase.CnpgCluster.Name<span class="text-muted"> / </span>@binding.CnpgDatabase.Name
                                            }
                                            else if (binding.MongoDatabase is not null)
                                            {
                                                <i class="bi bi-database me-1 text-success"></i>
                                                @binding.MongoDatabase.MongoCluster.Name<span class="text-muted"> / </span>@binding.MongoDatabase.Name
                                            }
                                        </td>
                                        <td><code class="small">@binding.KubernetesSecretName</code></td>
                                        <td class="small text-muted">
                                            @(binding.LastSyncedAt.HasValue ? binding.LastSyncedAt.Value.ToString("yyyy-MM-dd HH:mm") : "Never")
                                        </td>
                                        <td>
                                            <button class="btn btn-link btn-sm text-danger p-0" title="Detach"
                                                    @onclick="() => RemoveDatabaseBinding(binding.Id)">
                                                <i class="bi bi-x-circle" style="font-size:0.85rem;"></i>
                                            </button>
                                        </td>
                                    </tr>
                                }
                            </tbody>
                        </table>
                    }
                </div>
            </div>
        }
    }
    else
    {
        @* --- Deployment list view --- *@
        <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-rocket-takeoff me-2 text-primary"></i>
                    <strong>Deployments</strong>
                </div>
                <button class="btn btn-sm btn-outline-primary" @onclick="() => showCreateDeployment = !showCreateDeployment">
                    <i class="bi bi-plus me-1"></i>New Deployment
                </button>
            </div>
            <div class="card-body">
                @* --- Create deployment form --- *@
                @if (showCreateDeployment)
                {
                    <div class="card border-primary mb-3">
                        <div class="card-body">
                            <h6 class="mb-3"><i class="bi bi-plus-circle me-1"></i>Create Deployment</h6>
                            <div class="row g-2 mb-2">
                                <div class="col-md-6">
                                    <label class="form-label small">Name</label>
                                    <input class="form-control form-control-sm" @bind="newDeployName" placeholder="e.g. billing-api-prod" />
                                </div>
                                <div class="col-md-6">
                                    <label class="form-label small">Type</label>
                                    <select class="form-select form-select-sm" @bind="newDeployType">
                                        <option value="@DeploymentType.Manual">Manual</option>
                                        <option value="@DeploymentType.Yaml">YAML</option>
                                        <option value="@DeploymentType.HelmChart">Helm Chart</option>
                                    </select>
                                </div>
                            </div>

                            <div class="row g-2 mb-2">
                                <div class="col-md-4">
                                    <label class="form-label small">Environment</label>
                                    <select class="form-select form-select-sm" @bind="newDeployEnvId">
                                        <option value="">Select...</option>
                                        @if (environments is not null)
                                        {
                                            @foreach (Data.Environment env in environments)
                                            {
                                                <option value="@env.Id">@env.Name</option>
                                            }
                                        }
                                    </select>
                                </div>
                                <div class="col-md-4">
                                    <label class="form-label small">Cluster</label>
                                    <select class="form-select form-select-sm" @bind="newDeployClusterId">
                                        <option value="">Select...</option>
                                        @if (clusters is not null)
                                        {
                                            @foreach (KubernetesCluster cluster in clusters.Where(c => newDeployEnvId == Guid.Empty || c.EnvironmentId == newDeployEnvId))
                                            {
                                                <option value="@cluster.Id">@cluster.Name</option>
                                            }
                                        }
                                    </select>
                                </div>
                                <div class="col-md-4">
                                    <label class="form-label small">Namespace</label>
                                    <input class="form-control form-control-sm" @bind="newDeployNamespace" placeholder="e.g. billing" />
                                </div>
                            </div>

                            @if (newDeployType == DeploymentType.HelmChart)
                            {
                                <div class="row g-2 mb-2">
                                    <div class="col-md-4">
                                        <label class="form-label small">Helm Repo URL</label>
                                        <input class="form-control form-control-sm" @bind="newHelmRepoUrl"
                                               placeholder="https://charts.bitnami.com/bitnami" />
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label small">Chart Name</label>
                                        <input class="form-control form-control-sm" @bind="newHelmChartName"
                                               placeholder="e.g. postgresql" />
                                    </div>
                                    <div class="col-md-4">
                                        <label class="form-label small">Chart Version</label>
                                        <input class="form-control form-control-sm" @bind="newHelmChartVersion"
                                               placeholder="e.g. 15.5.0" />
                                    </div>
                                </div>
                            }

                            @if (!string.IsNullOrEmpty(createDeployError))
                            {
                                <div class="alert alert-danger py-1 small mb-2">@createDeployError</div>
                            }

                            <div class="d-flex gap-1">
                                <button class="btn btn-sm btn-primary" @onclick="CreateDeployment"
                                        disabled="@(string.IsNullOrWhiteSpace(newDeployName) || newDeployEnvId == Guid.Empty || newDeployClusterId == Guid.Empty)">
                                    Create
                                </button>
                                <button class="btn btn-sm btn-outline-secondary" @onclick="() => showCreateDeployment = false">Cancel</button>
                            </div>
                        </div>
                    </div>
                }

                @* --- Deployment list --- *@
                @if (deployments is null)
                {
                    <div class="text-center py-3">
                        <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                    </div>
                }
                else if (deployments.Count == 0)
                {
                    <div class="text-center py-4">
                        <i class="bi bi-rocket-takeoff text-muted" style="font-size: 2rem;"></i>
                        <p class="text-muted small mt-2 mb-0">No deployments yet. Create one to start deploying to Kubernetes.</p>
                    </div>
                }
                else
                {
                    <div class="row row-cols-1 row-cols-lg-2 g-2">
                        @foreach (AppDeployment deploy in deployments)
                        {
                            <div class="col">
                                <div class="card border-light h-100" role="button" style="cursor: pointer;"
                                     @onclick="() => SelectDeployment(deploy)">
                                    <div class="card-body py-2">
                                        <div class="d-flex align-items-center justify-content-between mb-1">
                                            <span class="fw-medium">
                                                <i class="bi bi-rocket-takeoff me-1 text-primary"></i>@deploy.Name
                                            </span>
                                            <div class="d-flex gap-1">
                                                @GetSyncBadge(deploy.SyncStatus)
                                                @GetHealthBadge(deploy.HealthStatus)
                                            </div>
                                        </div>
                                        <div class="d-flex flex-wrap gap-2 text-muted small">
                                            @GetTypeBadge(deploy.Type)
                                            <span><i class="bi bi-layers me-1"></i>@deploy.Environment?.Name</span>
                                            <span><i class="bi bi-hdd-network me-1"></i>@deploy.Cluster?.Name</span>
                                            <span><i class="bi bi-box me-1"></i>@deploy.Namespace</span>
                                        </div>

                                        @if (!string.IsNullOrEmpty(deploy.StatusMessage))
                                        {
                                            <div class="text-muted small mt-1 text-truncate">@deploy.StatusMessage</div>
                                        }
                                    </div>
                                </div>
                            </div>
                        }
                    </div>
                }
            </div>
        </div>
    }
}

@code {
    [Parameter] public required Data.App App { get; set; }
    [Parameter] public Guid TenantId { get; set; }
    [Parameter] public string CustomerName { get; set; } = "";
    [Parameter] public EventCallback OnBack { get; set; }
    [Parameter] public EventCallback OnDeleted { get; set; }

    private string section = "environments";
    private bool confirmDelete;

    // Environments
    private List<Data.Environment>? environments;
    private HashSet<Guid> linkedEnvIds = new();

    // Deployments
    private List<AppDeployment>? deployments;
    private List<KubernetesCluster>? clusters;
    private AppDeployment? selectedDeployment;
    private string deploymentSection = "manifests";
    private bool confirmDeleteDeployment;

    // Create deployment form
    private bool showCreateDeployment;
    private string newDeployName = "";
    private DeploymentType newDeployType = DeploymentType.Manual;
    private Guid newDeployEnvId;
    private Guid newDeployClusterId;
    private string newDeployNamespace = "";
    private string newHelmRepoUrl = "";
    private string newHelmChartName = "";
    private string newHelmChartVersion = "";
    private string? createDeployError;

    // Manifest management
    private List<DeploymentManifest>? manifests;
    private bool showAddManifest;
    private string newManifestKind = "";
    private string newManifestName = "";
    private string newManifestYaml = "";
    private int newManifestSortOrder;
    private Guid? editingManifestId;
    private string editManifestYaml = "";

    // Helm values
    private string helmValuesYaml = "";

    // Resource tree
    private List<DeploymentResource>? resourceTree;

    // Database bindings
    private List<DatabaseBinding>? databaseBindings;
    private List<(CnpgCluster Cluster, CnpgDatabase Database)>? availableCnpgDatabases;
    private bool showAddBinding;
    private Guid newBindingDatabaseId;
    private string newBindingSecretName = "";
    private string? bindingError;

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

    // ──────── App ────────

    private async Task DeleteApp()
    {
        await TenantService.DeleteAppAsync(App.Id);
        await OnDeleted.InvokeAsync();
    }

    // ──────── Environments ────────

    private async Task LoadEnvironments()
    {
        environments = await TenantService.GetEnvironmentsAsync(TenantId);

        // Refresh the app to get current environment links.
        List<Data.App> apps = await TenantService.GetAppsAsync(App.CustomerId);
        Data.App? freshApp = apps.FirstOrDefault(a => a.Id == App.Id);

        linkedEnvIds = freshApp?.AppEnvironments.Select(ae => ae.EnvironmentId).ToHashSet() ?? new();
    }

    private async Task ToggleEnvironment(Guid envId, bool currentlyLinked)
    {
        if (currentlyLinked)
        {
            await TenantService.UnlinkAppFromEnvironmentAsync(App.Id, envId);
        }
        else
        {
            await TenantService.LinkAppToEnvironmentAsync(App.Id, envId);
        }

        await LoadEnvironments();
    }

    // ──────── Deployments ────────

    private async Task SwitchToDeployments()
    {
        section = "deployments";

        if (deployments is null)
        {
            await LoadDeployments();
        }

        if (clusters is null)
        {
            clusters = await TenantService.GetClustersAsync(TenantId);
        }
    }

    private async Task LoadDeployments()
    {
        deployments = await DeploymentService.GetDeploymentsAsync(App.Id);
    }

    private async Task CreateDeployment()
    {
        createDeployError = null;

        try
        {
            await DeploymentService.CreateDeploymentAsync(
                App.Id, newDeployName, newDeployType,
                newDeployEnvId, newDeployClusterId, newDeployNamespace,
                newDeployType == DeploymentType.HelmChart ? newHelmRepoUrl : null,
                newDeployType == DeploymentType.HelmChart ? newHelmChartName : null,
                newDeployType == DeploymentType.HelmChart ? newHelmChartVersion : null);

            // Reset form and reload.
            showCreateDeployment = false;
            newDeployName = "";
            newDeployNamespace = "";
            newHelmRepoUrl = "";
            newHelmChartName = "";
            newHelmChartVersion = "";
            await LoadDeployments();
        }
        catch (DbUpdateException)
        {
            createDeployError = $"A deployment named '{newDeployName}' already exists for this app.";
        }
    }

    private async Task SelectDeployment(AppDeployment deploy)
    {
        selectedDeployment = deploy;
        confirmDeleteDeployment = false;

        // Default to the appropriate sub-tab based on type.
        if (deploy.Type == DeploymentType.HelmChart)
        {
            deploymentSection = "helm-values";
            helmValuesYaml = deploy.HelmValues ?? "";
        }
        else
        {
            deploymentSection = "manifests";
            await LoadManifests();
        }
    }

    private async Task DeleteDeployment()
    {
        if (selectedDeployment is not null)
        {
            await DeploymentService.DeleteDeploymentAsync(selectedDeployment.Id);
            selectedDeployment = null;
            confirmDeleteDeployment = false;
            await LoadDeployments();
        }
    }

    // ──────── Manifests ────────

    private async Task LoadManifests()
    {
        if (selectedDeployment is not null)
        {
            manifests = await DeploymentService.GetManifestsAsync(selectedDeployment.Id);
        }
    }

    private async Task AddManifest()
    {
        if (selectedDeployment is null)
        {
            return;
        }

        await DeploymentService.AddManifestAsync(
            selectedDeployment.Id, newManifestKind, newManifestName, newManifestYaml, newManifestSortOrder);

        showAddManifest = false;
        newManifestKind = "";
        newManifestName = "";
        newManifestYaml = "";
        newManifestSortOrder = 0;
        await LoadManifests();
    }

    private void StartEditManifest(DeploymentManifest manifest)
    {
        editingManifestId = manifest.Id;
        editManifestYaml = manifest.YamlContent;
    }

    private async Task SaveManifest(Guid manifestId)
    {
        await DeploymentService.UpdateManifestAsync(manifestId, editManifestYaml);
        editingManifestId = null;
        await LoadManifests();
    }

    private async Task DeleteManifest(Guid manifestId)
    {
        await DeploymentService.DeleteManifestAsync(manifestId);
        await LoadManifests();
    }

    // ──────── Helm Values ────────

    private async Task SaveHelmValues()
    {
        if (selectedDeployment is not null)
        {
            await DeploymentService.UpdateHelmValuesAsync(selectedDeployment.Id, helmValuesYaml);
        }
    }

    // ──────── Resources ────────

    private async Task OpenResourcesTab()
    {
        deploymentSection = "resources";

        if (selectedDeployment is not null)
        {
            resourceTree = await DeploymentService.GetResourceTreeAsync(selectedDeployment.Id);
        }
    }

    // ──────── Database bindings ────────

    private async Task OpenDatabasesTab()
    {
        deploymentSection = "databases";

        if (selectedDeployment is not null)
        {
            databaseBindings = await CnpgService.GetDatabaseBindingsAsync(selectedDeployment.Id);

            if (availableCnpgDatabases is null)
            {
                List<CnpgCluster> clusters = await CnpgService.GetClustersAsync(TenantId);
                availableCnpgDatabases = clusters
                    .SelectMany(c => c.Databases.Select(d => (c, d)))
                    .ToList();
            }
        }
    }

    private async Task AddDatabaseBinding()
    {
        if (selectedDeployment is null || newBindingDatabaseId == Guid.Empty)
        {
            return;
        }

        bindingError = null;

        try
        {
            DatabaseBinding binding = await CnpgService.AddCnpgDatabaseBindingAsync(
                selectedDeployment.Id, newBindingDatabaseId, newBindingSecretName);

            // Find the cluster that owns this database so we can call sync.
            (CnpgCluster cluster, CnpgDatabase _)? match = availableCnpgDatabases?
                .FirstOrDefault(x => x.Database.Id == newBindingDatabaseId);

            if (match.HasValue)
            {
                await CnpgService.SyncDatabaseCredentialsToK8sAsync(
                    TenantId, match.Value.cluster.Id, newBindingDatabaseId);
            }

            showAddBinding = false;
            newBindingDatabaseId = Guid.Empty;
            newBindingSecretName = "";
            databaseBindings = await CnpgService.GetDatabaseBindingsAsync(selectedDeployment.Id);
        }
        catch (Exception ex)
        {
            bindingError = $"Failed to attach database: {ex.Message}";
        }
    }

    private async Task RemoveDatabaseBinding(Guid bindingId)
    {
        bindingError = null;

        try
        {
            await CnpgService.RemoveDatabaseBindingAsync(bindingId);

            if (selectedDeployment is not null)
            {
                databaseBindings = await CnpgService.GetDatabaseBindingsAsync(selectedDeployment.Id);
            }
        }
        catch (Exception ex)
        {
            bindingError = $"Failed to detach database: {ex.Message}";
        }
    }

    // ──────── Rendering helpers ────────

    private RenderFragment GetTypeBadge(DeploymentType type) => type switch
    {
        DeploymentType.Manual => @<span class="badge bg-info">Manual</span>,
        DeploymentType.Yaml => @<span class="badge bg-warning text-dark">YAML</span>,
        DeploymentType.HelmChart => @<span class="badge bg-purple text-white" style="background-color: #6f42c1 !important;">Helm</span>,
        _ => @<span class="badge bg-secondary">Unknown</span>
    };

    private RenderFragment GetSyncBadge(SyncStatus status) => status switch
    {
        SyncStatus.Synced => @<span class="badge bg-success"><i class="bi bi-check-circle me-1"></i>Synced</span>,
        SyncStatus.OutOfSync => @<span class="badge bg-warning text-dark"><i class="bi bi-exclamation-circle me-1"></i>OutOfSync</span>,
        SyncStatus.Syncing => @<span class="badge bg-info"><i class="bi bi-arrow-repeat me-1"></i>Syncing</span>,
        SyncStatus.Failed => @<span class="badge bg-danger"><i class="bi bi-x-circle me-1"></i>Failed</span>,
        _ => @<span class="badge bg-secondary">Unknown</span>
    };

    private RenderFragment GetHealthBadge(HealthStatus status) => status switch
    {
        HealthStatus.Healthy => @<span class="badge bg-success"><i class="bi bi-heart-fill me-1"></i>Healthy</span>,
        HealthStatus.Progressing => @<span class="badge bg-info"><i class="bi bi-hourglass-split me-1"></i>Progressing</span>,
        HealthStatus.Degraded => @<span class="badge bg-warning text-dark"><i class="bi bi-exclamation-triangle me-1"></i>Degraded</span>,
        HealthStatus.Missing => @<span class="badge bg-danger"><i class="bi bi-question-circle me-1"></i>Missing</span>,
        HealthStatus.Suspended => @<span class="badge bg-secondary"><i class="bi bi-pause-circle me-1"></i>Suspended</span>,
        _ => @<span class="badge bg-secondary">Unknown</span>
    };

    private RenderFragment RenderResource(DeploymentResource resource, int depth) => __builder =>
    {
        <div class="d-flex align-items-center py-1 border-bottom" style="padding-left: @(depth * 24)px;">
            <span class="badge bg-secondary me-2 small">@resource.Kind</span>
            <span class="fw-medium small flex-grow-1">@resource.Name</span>
            <div class="d-flex gap-1">
                @GetSyncBadge(resource.SyncStatus)
                @GetHealthBadge(resource.HealthStatus)
            </div>
        </div>
        @if (resource.ChildResources?.Count > 0)
        {
            @foreach (DeploymentResource child in resource.ChildResources)
            {
                @RenderResource(child, depth + 1)
            }
        }
    };
}
