<!-- #region ReposPage [C:3] [TYPE Page] [SEMANTICS sveltekit, git, repository, dashboard, environment] -->
<!-- @BRIEF Page component: routes/storage/repos/+page.svelte -->
<!-- @LAYER Page -->
<!--
@SEMANTICS: git, repository, dashboard, environment
@PURPOSE:   Dashboard management page for Git integration (moved from /git).
@LAYER     UI (Page)
@RELATION  DEPENDS_ON -> [EXT:frontend:RepositoryDashboardGrid]
@RELATION  DEPENDS_ON -> [EXT:frontend:api]
@INVARIANT: Dashboard grid is always shown when an environment is selected.
-->

<!-- @UX_STATE Loading -> Showing spinner while fetching environments/dashboards. -->
<!-- @UX_STATE Idle -> Showing dashboard grid with repository filter. -->
<!-- @UX_FEEDBACK Toast error messages on fetch failure. -->
<!-- @UX_RECOVERY Environment selection refreshes the dashboard list. -->
<script lang="ts">
  /**
   * @UX_STATE: Loading -> Showing spinner while fetching environments/dashboards.
   * @UX_STATE: Idle -> Showing dashboard grid with actions.
   * @UX_FEEDBACK: Toast -> Error messages on fetch failure.
   * @UX_RECOVERY: Environment Selection -> Switch environment to retry loading.
   */
  import { onMount } from 'svelte';
  import RepositoryDashboardGrid from '../../../components/RepositoryDashboardGrid.svelte';
  import { addToast as toast } from '$lib/toasts.svelte.js';
  import { api } from '$lib/api.js';
  import { gitService } from '../../../services/gitService.js';
  import type { DashboardMetadata } from '$lib/types/dashboard';
  import { t } from '$lib/i18n/index.svelte.js';
  import { Button, Card, PageHeader, Select } from '$lib/ui';
  import {
    environmentContextStore,
    initializeEnvironmentContext,
    setSelectedEnvironment,
  } from '$lib/stores/environmentContext.svelte.js';

  let selectedEnvId = $state("");
  let dashboards: DashboardMetadata[] = $state([]);
  let loading = $state(true);
  let fetchingDashboards = $state(false);
  let environments = $derived(
    environmentContextStore.value?.environments || [],
  );

  // #region fetchEnvironments:Function [TYPE Function]
  /**
   * @PURPOSE: Fetches the list of available environments.
   * @PRE: None.
   * @POST: environments array is populated, selectedEnvId is set to first env if available.
   */
  async function fetchEnvironments() {
    try {
      await initializeEnvironmentContext();
      selectedEnvId = environmentContextStore.value?.selectedEnvId || "";
    } catch (e) {
      toast(e.message, 'error');
    } finally {
      loading = false;
    }
  }
  // #endregion fetchEnvironments:Function

  // #region fetchDashboards:Function [TYPE Function]
  /**
   * @PURPOSE: Fetches dashboards for a specific environment.
   * @PRE: envId is a valid environment ID.
   * @POST: dashboards array is populated with metadata for the selected environment.
   */
  async function fetchDashboards(envId: string) {
    if (!envId) return;
    fetchingDashboards = true;
    try {
      const pageSize = 100;
      let page = 1;
      let aggregatedDashboards: DashboardMetadata[] = [];
      let totalPages = 1;

      while (page <= totalPages) {
        const response = await api.requestApi(
          `/dashboards?env_id=${encodeURIComponent(envId)}&page=${page}&page_size=${pageSize}`,
        );
        const pageDashboards = Array.isArray(response?.dashboards)
          ? response.dashboards
          : [];
        aggregatedDashboards = aggregatedDashboards.concat(pageDashboards);
        totalPages = Number(response?.total_pages || 1);
        page += 1;
      }

      dashboards = await filterDashboardsWithRepositories(aggregatedDashboards);
    } catch (e) {
      toast(e.message, 'error');
      dashboards = [];
    } finally {
      fetchingDashboards = false;
    }
  }
  // #endregion fetchDashboards:Function

  // #region filterDashboardsWithRepositories:Function [TYPE Function]
  /**
   * @PURPOSE: Keep only dashboards that already have initialized Git repositories.
   * @PRE: dashboards list is loaded for selected environment.
   * @POST: Returns dashboards with status != NO_REPO.
   */
  async function filterDashboardsWithRepositories(
    allDashboards: DashboardMetadata[],
  ): Promise<DashboardMetadata[]> {
    if (allDashboards.length === 0) return [];

    const chunkSize = 50;
    const repositoryDashboardIds = new Set<number>();
    const allIds = allDashboards.map((dashboard) => dashboard.id);

    for (let offset = 0; offset < allIds.length; offset += chunkSize) {
      const idsChunk = allIds.slice(offset, offset + chunkSize);
      try {
        const batchResponse = await gitService.getStatusesBatch(idsChunk);
        const statuses = batchResponse?.statuses || {};
        idsChunk.forEach((dashboardId) => {
          const status = statuses[dashboardId] || statuses[String(dashboardId)];
          const syncStatus = String(status?.sync_status || status?.sync_state || "").toUpperCase();
          if (syncStatus && syncStatus !== "NO_REPO") {
            repositoryDashboardIds.add(dashboardId);
          }
        });
      } catch (error) {
        console.error(
          `[StorageReposPage][Coherence:Failed] Failed to resolve repository statuses chunk: ${error?.message || error}`,
        );
      }
    }

    return allDashboards.filter((dashboard) =>
      repositoryDashboardIds.has(dashboard.id),
    );
  }
  // #endregion filterDashboardsWithRepositories:Function

  onMount(fetchEnvironments);

  $effect(() => {
    const storeSelectedEnvId = environmentContextStore.value?.selectedEnvId || "";
    if (storeSelectedEnvId && selectedEnvId !== storeSelectedEnvId) {
      selectedEnvId = storeSelectedEnvId;
    }
  });

  $effect(() => {
    if (!selectedEnvId) return;
    setSelectedEnvironment(selectedEnvId);
    void fetchDashboards(selectedEnvId);
  });
</script>

<div class="max-w-6xl mx-auto p-6">
  <PageHeader title={$t.nav?.repositories }>
    <div slot="actions" class="flex items-center space-x-4">
      <Select
        label={$t.dashboard?.environment }
        bind:value={selectedEnvId}
        options={environments.map(e => ({ value: e.id, label: e.name }))}
      />
    </div>
  </PageHeader>

  {#if loading}
    <div class="flex justify-center py-12">
      <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
    </div>
  {:else}
    <Card title={$t.nav?.repositories || "Репозитории"}>
      {#if fetchingDashboards}
        <p class="text-gray-500">{$t.common?.loading }</p>
      {:else if dashboards.length > 0}
        <RepositoryDashboardGrid {dashboards} statusMode="repository" envId={selectedEnvId || null} repositoriesOnly={true} />
      {:else}
        <p class="text-gray-500 italic">{$t.git?.no_repositories_selected || "Репозитории не найдены"}</p>
      {/if}
    </Card>
  {/if}
</div>
<!-- #endregion ReposPage -->
