<script setup lang="ts">
import { ref, onMounted, watch, computed } from 'vue'
import { RouterLink, useRoute, useRouter } from 'vue-router'
import { api, ApiError } from '@/api/client'
import type { Category, Paginated, ProjectListRow, ProjectStatus, Wrapped } from '@/types/api'
import ProjectCard from '@/components/ProjectCard.vue'
import LoadingState from '@/components/LoadingState.vue'
import ErrorState from '@/components/ErrorState.vue'

const route = useRoute()
const router = useRouter()

// État
const categories = ref<Category[]>([])
const projects = ref<ProjectListRow[]>([])
const totalProjects = ref(0)
const loading = ref(true)
const error = ref<string | null>(null)

// Filtres lus depuis la query string -> source de vérité = l'URL.
const filterCategory = computed(() => (route.query.category as string) || '')
const filterStatus = computed(() => (route.query.status as string) || '')
const filterQ = computed(() => (route.query.q as string) || '')
const searchInput = ref(filterQ.value)

function updateQuery(patch: Record<string, string | null>) {
  const next: Record<string, string> = {}
  for (const [k, v] of Object.entries({ ...route.query, ...patch })) {
    if (v && typeof v === 'string') next[k] = v
  }
  router.replace({ name: 'projects', query: next })
}

async function loadCategories() {
  try {
    const r = await api.get<Wrapped<Category>>('/api/categories')
    categories.value = r.data
  } catch {
    /* silencieux : on garde les filtres sans label de catégorie. */
  }
}

async function loadProjects() {
  loading.value = true
  error.value = null
  try {
    const r = await api.get<Paginated<ProjectListRow>>('/api/projects', {
      query: {
        category: filterCategory.value || undefined,
        status: filterStatus.value || undefined,
        q: filterQ.value || undefined,
        per_page: 50,
      },
    })
    projects.value = r.data
    totalProjects.value = r.meta.total
  } catch (e) {
    error.value = e instanceof ApiError ? (e.payload.message ?? e.code) : 'Erreur réseau'
  } finally {
    loading.value = false
  }
}

onMounted(async () => {
  await Promise.all([loadCategories(), loadProjects()])
})

// Re-fetch quand un filtre change dans l'URL (back/forward, RouterLink externe).
watch(() => [filterCategory.value, filterStatus.value, filterQ.value], loadProjects)

// Recherche : on debounce 250ms.
let searchTimer: number | undefined
function onSearchInput() {
  window.clearTimeout(searchTimer)
  searchTimer = window.setTimeout(() => {
    updateQuery({ q: searchInput.value || null })
  }, 250)
}

const STATUSES: { value: ProjectStatus | ''; label: string }[] = [
  { value: '',          label: 'Tous les statuts' },
  { value: 'active',    label: 'Actifs' },
  { value: 'completed', label: 'Réalisés' },
  { value: 'archived',  label: 'Archivés' },
]
</script>

<template>
  <section class="px-10 py-8 max-w-7xl">
    <header class="flex items-start justify-between gap-4 flex-wrap">
      <div>
        <h1 class="text-3xl font-semibold text-donut-text">Projets Actifs</h1>
        <p class="text-donut-muted mt-1">Découvrez et rejoignez les initiatives de la communauté.</p>
      </div>
      <RouterLink
        :to="{ name: 'project-new' }"
        class="flex items-center gap-1.5 bg-donut-text text-white rounded-lg px-3.5 py-2 text-sm font-medium hover:bg-black transition-colors"
      >
        <svg viewBox="0 0 24 24" class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
          <path d="M12 5v14M5 12h14" />
        </svg>
        Nouveau Projet
      </RouterLink>
    </header>

    <!-- Filtres -->
    <div class="mt-6 flex items-center gap-3 flex-wrap">
      <div class="flex items-center gap-2 bg-donut-surface border border-donut-border rounded-lg px-3 py-2 flex-1 min-w-[240px] max-w-md">
        <svg viewBox="0 0 24 24" class="w-4 h-4 text-donut-muted" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>
        </svg>
        <input
          v-model="searchInput"
          @input="onSearchInput"
          type="search"
          placeholder="Rechercher un projet…"
          class="flex-1 bg-transparent text-sm outline-none placeholder:text-donut-muted"
        />
      </div>

      <select
        :value="filterCategory"
        @change="updateQuery({ category: ($event.target as HTMLSelectElement).value || null })"
        class="bg-donut-surface border border-donut-border rounded-lg px-3 py-2 text-sm outline-none focus:border-donut-text"
      >
        <option value="">Toutes les catégories</option>
        <option v-for="c in categories" :key="c.id" :value="c.slug">{{ c.name }}</option>
      </select>

      <select
        :value="filterStatus"
        @change="updateQuery({ status: ($event.target as HTMLSelectElement).value || null })"
        class="bg-donut-surface border border-donut-border rounded-lg px-3 py-2 text-sm outline-none focus:border-donut-text"
      >
        <option v-for="s in STATUSES" :key="s.value" :value="s.value">{{ s.label }}</option>
      </select>
    </div>

    <!-- Liste -->
    <div class="mt-6">
      <LoadingState v-if="loading" />
      <ErrorState v-else-if="error" :message="error" :retry="loadProjects" />
      <div v-else-if="projects.length === 0" class="text-donut-muted text-center py-16">
        Aucun projet ne correspond aux critères.
      </div>
      <div v-else>
        <div class="text-xs text-donut-muted mb-4">
          {{ totalProjects }} projet{{ totalProjects > 1 ? 's' : '' }} trouvé{{ totalProjects > 1 ? 's' : '' }}
        </div>
        <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
          <ProjectCard v-for="p in projects" :key="p.id" :project="p" />
        </div>
      </div>
    </div>
  </section>
</template>
