<script setup lang="ts">
// 프로젝트 상세 — 프로젝트 헤더(공통) + 진행률 + 서브탭(공통) + 업무 목록
// 세그먼트/검색은 백엔드에서 필터·카운트하고, 목록은 더보기(오프셋 페이지네이션)로 점진 로드한다.
import { computed, onBeforeUnmount, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useRoute, RouterLink } from 'vue-router'
import AppShell from '@/layouts/AppShell.vue'
import ProjectHeader from '@/components/ProjectHeader.vue'
import ProjectTabs from '@/components/ProjectTabs.vue'
import UserAvatar from '@/components/UserAvatar.vue'
import DropdownSelect from '@/components/DropdownSelect.vue'
import { useProjectStore } from '@/stores/project.store'
import { useTaskStore } from '@/stores/task.store'
import type { TaskListQuery, TaskSegment, TaskSort } from '@/types/task'
import type { Project, TaskStatus } from '@/mock/relay.mock'

const route = useRoute()
const projectId = computed(() => String(route.params.projectId))
const projectStore = useProjectStore()
const taskStore = useTaskStore()
const { tasks, counts, hasMore, loadingMore, loading } = storeToRefs(taskStore)

// 프로젝트 헤더/진행률 — API 연동
const repo = ref<Project | null>(null)
async function loadProject() {
  try {
    repo.value = await projectStore.fetchOne(projectId.value)
  } catch {
    repo.value = null // 404/403 등은 인터셉터가 알림 처리
  }
}

const keyword = ref('')
const segment = ref<TaskSegment>('all')
const sort = ref<TaskSort>('latest')
const SORT_OPTIONS: { value: TaskSort; label: string }[] = [
  { value: 'latest', label: '최신순' },
  { value: 'due', label: '마감 임박순' },
  { value: 'oldest', label: '오래된순' },
]

// 현재 세그먼트/검색/정렬 조건 → 목록 쿼리
function currentQuery(): TaskListQuery {
  const q = keyword.value.trim()
  return { segment: segment.value, sort: sort.value, ...(q ? { q } : {}) }
}

// 업무 목록 첫 페이지 — 세그먼트/검색 변경 시 리셋 로드
async function loadTasks() {
  try {
    await taskStore.fetchList(projectId.value, currentQuery())
  } catch {
    // 인터셉터가 알림 처리
  }
}

// 더보기 — 같은 조건으로 다음 페이지 이어붙이기
async function loadMoreTasks() {
  try {
    await taskStore.loadMore(projectId.value, currentQuery())
  } catch {
    // 인터셉터가 알림 처리
  }
}

// 프로젝트 전환 시 헤더 + 목록 리셋 로드
watch(
  projectId,
  () => {
    loadProject()
    loadTasks()
  },
  { immediate: true },
)

// 세그먼트/정렬 변경 시 목록만 리셋 로드(프로젝트 재조회 불필요)
watch([segment, sort], loadTasks)

// 검색어는 디바운스 후 리셋 로드(연속 입력 시 호출 폭주 방지)
let searchTimer: ReturnType<typeof setTimeout> | null = null
watch(keyword, () => {
  if (searchTimer) clearTimeout(searchTimer)
  searchTimer = setTimeout(loadTasks, 250)
})
onBeforeUnmount(() => {
  if (searchTimer) clearTimeout(searchTimer)
})

const memberCount = computed(() =>
  repo.value ? repo.value.members.length + repo.value.moreCount : 0,
)

// 빈 목록이 '검색/세그먼트로 걸러져 비었는지' 판별(빈 상태 문구 분기)
const isFiltered = computed(() => keyword.value.trim() !== '' || segment.value !== 'all')

// 지연 건수 — 현재 로드된 목록 기준(전역 정확 집계는 백엔드 미지원, 알려진 한계)
const overdueCount = computed(() => tasks.value.filter((t) => t.overdue).length)

// 업무 상태 → 배지 라벨
const STATUS_LABEL: Record<TaskStatus, string> = {
  prog: '진행 중',
  review: '승인 대기',
  todo: '대기',
  done: '완료',
  changes: '수정 요청',
}
</script>

<template>
  <AppShell>
    <div
      v-if="repo"
      class="page"
    >
      <div class="crumb">
        <RouterLink
          to="/projects"
          class="lnk"
        >
          프로젝트
        </RouterLink>
        <span class="sep">/</span>
        <b>{{ repo.name }}</b>
      </div>

      <!-- 프로젝트 헤더(공통) — 진행률 스트립을 extra 슬롯으로 주입 -->
      <ProjectHeader
        :repo="repo"
        :meta-text="repo.updatedAgo"
      >
        <template #extra>
          <div class="prog-strip">
            <span class="prog-txt">{{ repo.doneCount }} <span>/ {{ repo.totalCount }} 업무 완료</span> · {{ repo.progressPct }}%</span>
            <div class="pbar">
              <i :style="{ width: repo.progressPct + '%' }" />
            </div>
            <span
              v-if="overdueCount > 0"
              class="prog-warn"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              >
                <circle
                  cx="12"
                  cy="12"
                  r="9"
                /><path d="M12 7v5l3 2" />
              </svg>
              지연 {{ overdueCount }}건
            </span>
          </div>
        </template>
      </ProjectHeader>

      <!-- 서브탭(공통) -->
      <ProjectTabs
        :project-id="repo.id"
        active="tasks"
        :task-count="counts.all"
        :member-count="memberCount"
        :can-manage="repo.canManage"
      />

      <!-- 툴바 -->
      <div class="toolbar">
        <div class="search">
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
          >
            <circle
              cx="11"
              cy="11"
              r="7"
            /><path d="m21 21-4-4" />
          </svg>
          <input
            v-model="keyword"
            type="text"
            placeholder="업무 검색…"
          >
        </div>
        <div class="segmented">
          <button
            :class="{ active: segment === 'all' }"
            @click="segment = 'all'"
          >
            전체 <span class="n">{{ counts.all }}</span>
          </button>
          <button
            :class="{ active: segment === 'prog' }"
            @click="segment = 'prog'"
          >
            진행 중 <span class="n">{{ counts.prog }}</span>
          </button>
          <button
            :class="{ active: segment === 'todo' }"
            @click="segment = 'todo'"
          >
            대기 <span class="n">{{ counts.todo }}</span>
          </button>
          <button
            :class="{ active: segment === 'done' }"
            @click="segment = 'done'"
          >
            완료 <span class="n">{{ counts.done }}</span>
          </button>
        </div>
        <DropdownSelect
          v-model="sort"
          :options="SORT_OPTIONS"
          push-right
          align="right"
          aria-label="정렬"
        >
          <template #icon>
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            >
              <path d="M11 5h10M11 9h7M11 13h4M3 17l3 3 3-3M6 18V4" />
            </svg>
          </template>
        </DropdownSelect>
        <RouterLink
          v-if="repo.canManage"
          class="btn primary new-task"
          :to="`/projects/${repo.id}/tasks/new`"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2.2"
            stroke-linecap="round"
            stroke-linejoin="round"
          >
            <path d="M12 5v14M5 12h14" />
          </svg>
          새 업무
        </RouterLink>
      </div>

      <!-- 업무 목록 -->
      <div
        v-if="loading && tasks.length === 0"
        class="state-msg"
      >
        업무를 불러오는 중…
      </div>
      <div
        v-else-if="tasks.length === 0"
        class="state-msg"
      >
        {{ isFiltered ? '조건에 맞는 업무가 없습니다.' : '아직 등록된 업무가 없습니다. 새 업무를 지시해 보세요.' }}
      </div>
      <div
        v-else
        class="list"
      >
        <RouterLink
          v-for="task in tasks"
          :key="task.id"
          class="task-row"
          :class="{ 'is-done': task.status === 'done' }"
          :to="`/projects/${repo.id}/tasks/${task.id}`"
        >
          <span
            class="st-dot"
            :class="task.status"
          />
          <span class="task-main">
            <span class="task-title">{{ task.title }} <span class="tid">#{{ task.id }}</span></span>
            <span class="task-meta">
              <span
                v-if="task.overdue"
                class="mi overdue"
              >
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <circle
                    cx="12"
                    cy="12"
                    r="9"
                  /><path d="M12 7v5l3 2" />
                </svg>
                {{ task.dueLabel }}
              </span>
              <span
                v-else-if="task.status !== 'done' && task.dueLabel"
                class="mi"
              >
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <rect
                    x="3"
                    y="4"
                    width="18"
                    height="18"
                    rx="2"
                  /><path d="M16 2v4M8 2v4M3 10h18" />
                </svg>
                {{ task.dueLabel }}
              </span>
              <span
                v-if="task.checklist"
                class="mi"
              >
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <path d="M9 11l3 3L22 4" />
                  <path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" />
                </svg>
                {{ task.checklist[0] }}/{{ task.checklist[1] }}
              </span>
              <span
                v-if="task.comments"
                class="mi"
              >
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
                </svg>
                {{ task.comments }}
              </span>
              <span
                v-if="task.files"
                class="mi"
              >
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" />
                </svg>
                {{ task.files }}
              </span>
              <span
                v-if="task.status === 'done'"
                class="mi"
              >{{ task.dueLabel }}</span>
            </span>
          </span>
          <span class="task-right">
            <span class="avstack">
              <span
                v-for="a in task.assignees.slice(0, 3)"
                :key="a.id"
                class="avatar"
              ><UserAvatar
                :url="a.avatarUrl"
                :name="a.name"
              /></span>
              <span
                v-if="task.assignees.length > 3"
                class="avatar av-more"
              >+{{ task.assignees.length - 3 }}</span>
            </span>
            <span
              class="st-badge"
              :class="task.status"
            >{{ STATUS_LABEL[task.status] }}</span>
            <span class="chev">
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              >
                <path d="m9 18 6-6-6-6" />
              </svg>
            </span>
          </span>
        </RouterLink>
      </div>

      <!-- 더보기 -->
      <button
        v-if="hasMore"
        class="load-more"
        type="button"
        :disabled="loadingMore"
        @click="loadMoreTasks()"
      >
        {{ loadingMore ? '불러오는 중…' : '더보기' }}
      </button>
    </div>

    <!-- 프로젝트를 찾지 못한 경우 -->
    <div
      v-else
      class="page"
    >
      <p class="not-found-msg">
        요청하신 프로젝트를 찾을 수 없습니다.
      </p>
    </div>
  </AppShell>
</template>

<style scoped>
.crumb {
  padding: 1.125rem 0 0.75rem;
}
/* 진행률 스트립 (ProjectHeader 의 extra 슬롯에 주입 — 부모 스코프 스타일 적용) */
.prog-strip {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 1rem;
  padding-top: 0.9375rem;
  border-top: 1px solid var(--border);
}
.prog-strip .pbar {
  flex: 1;
  height: 0.5rem;
  max-width: 22.5rem;
}
.prog-txt {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.prog-txt span {
  color: var(--text-3);
  font-weight: 500;
}
.prog-warn {
  font-size: 0.781rem;
  font-weight: 600;
  color: var(--red);
  display: flex;
  align-items: center;
  gap: 0.3125rem;
  white-space: nowrap;
}
.prog-warn svg {
  width: 0.875rem;
  height: 0.875rem;
}

.toolbar .search {
  width: 15rem;
}
.new-task {
  /* 정렬 드롭다운(push-right)의 margin-left:auto 가 오른쪽 그룹을 밀어내므로 여기엔 auto 를 두지 않는다
     (이중 auto 는 여유 공간을 분배해 필터/정렬 버튼이 떨어져 보이는 원인) */
  border: none;
  text-decoration: none;
}
.new-task svg {
  width: 0.9375rem;
  height: 0.9375rem;
}

/* 업무 행 */
.task-row {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.875rem 1.125rem;
  border-top: 1px solid var(--border);
  cursor: pointer;
  text-decoration: none;
  color: inherit;
}
.task-row:first-child {
  border-top: none;
}
.task-row:hover {
  background: #fafbfc;
}
.task-main {
  flex: 1;
  min-width: 0;
}
.task-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.task-title .tid {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-3);
}
.task-row.is-done .task-title {
  color: var(--text-2);
}
.task-meta {
  display: flex;
  align-items: center;
  gap: 0.8125rem;
  margin-top: 0.1875rem;
  font-size: 0.75rem;
  color: var(--text-3);
}
.task-meta .mi {
  display: flex;
  align-items: center;
  gap: 0.3125rem;
  white-space: nowrap;
}
.task-meta .mi svg {
  width: 0.8125rem;
  height: 0.8125rem;
}
.task-meta .mi.overdue {
  color: var(--red);
  font-weight: 600;
}
.task-right {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  flex-shrink: 0;
}
.task-right .st-badge {
  min-width: 3.5rem;
  border: 1px solid transparent;
}
.task-right .st-badge.done {
  border-color: var(--green-border);
}
.task-right .st-badge.prog {
  border-color: var(--blue-border);
}
.task-right .st-badge.review {
  border-color: var(--amber-border);
}
.task-right .st-badge.todo {
  border-color: var(--border);
}
.chev {
  color: var(--text-3);
  display: grid;
  place-items: center;
}
.chev svg {
  width: 1.125rem;
  height: 1.125rem;
}
.not-found-msg {
  padding: 3rem 0;
  text-align: center;
  color: var(--text-2);
}
.state-msg {
  padding: 2.5rem 1.125rem;
  text-align: center;
  font-size: 0.844rem;
  color: var(--text-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #fff;
}
</style>
