<!-- [DEF:DeploymentModal:Component] -->
<!--
@SEMANTICS: deployment, git, environment, modal
@PURPOSE:   Modal for deploying a dashboard to a target environment.
@LAYER:     Component
@RELATION:  CALLS -> frontend/src/services/gitService.js
@RELATION:  DISPATCHES -> deploy

@INVARIANT: Cannot deploy without a selected environment.
-->

<script>
    // [SECTION: IMPORTS]
    import { gitService } from "../../services/gitService";
    import { api } from "../../lib/api.js";
    import { addToast as toast } from "../../lib/toasts.js";
    import { t } from "../../lib/i18n";
    // [/SECTION]

    // [SECTION: PROPS]
    let { dashboardId, envId = null, show = $bindable(false), preferredTargetStage = "" } = $props();

    // [/SECTION]

    // [SECTION: STATE]
    let environments = $state([]);
    let selectedEnv = $state("");
    let loading = $state(false);
    let deploying = $state(false);
    // [/SECTION]

    const normalizedPreferredStage = $derived(String(preferredTargetStage || "").toUpperCase());
    const deploymentCandidates = $derived.by(() => {
        const all = environments.filter((env) => env?.id !== envId);
        if (!normalizedPreferredStage) return all;
        const stageMatched = all.filter((env) => normalizeEnvStage(env) === normalizedPreferredStage);
        return stageMatched.length > 0 ? stageMatched : all;
    });
    const selectedEnvironment = $derived(
        deploymentCandidates.find((env) => env.id === selectedEnv) || null,
    );
    const selectedEnvironmentStage = $derived(
        selectedEnvironment ? normalizeEnvStage(selectedEnvironment) : "",
    );
    const isProdTarget = $derived(selectedEnvironmentStage === "PROD");

    // [DEF:loadStatus:Watcher]
    $effect(() => {
        if (show) loadEnvironments();
    });
    // [/DEF:loadStatus:Watcher]

    // [DEF:normalizeEnvStage:Function]
    /**
     * @purpose Normalize environment stage with legacy production fallback.
     * @post Returns DEV/PREPROD/PROD.
     */
    function normalizeEnvStage(env) {
        if (env?.is_production) return "PROD";
        const stage = String(env?.stage || "").trim().toUpperCase();
        if (stage === "PROD" || stage === "PREPROD") return stage;
        return "DEV";
    }
    // [/DEF:normalizeEnvStage:Function]

    // [DEF:resolveEnvUrl:Function]
    /**
     * @purpose Resolve environment URL from consolidated or git-specific payload shape.
     * @post Returns stable URL string.
     */
    function resolveEnvUrl(env) {
        return String(env?.superset_url || env?.url || "");
    }
    // [/DEF:resolveEnvUrl:Function]

    // [DEF:loadEnvironments:Function]
    /**
     * @purpose Fetch available environments from API.
     * @post environments state is populated.
     * @side_effect Updates environments state.
     */
    async function loadEnvironments() {
        console.log(`[DeploymentModal][Action] Loading environments`);
        loading = true;
        try {
            environments = await api.getEnvironmentsList();
            const candidates = (environments || []).filter((env) => env?.id !== envId);
            if (normalizedPreferredStage) {
                const stageMatched = candidates.filter((env) => normalizeEnvStage(env) === normalizedPreferredStage);
                selectedEnv = (stageMatched[0]?.id) || (candidates[0]?.id) || "";
            } else {
                selectedEnv = (candidates[0]?.id) || "";
            }
            console.log(
                `[DeploymentModal][Coherence:OK] Loaded ${environments.length} environments`,
            );
        } catch (e) {
            console.error(`[DeploymentModal][Coherence:Failed] ${e.message}`);
            toast($t.migration?.loading_envs_failed, "error");
        } finally {
            loading = false;
        }
    }
    // [/DEF:loadEnvironments:Function]

    // [DEF:handleDeploy:Function]
    /**
     * @purpose Trigger deployment to selected environment.
     * @pre selectedEnv must be set.
     * @post Deploy request finishes and modal closes on success.
     * @side_effect Triggers API call, closes modal, shows toast.
     */
    async function handleDeploy() {
        if (!selectedEnv) return;
        if (isProdTarget) {
            const expected = String(dashboardId);
            const confirmation = prompt(`Подтвердите deploy в PROD. Введите slug: ${expected}`);
            if (String(confirmation || "").trim() !== expected) {
                toast("Подтверждение PROD не пройдено. Deploy отменен.", "error");
                return;
            }
        }
        console.log(`[DeploymentModal][Action] Deploying to ${selectedEnv}`);
        deploying = true;
        try {
            const result = await gitService.deploy(dashboardId, selectedEnv, envId);
            toast(
                result.message || $t.git?.deploy_success,
                "success",
            );
            show = false;
            console.log(`[DeploymentModal][Coherence:OK] Deployment triggered`);
        } catch (e) {
            console.error(`[DeploymentModal][Coherence:Failed] ${e.message}`);
            toast(e.message, "error");
        } finally {
            deploying = false;
        }
    }
    // [/DEF:handleDeploy:Function]
</script>

<!-- [SECTION: TEMPLATE] -->
{#if show}
    <div
        class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
    >
        <div class="bg-white p-6 rounded-lg shadow-xl w-96">
            <h2 class="text-xl font-bold mb-4">{$t.git?.deploy}</h2>

            {#if loading}
                <p class="text-gray-500">{$t.migration?.loading_envs}</p>
            {:else if deploymentCandidates.length === 0}
                <p class="text-red-500 mb-4">
                    {$t.git?.no_deploy_envs}
                </p>
                <div class="flex justify-end">
                    <button
                        onclick={() => (show = false)}
                        class="px-4 py-2 bg-gray-200 text-gray-800 rounded hover:bg-gray-300"
                    >
                        {$t.common?.close}
                    </button>
                </div>
            {:else}
                {#if normalizedPreferredStage}
                    <p class="mb-3 rounded border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800">
                        GitFlow target stage: {normalizedPreferredStage}
                    </p>
                {/if}
                <div class="mb-6">
                    <label for="deployment-target-env" class="block text-sm font-medium text-gray-700 mb-2"
                        >{$t.migration?.target_env}</label
                    >
                    <select
                        id="deployment-target-env"
                        bind:value={selectedEnv}
                        class="w-full border rounded p-2 focus:ring-2 focus:ring-blue-500 outline-none bg-white"
                    >
                        {#each deploymentCandidates as env}
                            <option value={env.id}
                                >{env.name} [{normalizeEnvStage(env)}] ({resolveEnvUrl(env)})</option
                            >
                        {/each}
                    </select>
                </div>
                {#if isProdTarget}
                    <p class="mb-3 rounded border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-800">
                        Внимание: выбрано PROD окружение. Потребуется подтверждение перед deploy.
                    </p>
                {/if}

                <div class="flex justify-end space-x-3">
                    <button
                        onclick={() => (show = false)}
                        class="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded"
                    >
                        {$t.common?.cancel}
                    </button>
                    <button
                        onclick={handleDeploy}
                        disabled={deploying || !selectedEnv}
                        class={`px-4 py-2 text-white rounded disabled:opacity-50 flex items-center ${isProdTarget ? 'bg-red-600 hover:bg-red-700' : 'bg-green-600 hover:bg-green-700'}`}
                    >
                        {#if deploying}
                            <svg
                                class="animate-spin -ml-1 mr-2 h-4 w-4 text-white"
                                xmlns="http://www.w3.org/2000/svg"
                                fill="none"
                                viewBox="0 0 24 24"
                            >
                                <circle
                                    class="opacity-25"
                                    cx="12"
                                    cy="12"
                                    r="10"
                                    stroke="currentColor"
                                    stroke-width="4"
                                ></circle>
                                <path
                                    class="opacity-75"
                                    fill="currentColor"
                                    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                                ></path>
                            </svg>
                            {$t.git?.deploying}
                        {:else}
                            {$t.git?.deploy}
                        {/if}
                    </button>
                </div>
            {/if}
        </div>
    </div>
{/if}
<!-- [/SECTION] -->

<!-- [/DEF:DeploymentModal:Component] -->
