<!-- #region HealthCenterPage [C:5] [TYPE Page] [SEMANTICS sveltekit, health, matrix, dashboard-cards, validation, environment] -->
<!-- @BRIEF Dashboard Health Center — clickable health matrix + card-based dashboard list with integrated schedule.
     Cards replace the old table; matrix clicks filter the list. -->
<!-- @LAYER Page -->
<!-- @RELATION DEPENDS_ON -> [HealthMatrix] -->
<!-- @RELATION DEPENDS_ON -> [ScheduleAtAGlance] -->
<!-- @RELATION CALLS -> [EXT:frontend:api_module] -->
<script lang="ts">
  import { onMount } from 'svelte';
  import { SvelteSet } from 'svelte/reactivity';
  import HealthMatrix from '$lib/components/health/HealthMatrix.svelte';
  import ScheduleAtAGlance from '$lib/components/health/ScheduleAtAGlance.svelte';
  import { getHealthSummary, getEnvironments, getConsolidatedSettings, requestApi } from '$lib/api.js';
  import { healthStore } from '$lib/stores/health.svelte.js';
  import { t } from '$lib/i18n/index.svelte.js';
  import { addToast } from '$lib/toasts.svelte.js';
  import { formatDistanceToNow } from 'date-fns';

  interface HealthItem {
    record_id?: string;
    dashboard_id: string;
    dashboard_slug?: string;
    dashboard_title?: string;
    dashboard_name?: string;
    environment_id: string;
    status: string;
    last_check: string;
    task_id?: string;
    run_id?: string;
    policy_id?: string;
    summary?: string;
    execution_path?: string;
    issues_count?: number;
    timings?: Record<string, unknown>;
    chunk_count?: number;
  }

  let healthData = $state<{
    items: HealthItem[];
    pass_count: number;
    warn_count: number;
    fail_count: number;
    unknown_count: number;
  }>({ items: [], pass_count: 0, warn_count: 0, fail_count: 0, unknown_count: 0 });
  let environments = $state<Array<{ id: string; name?: string }>>([]);
  let selectedEnvId = $state('');
  let appTimezone = $state('Europe/Moscow');
  let loading = $state(true);
  let error = $state<string | null>(null);
  let deletingReportIds = new SvelteSet<string>();
  let activeStatusFilter = $state('');

  // Derived: filtered items based on matrix selection
  let filteredItems = $derived(
    activeStatusFilter
      ? healthData.items.filter((item) => item.status === activeStatusFilter)
      : healthData.items
  );

  async function loadData() {
    loading = true;
    error = null;
    try {
      const summaryPromise = selectedEnvId
        ? getHealthSummary(selectedEnvId)
        : healthStore.refresh();
      const [summary, envs, consolidated] = await Promise.all([
        summaryPromise,
        getEnvironments(),
        getConsolidatedSettings().catch(() => ({ app_timezone: 'Europe/Moscow' }))
      ]);
      healthData = summary as typeof healthData;
      environments = envs as Array<{ id: string; name?: string }>;
      appTimezone = consolidated.app_timezone || 'Europe/Moscow';
      if (!selectedEnvId && envs.length > 0) {
        const { get } = await import('svelte/store');
        const envCtx = await import('$lib/stores/environmentContext.svelte.js');
        const state = get(envCtx.environmentContextStore);
        if (state.selectedEnvId && envs.some((e: { id: string }) => e.id === state.selectedEnvId)) {
          selectedEnvId = state.selectedEnvId;
        }
      }
    } catch (e: unknown) {
      error = e instanceof Error ? e.message : String(e);
    } finally {
      loading = false;
    }
  }

  onMount(() => { loadData(); });

  function handleEnvChange(e: Event) {
    selectedEnvId = (e.target as HTMLSelectElement).value;
    loadData();
  }

  function handleMatrixSelect(status: string) {
    activeStatusFilter = status;
  }

  async function handleDeleteReport(item: HealthItem) {
    if (!item?.record_id || deletingReportIds.has(item.record_id)) return;
    const slug = item.dashboard_slug || item.dashboard_name || item.dashboard_id;
    if (!confirm(($t.health?.delete_confirm || 'Delete report for {slug}?').replace('{slug}', slug))) return;

    deletingReportIds.add(item.record_id);
    try {
      await requestApi(`/health/summary/${item.record_id}`, 'DELETE');
      addToast(($t.health?.delete_success || 'Report for {slug} deleted').replace('{slug}', slug), 'success');
      await loadData();
    } catch (e: unknown) {
      addToast(($t.health?.delete_failed || 'Failed to delete: {error}').replace('{error}', e instanceof Error ? e.message : 'Unknown'), 'error');
    } finally {
      deletingReportIds.delete(item.record_id);
    }
  }

  function formatRelativeDate(ts: string): string {
    return formatDistanceToNow(new Date(ts), { addSuffix: true });
  }

  function getStatusBadge(status: string): string {
    switch (status) {
      case 'PASS': return 'bg-green-100 text-green-800 ring-1 ring-green-300';
      case 'WARN': return 'bg-yellow-100 text-yellow-800 ring-1 ring-yellow-300';
      case 'FAIL': return 'bg-red-100 text-red-800 ring-1 ring-red-300';
      default: return 'bg-gray-100 text-gray-600 ring-1 ring-gray-200';
    }
  }
</script>

<div class="max-w-7xl mx-auto px-4 py-6">
  <!-- Header -->
  <div class="flex flex-col sm:flex-row sm:items-center justify-between mb-6 gap-4">
    <div>
      <h1 class="text-2xl font-bold text-gray-900">{$t.health?.title || 'Dashboard Health Center'}</h1>
      <p class="text-sm text-gray-500 mt-1">{$t.health?.subtitle || 'Monitor the latest validation status across your environments.'}</p>
    </div>
    <div class="flex items-center gap-3">
      <select
        value={selectedEnvId}
        onchange={handleEnvChange}
        class="w-44 px-3 py-2 text-sm border-gray-300 rounded-lg bg-white shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
      >
        <option value="">{$t.health?.all_environments || 'All'}</option>
        {#each environments as env (env.id)}
          <option value={env.id}>{env.name || env.id}</option>
        {/each}
      </select>
      <button
        onclick={loadData}
        disabled={loading}
        class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium rounded-lg text-white bg-indigo-600 hover:bg-indigo-700 disabled:opacity-50 transition-colors"
      >
        <svg class="w-4 h-4" class:animate-spin={loading} fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
        </svg>
        {$t.common?.refresh || 'Refresh'}
      </button>
    </div>
  </div>

  <!-- Clickable Health Matrix -->
  <HealthMatrix
    pass_count={healthData.pass_count}
    warn_count={healthData.warn_count}
    fail_count={healthData.fail_count}
    unknown_count={healthData.unknown_count}
    selectedFilter={activeStatusFilter}
    onSelect={handleMatrixSelect}
    {loading}
    {error}
  />

  <!-- Schedule (compact) -->
  <div class="mt-5">
    <ScheduleAtAGlance
      healthItems={healthData.items}
      {selectedEnvId}
      {appTimezone}
    />
  </div>

  <!-- Dashboard Cards -->
  <div class="mt-5">
    <div class="flex items-center justify-between mb-3">
      <h2 class="text-sm font-semibold text-gray-500 uppercase tracking-wider">
        {$t.health?.validation_details || 'Dashboards'}
        {#if activeStatusFilter}
          <span class="font-normal normal-case text-gray-400"> · filtered by {activeStatusFilter}</span>
        {/if}
      </h2>
      <span class="text-xs text-gray-400">{filteredItems.length} {filteredItems.length === 1 ? 'dashboard' : 'dashboards'}</span>
    </div>

    {#if loading}
      <div class="space-y-3">
        {#each Array(4) as _, i (i)}
          <div class="animate-pulse bg-white border border-gray-200 rounded-xl p-5">
            <div class="flex items-center justify-between mb-3">
              <div class="h-5 bg-gray-100 rounded w-48"></div>
              <div class="h-6 bg-gray-100 rounded-full w-16"></div>
            </div>
            <div class="h-4 bg-gray-100 rounded w-full mb-2"></div>
            <div class="h-4 bg-gray-100 rounded w-3/4"></div>
          </div>
        {/each}
      </div>
    {:else if filteredItems.length === 0}
      <div class="bg-white border-2 border-dashed border-gray-200 rounded-xl p-12 text-center">
        <svg class="w-12 h-12 mx-auto mb-3 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
        </svg>
        <p class="text-sm text-gray-400">{$t.health?.no_records || 'No validation records found'}</p>
        {#if activeStatusFilter}
          <button onclick={() => { activeStatusFilter = ''; }} class="mt-3 text-xs text-indigo-600 hover:text-indigo-800 underline">
            {$t.validation?.clear_filters || 'Clear filter'}
          </button>
        {/if}
      </div>
    {:else}
      <div class="space-y-3">
        {#each filteredItems as item (item.record_id || item.dashboard_id)}
          <div class="bg-white border border-gray-200 rounded-xl p-5 hover:border-gray-300 hover:shadow-sm transition-all">
            <!-- Card top: name + status + last check -->
            <div class="flex items-start justify-between mb-3">
              <div class="min-w-0 flex-1">
                <div class="flex items-center gap-2 flex-wrap">
                  <a
                    href={`/dashboards/${encodeURIComponent(String(item.dashboard_slug || item.dashboard_id))}?env_id=${encodeURIComponent(item.environment_id)}`}
                    class="text-base font-semibold text-gray-900 hover:text-indigo-600 hover:underline truncate"
                  >
                    {item.dashboard_name || item.dashboard_title || item.dashboard_slug || item.dashboard_id}
                  </a>
                  <a
                    href={`/dashboards/${encodeURIComponent(String(item.dashboard_id))}/validation?env_id=${encodeURIComponent(item.environment_id)}`}
                    class="inline-flex items-center gap-0.5 text-[11px] text-gray-400 hover:text-indigo-600 transition-colors flex-shrink-0"
                    title="View full validation history"
                  >
                    <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
                    </svg>
                    {$t.health?.view_history || 'History'}
                  </a>
                  <span class="text-[10px] text-gray-400 font-mono">{item.environment_id}</span>
                </div>
              </div>
              <div class="flex items-center gap-2 flex-shrink-0 ml-3">
                <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold {getStatusBadge(item.status)}">{item.status}</span>
              </div>
            </div>

            <!-- Card meta: path, issues, chunks, time -->
            <div class="flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-gray-500 mb-2">
              {#if item.execution_path === 'screenshot'}
                <span class="inline-flex items-center gap-1"><span class="text-gray-400">📷</span> Screenshot</span>
              {:else if item.execution_path === 'text_only'}
                <span class="inline-flex items-center gap-1"><span class="text-gray-400">📝</span> Text</span>
              {:else}
                <span>—</span>
              {/if}
              <span>·</span>
              {#if item.issues_count != null}
                <span class="font-medium" class:text-red-600={item.status === 'FAIL'} class:text-yellow-600={item.status === 'WARN'}>
                  {item.issues_count} issue{item.issues_count !== 1 ? 's' : ''}
                </span>
              {:else}
                <span>—</span>
              {/if}
              {#if item.chunk_count != null}
                <span>·</span>
                <span>{item.chunk_count} chunk{item.chunk_count > 1 ? 's' : ''}</span>
              {/if}
              <span>·</span>
              <span class="text-gray-400">{formatRelativeDate(item.last_check)}</span>
            </div>

            <!-- Summary -->
            {#if item.summary}
              <p class="text-sm text-gray-600 line-clamp-2 mb-3 leading-relaxed">{item.summary}</p>
            {/if}

            <!-- Card actions -->
            <div class="flex items-center gap-3 pt-1">
              {#if item.policy_id && item.run_id}
                <a
                  href={`/validation-tasks/${encodeURIComponent(item.policy_id)}/runs/${encodeURIComponent(item.run_id)}`}
                  class="inline-flex items-center gap-1 text-xs font-medium text-indigo-600 hover:text-indigo-800 transition-colors"
                >
                  <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
                  </svg>
                  {$t.health?.view_report || 'Open Report'}
                </a>
              {:else if item.task_id}
                <a
                  href={`/reports/llm/${item.task_id}`}
                  class="inline-flex items-center gap-1 text-xs font-medium text-indigo-600 hover:text-indigo-800 transition-colors"
                >
                  {$t.health?.view_report || 'Open Report'}
                </a>
              {/if}
              <button
                type="button"
                class="inline-flex items-center gap-1 text-xs text-gray-400 hover:text-red-600 transition-colors ml-auto"
                onclick={() => handleDeleteReport(item)}
                disabled={deletingReportIds.has(item.record_id!)}
              >
                <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                </svg>
                {deletingReportIds.has(item.record_id!) ? '...' : $t.common?.delete || 'Delete'}
              </button>
            </div>
          </div>
        {/each}
      </div>
    {/if}
  </div>
</div>
<!-- #endregion HealthCenterPage -->
