<!-- #region BackupManager [C:3] [TYPE Component] [SEMANTICS backup, orchestrator, schedule, crud, manager] -->
<!-- @BRIEF Component component: components/backups/BackupManager.svelte -->
<!-- @LAYER UI -->
<!--
@SEMANTICS: backup, manager, orchestrator
@PURPOSE:   Main container for backup management, handling creation and listing.
@LAYER     Feature
@RELATION  USES -> [BackupList]
@RELATION  USES -> [EXT:frontend:api]

@INVARIANT: Only one backup task can be triggered at a time from the UI.
-->

<script lang="ts">
  // [SECTION: IMPORTS]
  import { onMount } from 'svelte';
  import { t } from '$lib/i18n/index.svelte.js';
  import { api, requestApi } from '../../lib/api';
  import { addToast } from '$lib/toasts.svelte.js';
  import { Button, Card, Select, Input } from '../../lib/ui';
  import BackupList from './BackupList.svelte';
  import type { Backup } from '../../types/backup';
  // [/SECTION]

  // [SECTION: STATE]
  let backups: Backup[] = $state([]);
  let environments: any[] = $state([]);
  let selectedEnvId = $state('');
  let loading = $state(true);
  let creating = $state(false);
  let savingSchedule = $state(false);
  let currentPath = $state('backups');

  // Schedule state for selected environment
  let scheduleEnabled = $state(false);
  let cronExpression = $state('0 0 * * *');
  let selectedEnv = $derived(
    environments.find((environment) => environment.id === selectedEnvId),
  );

  $effect(() => {
    if (!selectedEnv) return;
    scheduleEnabled = selectedEnv.backup_schedule?.enabled ?? false;
    cronExpression =
      selectedEnv.backup_schedule?.cron_expression ?? '0 0 * * *';
  });
  // [/SECTION]

  // #region loadData:Function [TYPE Function]
  /**
   * @purpose Loads backups and environments from the backend.
   *
   * @pre     API must be reachable.
   * @post    environments and backups stores are populated.
   *
   * @returns {Promise<void>}
   * @side_effect Updates local state variables.
   */
  // @RELATION CALLS -> api.getEnvironmentsList
  // @RELATION CALLS -> api.requestApi
  function getSubpath(path: string): string {
    if (!path || path === 'backups') return '';
    return path.replace(/^backups\/?/, '');
  }

  function normalizeBackupsPath(path: string): string {
    const trimmed = (path || '').trim().replace(/^\/+|\/+$/g, '');
    if (!trimmed) return 'backups';
    return trimmed.startsWith('backups') ? trimmed : `backups/${trimmed}`;
  }

  async function loadData() {
    console.log("[EXT:frontend:BackupManager][Entry] Loading data.");
    loading = true;
    try {
      const subpath = getSubpath(currentPath);
      const filesUrl = subpath
        ? `/storage/files?category=backups&path=${encodeURIComponent(subpath)}`
        : '/storage/files?category=backups';

      const [envsData, storageData] = await Promise.all([
        api.getEnvironmentsList(),
        requestApi(filesUrl)
      ]);
      environments = envsData;
      // Pre-fill with active environment from global context
      if (!selectedEnvId) {
        const { get } = await import('svelte/store');
        const envCtx = await import('$lib/stores/environmentContext.svelte.js');
        const state = get(envCtx.environmentContextStore);
        if (state.selectedEnvId && environments.some((env) => env.id === state.selectedEnvId)) {
          selectedEnvId = state.selectedEnvId;
        }
      }

      backups = (storageData || []).map((file: any) => ({
        id: file.path,
        name: file.name,
        path: file.path,
        environment: file.path.split('/')[1] || $t.common?.unknown,
        created_at: file.created_at,
        size_bytes: file.size,
        is_directory: file.mime_type === 'directory',
        status: 'success'
      }));
      console.log("[EXT:frontend:BackupManager][Action] Data loaded successfully.");
    } catch (error) {
      console.error("[EXT:frontend:BackupManager][Coherence:Failed] Load failed", error);
    } finally {
      loading = false;
    }
  }
  // #endregion loadData:Function

  // #region handleCreateBackup:Function [TYPE Function]
  /**
   * @purpose Triggers a new backup task for the selected environment.
   *
   * @pre     selectedEnvId must be a valid environment ID.
   * @post    A new task is created on the backend.
   *
   * @returns {Promise<void>}
   * @side_effect Dispatches a toast notification.
   */
  // @RELATION CALLS -> api.createTask
  // #region handleUpdateSchedule:Function [TYPE Function]
  /**
   * @purpose Updates the backup schedule for the selected environment.
   * @pre     selectedEnvId must be set.
   * @post    Environment config is updated on the backend.
   */
  async function handleUpdateSchedule() {
    if (!selectedEnvId) return;

    console.log(`[EXT:frontend:BackupManager][Action] Updating schedule for env: ${selectedEnvId}`);
    savingSchedule = true;
    try {
      await api.updateEnvironmentSchedule(selectedEnvId, {
        enabled: scheduleEnabled,
        cron_expression: cronExpression
      });
      addToast($t.common.success, 'success');
      
      // Update local state
      environments = environments.map(e =>
        e.id === selectedEnvId
          ? { ...e, backup_schedule: { enabled: scheduleEnabled, cron_expression: cronExpression } }
          : e
      );
    } catch (error) {
      console.error("[EXT:frontend:BackupManager][Coherence:Failed] Schedule update failed", error);
    } finally {
      savingSchedule = false;
    }
  }
  // #endregion handleUpdateSchedule:Function

  async function handleCreateBackup() {
    if (!selectedEnvId) {
      addToast($t.tasks.select_env, 'error');
      return;
    }

    console.log(`[EXT:frontend:BackupManager][Action] Triggering backup for env: ${selectedEnvId}`);
    creating = true;
    try {
      await api.createTask('superset-backup', { environment_id: selectedEnvId });
      addToast($t.common.success, 'success');
      console.log("[EXT:frontend:BackupManager][Coherence:OK] Backup task triggered.");
    } catch (error) {
      console.error("[EXT:frontend:BackupManager][Coherence:Failed] Create failed", error);
    } finally {
      creating = false;
    }
  }
  // #endregion handleCreateBackup:Function

  function handleNavigate(path: string) {
    currentPath = normalizeBackupsPath(path);
    loadData();
  }

  function handleNavigateUp() {
    if (currentPath === 'backups') return;
    const parts = currentPath.split('/');
    parts.pop();
    currentPath = parts.join('/') || 'backups';
    loadData();
  }

  onMount(loadData);
</script>

<!-- [SECTION: TEMPLATE] -->
<div class="space-y-6">
  <Card title={$t.tasks.manual_backup}>
    <div class="space-y-4">
      <div class="flex items-end gap-4">
        <div class="flex-1">
          <Select
            label={$t.tasks.target_env}
            bind:value={selectedEnvId}
            options={[
              { value: '', label: $t.tasks.select_env },
              ...environments.map(e => ({ value: e.id, label: e.name }))
            ]}
          />
        </div>
        <Button
          variant="primary"
          onclick={handleCreateBackup}
          disabled={creating || !selectedEnvId}
        >
          {creating ? $t.common.loading : $t.tasks.start_backup}
        </Button>
      </div>

      {#if selectedEnvId}
        <div class="pt-6 border-t border-gray-100 mt-4">
          <h3 class="text-sm font-semibold text-gray-800 mb-4 flex items-center gap-2">
            <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
            </svg>
            {$t.tasks.backup_schedule}
          </h3>
          
          <div class="bg-gray-50 rounded-lg p-4 border border-gray-200">
            <div class="flex flex-col md:flex-row md:items-start gap-6">
              <div class="pt-8">
                <label class="flex items-center gap-3 cursor-pointer group">
                  <div class="relative inline-flex items-center">
                    <input type="checkbox" bind:checked={scheduleEnabled} class="sr-only peer" />
                    <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-primary-ring rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
                    <span class="ml-3 text-sm font-medium text-gray-700 group-hover:text-gray-900 transition-colors">{$t.tasks.schedule_enabled}</span>
                  </div>
                </label>
              </div>

              <div class="flex-1 space-y-2">
                <Input
                  label={$t.tasks.cron_label}
                  placeholder="0 0 * * *"
                  bind:value={cronExpression}
                  disabled={!scheduleEnabled}
                />
                <p class="text-xs text-gray-500 italic">{$t.tasks.cron_hint}</p>
              </div>

              <div class="pt-8">
                <Button
                  variant="secondary"
                  onclick={handleUpdateSchedule}
                  disabled={savingSchedule}
                  class="min-w-[100px]"
                >
                  {#if savingSchedule}
                    <span class="flex items-center gap-2">
                      <svg class="animate-spin h-4 w-4" viewBox="0 0 24 24">
                        <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></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.common.loading}
                    </span>
                  {:else}
                    {$t.common.save}
                  {/if}
                </Button>
              </div>
            </div>
          </div>
        </div>
      {/if}
    </div>
  </Card>

  <div class="space-y-3">
    <h2 class="text-lg font-semibold text-gray-700">{$t.storage.backups}</h2>
    {#if loading}
      <div class="py-10 text-center text-gray-500">{$t.common.loading}</div>
    {:else}
      <BackupList
        {backups}
        {currentPath}
        onNavigate={handleNavigate}
        onNavigateUp={handleNavigateUp}
      />
    {/if}
  </div>
</div>
<!-- [/SECTION] -->

<!-- #endregion BackupManager -->
