<script setup lang="ts">
import { ref, onMounted } from "vue";
import { apiGet } from "@/api/client";
import { relativeTime } from "@/composables/useRelativeTime";

interface TaskRow { id: number; title: string; status: string; priority: string }
interface MilestoneBlock { id: number; title: string; progress_pct: number; open_tasks: TaskRow[] }
interface ActiveProject {
  id: number; title: string; color: string | null; last_activity: string;
  open_count: number; done_count: number; progress_pct: number;
  milestones: MilestoneBlock[]; no_milestone: TaskRow[];
}
interface DoneItem { id: number; title: string; project_title: string | null; completed_at: string }
interface WeekStats { completed_this_week: number; open_total: number; in_progress: number; active_plans: number }
interface IssueRow { id: number; title: string; status: string; priority: string; project_id: number | null; project_title: string | null }
interface DashboardData {
  active_projects: ActiveProject[];
  recently_completed: DoneItem[];
  open_issues: IssueRow[];
  week_stats: WeekStats;
}

const data = ref<DashboardData | null>(null);
const loading = ref(true);
const showAllDone = ref(false);
const DONE_VISIBLE = 5;

onMounted(async () => {
  try {
    data.value = await apiGet<DashboardData>("/api/dashboard");
  } catch {
    data.value = { active_projects: [], recently_completed: [], open_issues: [], week_stats: { completed_this_week: 0, open_total: 0, in_progress: 0, active_plans: 0 } };
  } finally {
    loading.value = false;
  }
});
</script>

<template>
  <div class="dash-root">
    <header class="dash-head">
      <h1>Dashboard</h1>
      <p class="dash-sub">What to work on, across your most-active projects.</p>
    </header>

    <div v-if="loading" class="dash-empty">Loading…</div>

    <template v-else-if="data">
      <!-- Done recently -->
      <section v-if="data.recently_completed.length" class="done-recent">
        <div class="dash-label">✓ Done recently</div>
        <router-link
          v-for="d in (showAllDone ? data.recently_completed : data.recently_completed.slice(0, DONE_VISIBLE))"
          :key="d.id"
          :to="`/tasks/${d.id}`"
          class="done-row"
        >
          <span class="done-mark">○</span>
          <span class="done-title">{{ d.title }}</span>
          <span class="done-meta">{{ d.project_title || "—" }} · {{ relativeTime(d.completed_at) }}</span>
        </router-link>
        <button
          v-if="data.recently_completed.length > DONE_VISIBLE"
          class="done-more"
          @click="showAllDone = !showAllDone"
        >
          {{ showAllDone ? "Show less" : `… ${data.recently_completed.length - DONE_VISIBLE} more` }}
        </button>
      </section>

      <div class="dash-cols">
        <!-- Active now -->
        <main class="dash-main">
          <div class="dash-label">Active now</div>

          <div v-if="!data.active_projects.length" class="dash-empty card">
            No active projects yet — <router-link to="/projects">create one</router-link>.
          </div>

          <article v-for="p in data.active_projects" :key="p.id" class="proj-panel">
            <header class="proj-head">
              <span class="proj-dot" :style="{ background: p.color || 'var(--fs-accent)' }" />
              <router-link :to="`/projects/${p.id}`" class="proj-title">{{ p.title }}</router-link>
              <span class="proj-meta">{{ relativeTime(p.last_activity) }} · {{ p.open_count }} open</span>
            </header>
            <div class="bar"><div class="bar-fill" :style="{ width: p.progress_pct + '%' }" /></div>

            <div v-for="m in p.milestones" :key="m.id" class="ms-block">
              <div class="ms-head">
                <span class="ms-title">{{ m.title }}</span>
                <span class="ms-pct">{{ m.progress_pct }}%</span>
              </div>
              <router-link
                v-for="t in m.open_tasks"
                :key="t.id"
                :to="`/tasks/${t.id}`"
                class="task-row"
                :class="{ 'task-inprogress': t.status === 'in_progress' }"
              >
                <span class="task-mark">{{ t.status === 'in_progress' ? '▸' : '○' }}</span>
                <span class="task-title">{{ t.title }}</span>
                <span v-if="t.priority !== 'none'" class="task-pri" :class="`pri-${t.priority}`">{{ t.priority }}</span>
              </router-link>
            </div>

            <div v-if="p.no_milestone.length" class="ms-block">
              <div class="ms-head"><span class="ms-title ms-none">No milestone</span></div>
              <router-link
                v-for="t in p.no_milestone"
                :key="t.id"
                :to="`/tasks/${t.id}`"
                class="task-row"
                :class="{ 'task-inprogress': t.status === 'in_progress' }"
              >
                <span class="task-mark">{{ t.status === 'in_progress' ? '▸' : '○' }}</span>
                <span class="task-title">{{ t.title }}</span>
                <span v-if="t.priority !== 'none'" class="task-pri" :class="`pri-${t.priority}`">{{ t.priority }}</span>
              </router-link>
            </div>

            <router-link :to="`/projects/${p.id}`" class="proj-more">+ more in {{ p.title }} →</router-link>
          </article>
        </main>

        <!-- Right rail -->
        <aside class="dash-rail">
          <template v-if="data.open_issues.length">
            <div class="dash-label">⚠ Open issues</div>
            <div class="rail-card issues-card">
              <router-link
                v-for="i in data.open_issues"
                :key="i.id"
                :to="`/tasks/${i.id}`"
                class="issue-row"
              >
                <span class="issue-mark" :class="`imk-${i.status}`">{{ i.status === 'in_progress' ? '▸' : '○' }}</span>
                <span class="issue-title">{{ i.title }}</span>
                <span class="issue-meta">{{ i.project_title || '—' }}</span>
              </router-link>
            </div>
          </template>

          <div class="dash-label">This week</div>
          <div class="rail-card stats">
            <span>✓ {{ data.week_stats.completed_this_week }} done</span>
            <span>○ {{ data.week_stats.open_total }} open</span>
            <span class="stats-sub">{{ data.week_stats.in_progress }} in progress · {{ data.week_stats.active_plans }} plans</span>
          </div>

          <template v-if="data.active_projects.length">
            <div class="dash-label">Projects</div>
            <div class="rail-card proj-stats">
              <router-link
                v-for="p in data.active_projects"
                :key="p.id"
                :to="`/projects/${p.id}`"
                class="pstat-row"
              >
                <span class="pstat-dot" :style="{ background: p.color || 'var(--fs-accent)' }" />
                <span class="pstat-title">{{ p.title }}</span>
                <span class="pstat-counts">{{ p.open_count }} open · {{ p.done_count }} done</span>
              </router-link>
            </div>
          </template>

          <div class="quick-add">
            <router-link to="/tasks/new" class="qa-btn">+ Task</router-link>
            <router-link to="/notes/new" class="qa-btn">+ Note</router-link>
            <router-link to="/notes/new?type=process" class="qa-btn">+ Process</router-link>
          </div>
        </aside>
      </div>
    </template>
  </div>
</template>

<style scoped>
.dash-root { max-width: 1100px; margin: 0 auto; padding: 1.5rem; }
/* `.dash-head` is deliberately bare: a block header whose two children carry
   all the spacing between them (h1 zeroed, .dash-sub margined). Nothing in it
   assumes a flex parent, which is the tell for a deleted rule (#2444). */
.dash-head h1 { margin: 0; font-family: 'Fraunces', Georgia, serif; }
.dash-sub { margin: 0.2rem 0 1.25rem; color: var(--fs-text-tertiary); font-size: 0.9rem; }
.dash-label { display: block; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--fs-text-tertiary); margin-bottom: 0.6rem; }
.dash-empty { color: var(--fs-text-tertiary); padding: 1rem 0; }
.dash-empty.card { padding: 1rem; border: 1px dashed var(--fs-border-color); border-radius: 10px; }

.done-recent { margin-bottom: 1.5rem; }
.done-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.55rem; border-radius: 7px; text-decoration: none; color: var(--fs-text-primary); font-size: 0.86rem; }
.done-row:hover { background: var(--fs-surface-hover); }
.done-mark { color: var(--fs-accent); flex-shrink: 0; }
.done-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.done-meta { font-size: 0.72rem; color: var(--fs-text-tertiary); white-space: nowrap; flex-shrink: 0; }
.done-more { background: none; border: none; cursor: pointer; margin-top: 0.25rem; padding: 0.2rem 0.55rem; font-size: 0.78rem; color: var(--fs-accent); font-family: inherit; }
.done-more:hover { text-decoration: underline; }

.dash-cols { display: flex; gap: 1.25rem; align-items: flex-start; }
.dash-main { flex: 1.7; min-width: 0; }
.dash-rail { flex: 1; min-width: 240px; }

.proj-panel { background: var(--fs-surface-hover); border: 1px solid var(--fs-border-color); border-radius: 12px; padding: 0.9rem 1rem; margin-bottom: 0.9rem; }
.proj-head { display: flex; align-items: center; gap: 0.5rem; }
.proj-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.proj-title { font-weight: 700; color: var(--fs-text-primary); text-decoration: none; }
.proj-title:hover { color: var(--fs-accent); }
.proj-meta { margin-left: auto; font-size: 0.74rem; color: var(--fs-text-tertiary); }
.bar { height: 5px; background: var(--fs-border-color); border-radius: 3px; margin: 0.55rem 0 0.2rem; }
.bar-fill { height: 5px; background: var(--fs-accent); border-radius: 3px; }

.ms-block { margin-top: 0.7rem; }
.ms-head { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.3rem; }
.ms-title { font-size: 0.82rem; font-weight: 600; color: var(--fs-text-primary); }
.ms-title.ms-none { color: var(--fs-text-tertiary); font-weight: 500; }
.ms-pct { margin-left: auto; font-size: 0.72rem; color: var(--fs-text-tertiary); }

.task-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.55rem; border-radius: 7px; text-decoration: none; color: var(--fs-text-primary); font-size: 0.86rem; }
.task-row:hover { background: var(--fs-surface-hover); }
.task-inprogress { border-left: 3px solid var(--fs-accent); padding-left: calc(0.55rem - 3px); }
.task-mark { color: var(--fs-text-tertiary); }
.task-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.task-pri { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; padding: 1px 6px; border-radius: 8px; border: 1px solid var(--fs-border-color); color: var(--fs-text-tertiary); }
.pri-high { color: #c0556b; border-color: #c0556b66; }
.proj-more { display: inline-block; margin-top: 0.6rem; font-size: 0.78rem; color: var(--fs-accent); text-decoration: none; }

.rail-card { background: var(--fs-surface-hover); border: 1px solid var(--fs-border-color); border-radius: 12px; padding: 0.7rem 0.85rem; margin-bottom: 1.25rem; }
.stats { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.9rem; }
.stats-sub { color: var(--fs-text-tertiary); font-size: 0.78rem; }
.proj-stats { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.4rem 0.45rem; }
.pstat-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.4rem; border-radius: 7px; text-decoration: none; color: var(--fs-text-primary); font-size: 0.85rem; }
.pstat-row:hover { background: var(--fs-surface-hover); }
.pstat-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.pstat-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.pstat-counts { font-size: 0.74rem; color: var(--fs-text-tertiary); white-space: nowrap; flex-shrink: 0; }
.quick-add { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.qa-btn { background: var(--fs-surface-hover); border: 1px solid var(--fs-border-color); border-radius: 8px; padding: 6px 12px; font-size: 0.82rem; color: var(--fs-text-primary); text-decoration: none; }
.qa-btn:hover { border-color: var(--fs-accent); color: var(--fs-accent); }

.issues-card { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.4rem 0.45rem; }
.issue-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.4rem; border-radius: 7px; text-decoration: none; color: var(--fs-text-primary); font-size: 0.85rem; }
.issue-row:hover { background: var(--fs-surface-hover); }
.issue-mark { color: var(--fs-text-tertiary); flex-shrink: 0; }
.issue-mark.imk-in_progress { color: var(--fs-accent); }
.issue-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.issue-meta { font-size: 0.72rem; color: var(--fs-text-tertiary); white-space: nowrap; flex-shrink: 0; }

@media (max-width: 760px) { .dash-cols { flex-direction: column; } }
</style>
