@page "/design/transport/import"
@using ZB.MOM.WW.ScadaBridge.Security
@using ZB.MOM.WW.ScadaBridge.Commons.Types.Transport
@using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Transport
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.Extensions.Options
@using ZB.MOM.WW.ScadaBridge.Transport
@using ZB.MOM.WW.ScadaBridge.Transport.Import
@using System.Security.Cryptography
@attribute [Authorize(Policy = AuthorizationPolicies.RequireAdmin)]

@*
   TransportImport wizard (Component #24, Task T22).

   A 5-step linear wizard:
     Step 1 — Upload     : InputFile + manifest summary; LoadAsync without passphrase first.
     Step 2 — Passphrase : only shown for encrypted bundles; 3-strike lockout.
     Step 3 — Diff       : conflict resolution (Add/Overwrite/Skip/Rename) per ImportPreviewItem.
     Step 4 — Confirm    : type-the-environment-name guard.
     Step 5 — Result     : ApplyAsync result + audit drilldown link.

   The page is Admin-only — Import touches central configuration globally.
*@

<div class="container-fluid mt-3">
    <h4 class="mb-3">Import Bundle</h4>

    @* Step indicator — five numbered pills, mirrors TransportExport. *@
    <nav aria-label="Import wizard steps" class="mb-4">
        <ol class="list-unstyled d-flex flex-wrap gap-3 mb-0 small">
            <li class="@StepClass(ImportWizardStep.Upload)">
                <span class="badge rounded-pill me-1">1</span> Upload
            </li>
            <li class="@StepClass(ImportWizardStep.Passphrase)">
                <span class="badge rounded-pill me-1">2</span> Passphrase
            </li>
            <li class="@StepClass(ImportWizardStep.Diff)">
                <span class="badge rounded-pill me-1">3</span> Diff
            </li>
            <li class="@StepClass(ImportWizardStep.Confirm)">
                <span class="badge rounded-pill me-1">4</span> Confirm
            </li>
            <li class="@StepClass(ImportWizardStep.Result)">
                <span class="badge rounded-pill me-1">5</span> Result
            </li>
        </ol>
    </nav>

    @if (_errorMessage != null)
    {
        <div class="alert alert-danger" data-testid="error-message">@_errorMessage</div>
    }

    @switch (_step)
    {
        case ImportWizardStep.Upload:
            @RenderStepUpload();
            break;
        case ImportWizardStep.Passphrase:
            @RenderStepPassphrase();
            break;
        case ImportWizardStep.Diff:
            @RenderStepDiff();
            break;
        case ImportWizardStep.Confirm:
            @RenderStepConfirm();
            break;
        case ImportWizardStep.Result:
            @RenderStepResult();
            break;
    }
</div>

@code {
    private string StepClass(ImportWizardStep s) =>
        s == _step ? "fw-semibold text-primary"
        : (int)s < (int)_step ? "text-success"
        : "text-muted";

    // ============================================================
    // Step 1 — Upload
    // ============================================================
    private RenderFragment RenderStepUpload() => __builder =>
    {
        <div>
            <p class="text-body-secondary">
                Select a <code>.scadabundle</code> file produced by an exporter on this
                or another cluster. The bundle's manifest will be validated immediately;
                encrypted bundles will prompt for a passphrase on the next step.
            </p>

            <div class="mb-3">
                <label for="bundle-input" class="form-label">Bundle file</label>
                <InputFile id="bundle-input" OnChange="OnFileSelectedAsync"
                           class="form-control" accept=".scadabundle,application/zip" />
                <div class="form-text">
                    Maximum bundle size: @Options.Value.MaxBundleSizeMb MB.
                </div>
            </div>

            @if (_uploadInProgress)
            {
                <div class="text-muted small fst-italic">Reading bundle…</div>
            }

            @if (_bundleTempPath is not null && _errorMessage is null)
            {
                @if (_session is not null)
                {
                    <dl class="row small mt-3" data-testid="manifest-summary">
                        <dt class="col-sm-3">Source environment</dt>
                        <dd class="col-sm-9"><code>@_session.Manifest.SourceEnvironment</code></dd>

                        <dt class="col-sm-3">Exported by</dt>
                        <dd class="col-sm-9">@_session.Manifest.ExportedBy</dd>

                        <dt class="col-sm-3">Created</dt>
                        <dd class="col-sm-9">@_session.Manifest.CreatedAtUtc.ToString("u")</dd>

                        <dt class="col-sm-3">Content count</dt>
                        <dd class="col-sm-9">@_session.Manifest.Contents.Count items</dd>

                        <dt class="col-sm-3">SHA-256</dt>
                        <dd class="col-sm-9"><code class="small">@_session.Manifest.ContentHash</code></dd>

                        <dt class="col-sm-3">Encryption</dt>
                        <dd class="col-sm-9">
                            @if (_session.Manifest.Encryption is null)
                            {
                                <span class="text-warning">Unencrypted</span>
                            }
                            else
                            {
                                <span class="text-success">@_session.Manifest.Encryption.Algorithm</span>
                            }
                        </dd>
                    </dl>
                }
                else
                {
                    <div class="alert alert-info mt-3" data-testid="encrypted-bundle-notice">
                        <strong>Encrypted bundle uploaded.</strong>
                        Click <strong>Next</strong> to enter the passphrase.
                    </div>
                }

                <div class="d-flex justify-content-end mt-3">
                    <button class="btn btn-primary" @onclick="GoFromUploadAsync">Next</button>
                </div>
            }
        </div>
    };

    // ============================================================
    // Step 2 — Passphrase
    // ============================================================
    private RenderFragment RenderStepPassphrase() => __builder =>
    {
        var maxAttempts = Options.Value.MaxUnlockAttemptsPerSession;
        var attemptsLeft = Math.Max(0, maxAttempts - _failedUnlockAttempts);

        <div>
            <p class="text-body-secondary">
                This bundle is encrypted. Enter the passphrase that was used to
                produce it. You have @attemptsLeft of @maxAttempts attempts before
                the upload must be restarted.
            </p>

            <div class="mb-3">
                <label for="import-passphrase" class="form-label">Passphrase</label>
                <input id="import-passphrase" type="password" class="form-control"
                       autocomplete="current-password"
                       @bind="_passphrase" @bind:event="oninput" />
            </div>

            @if (_failedUnlockAttempts > 0)
            {
                <div class="alert alert-warning small" data-testid="unlock-attempts">
                    Failed unlock attempts: @_failedUnlockAttempts of @maxAttempts.
                </div>
            }

            <div class="d-flex justify-content-between mt-3">
                <button class="btn btn-outline-secondary" @onclick="BackToUpload">Back</button>
                <button class="btn btn-primary"
                        disabled="@(string.IsNullOrEmpty(_passphrase) || _uploadInProgress)"
                        @onclick="SubmitPassphraseAsync">
                    @(_uploadInProgress ? "Unlocking…" : "Unlock")
                </button>
            </div>
        </div>
    };

    // ============================================================
    // Step 3 — Diff & resolve conflicts
    // ============================================================
    private RenderFragment RenderStepDiff() => __builder =>
    {
        if (_preview is null || _resolutions is null)
        {
            <div class="alert alert-warning">No preview available — please go back and re-upload.</div>
            return;
        }

        var (adds, overs, skips, renames, blockers) = CountResolutions();
        var hasBlockers = _preview.Items.Any(i => i.Kind == ConflictKind.Blocker);

        <div>
            <p class="text-body-secondary">
                Review each artifact in the bundle and choose how it should be applied
                to this environment. Identical items are skipped automatically; new
                items default to Add; modified items require an explicit choice.
            </p>

            <div class="mb-3 d-flex flex-wrap gap-2 align-items-center" data-testid="bulk-actions">
                <span class="small text-body-secondary">Apply to all modified:</span>
                <button class="btn btn-sm btn-outline-secondary" @onclick="() => BulkSet(ResolutionAction.Skip)">Skip</button>
                <button class="btn btn-sm btn-outline-secondary" @onclick="() => BulkSet(ResolutionAction.Overwrite)">Overwrite</button>
            </div>

            <div class="table-responsive" style="max-height: 480px; overflow-y: auto;">
                <table class="table table-sm table-striped align-middle">
                    <thead>
                        <tr>
                            <th>Type</th>
                            <th>Name</th>
                            <th>Status</th>
                            <th>Existing</th>
                            <th>Incoming</th>
                            <th>Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (var item in _preview.Items)
                        {
                            var key = (item.EntityType, item.Name);
                            var current = _resolutions[key];
                            <tr data-testid="diff-row">
                                <td><span class="badge bg-secondary">@item.EntityType</span></td>
                                <td>@item.Name</td>
                                <td>@RenderKindBadge(item)</td>
                                <td>@(item.ExistingVersion?.ToString() ?? "—")</td>
                                <td>@(item.IncomingVersion?.ToString() ?? "—")</td>
                                <td>@RenderResolutionControls(item, current)</td>
                            </tr>
                            @if (item.Kind == ConflictKind.Modified && !string.IsNullOrEmpty(item.FieldDiffJson))
                            {
                                <tr>
                                    <td colspan="6">
                                        <details>
                                            <summary class="small">Field diff</summary>
                                            <pre class="small mb-0"><code>@item.FieldDiffJson</code></pre>
                                        </details>
                                    </td>
                                </tr>
                            }
                            @if (item.Kind == ConflictKind.Blocker && !string.IsNullOrEmpty(item.BlockerReason))
                            {
                                <tr>
                                    <td colspan="6">
                                        <div class="alert alert-danger small mb-0">@item.BlockerReason</div>
                                    </td>
                                </tr>
                            }
                        }
                    </tbody>
                </table>
            </div>

            <div class="d-flex justify-content-between mt-3">
                <button class="btn btn-outline-secondary" @onclick="BackToUpload">Back</button>
                <div>
                    <span class="me-3 small text-body-secondary" data-testid="diff-summary">
                        @adds add · @overs overwrite · @skips skip · @renames rename · @blockers blocker
                    </span>
                    <button class="btn btn-primary"
                            disabled="@hasBlockers"
                            @onclick="GoToConfirm">
                        Next
                    </button>
                </div>
            </div>
        </div>
    };

    private RenderFragment RenderKindBadge(ImportPreviewItem item) => __builder =>
    {
        var (cls, label) = item.Kind switch
        {
            ConflictKind.Identical => ("bg-secondary", "Identical"),
            ConflictKind.Modified => ("bg-warning text-dark", "Modified"),
            ConflictKind.New => ("bg-success", "New"),
            ConflictKind.Blocker => ("bg-danger", "Blocker"),
            _ => ("bg-light text-dark", item.Kind.ToString()),
        };
        <span class="badge @cls">@label</span>
    };

    private RenderFragment RenderResolutionControls(ImportPreviewItem item, ImportResolution current) => __builder =>
    {
        // Identical → forced Skip; New → forced Add; Blocker → no actions.
        if (item.Kind == ConflictKind.Identical)
        {
            <span class="text-muted small">Skip</span>
            return;
        }
        if (item.Kind == ConflictKind.New)
        {
            <span class="text-muted small">Add</span>
            return;
        }
        if (item.Kind == ConflictKind.Blocker)
        {
            <span class="text-muted small">—</span>
            return;
        }

        var key = (item.EntityType, item.Name);

        <div class="d-flex flex-wrap gap-2 align-items-center">
            @foreach (var action in new[] { ResolutionAction.Overwrite, ResolutionAction.Skip, ResolutionAction.Rename })
            {
                var inputId = $"res-{item.EntityType}-{item.Name}-{action}";
                <div class="form-check form-check-inline mb-0">
                    <input class="form-check-input" type="radio"
                           id="@inputId"
                           name="@($"res-{item.EntityType}-{item.Name}")"
                           checked="@(current.Action == action)"
                           @onchange="() => SetResolution(key, action)" />
                    <label class="form-check-label small" for="@inputId">@action</label>
                </div>
            }
            @if (current.Action == ResolutionAction.Rename)
            {
                <input type="text" class="form-control form-control-sm"
                       style="max-width: 14rem;"
                       placeholder="New name"
                       value="@(current.RenameTo ?? string.Empty)"
                       @onchange="e => SetRenameTo(key, e.Value?.ToString())" />
            }
        </div>
    };

    // ============================================================
    // Step 4 — Confirm
    // ============================================================
    private RenderFragment RenderStepConfirm() => __builder =>
    {
        if (_session is null)
        {
            <div class="alert alert-warning">No bundle session — please re-upload.</div>
            return;
        }

        var (adds, overs, skips, renames, _) = CountResolutions();
        var changeCount = adds + overs + renames;

        <div>
            <p class="text-body-secondary">
                You are about to apply <strong>@changeCount</strong> change(s)
                to this environment (@adds add · @overs overwrite · @skips skip · @renames rename).
            </p>

            <div class="alert alert-info small">
                Affected instances will become stale and require redeployment via the
                <a href="/deployment/deployments">Deployments</a> page.
            </div>

            <div class="mb-3">
                <label for="confirm-env" class="form-label">
                    Type the source environment name <code>@_session.Manifest.SourceEnvironment</code> to confirm:
                </label>
                <input id="confirm-env" type="text" class="form-control"
                       @bind="_confirmEnvironmentText" @bind:event="oninput" />
            </div>

            <div class="d-flex justify-content-between mt-3">
                <button class="btn btn-outline-secondary" @onclick="BackToDiff">Back</button>
                <button class="btn btn-danger"
                        disabled="@(_confirmEnvironmentText != _session.Manifest.SourceEnvironment || _applyInProgress)"
                        @onclick="ApplyAsync">
                    @(_applyInProgress ? "Applying…" : "Apply Import")
                </button>
            </div>
        </div>
    };

    // ============================================================
    // Step 5 — Result
    // ============================================================
    private RenderFragment RenderStepResult() => __builder =>
    {
        <div>
            @if (_validationErrors is not null && _validationErrors.Count > 0)
            {
                <div class="alert alert-danger" data-testid="validation-errors">
                    <strong>Bundle semantic validation failed.</strong>
                    <ul class="mb-0">
                        @foreach (var err in _validationErrors)
                        {
                            <li>@err</li>
                        }
                    </ul>
                </div>
                <button class="btn btn-outline-secondary" @onclick="BackToDiff">Back</button>
            }
            else if (_result is not null)
            {
                <div class="alert alert-success" data-testid="result-summary">
                    <strong>Import complete.</strong>
                    @_result.Added added · @_result.Overwritten overwritten ·
                    @_result.Skipped skipped · @_result.Renamed renamed.
                </div>

                <dl class="row small">
                    <dt class="col-sm-3">Bundle Import Id</dt>
                    <dd class="col-sm-9"><code>@_result.BundleImportId</code></dd>
                </dl>

                <div class="d-flex gap-3">
                    <a class="btn btn-outline-primary" href="/deployment/deployments">
                        View on Deployments →
                    </a>
                    <a class="btn btn-outline-secondary"
                       href="@($"/audit/configuration?bundleImportId={_result.BundleImportId}")">
                        Audit trail →
                    </a>
                </div>
            }
            else
            {
                <div class="alert alert-danger">
                    Import failed. Please re-upload the bundle.
                </div>
                <button class="btn btn-outline-secondary" @onclick="BackToUpload">Back</button>
            }
        </div>
    };
}
