import { ref } from 'vue'
import { defineStore } from 'pinia'
import { useActivity } from '@/composables/useActivity'
import {
  dayGroupKo,
  escapeHtml,
  monthDayKo,
  relativeTimeKo,
} from '@/shared/utils/format'
import type { ApiActivity } from '@/types/activity'
import type { ProjectActivityDay, ProjectActivityItem } from '@/mock/relay.mock'

// payload(자유형)에서 문자열 값 안전 추출
function pstr(payload: Record<string, unknown>, key: string): string {
  const v = payload[key]
  return typeof v === 'string' ? v : ''
}

// 행위자/시간 등 공통 필드
function baseOf(
  api: ApiActivity,
): Pick<ProjectActivityItem, 'avatarUrl' | 'actorId' | 'actorName' | 'time'> {
  return {
    avatarUrl: api.actor?.avatarUrl ?? null,
    actorId: api.actor?.id ?? null,
    actorName: api.actor?.name ?? null,
    time: relativeTimeKo(api.createdAt),
  }
}

// API 활동 → 화면용 ProjectActivityItem (type+payload 로 톤/아이콘/문구 조립)
// 사용자 입력(이름/제목/파일명/표시명)은 escapeHtml 로 감싸 XSS 를 방지한다.
function toProjectActivityItem(api: ApiActivity): ProjectActivityItem {
  const base = baseOf(api)
  const actor = escapeHtml(api.actor?.name ?? '알 수 없음')
  const p = api.payload
  const title = escapeHtml(pstr(p, 'taskTitle'))
  const target = escapeHtml(pstr(p, 'targetName'))

  switch (api.type) {
    case 'project.created':
      return { ...base, tone: 'setting', icon: 'repo', html: `<b>${actor}</b>님이 프로젝트를 생성했습니다` }
    case 'project.renamed':
      return {
        ...base,
        tone: 'setting',
        icon: 'pencil',
        html: `<b>${actor}</b>님이 표시 제목을 ‘${escapeHtml(pstr(p, 'newName'))}’(으)로 변경했습니다`,
      }
    case 'member.invited':
      return { ...base, tone: 'member', icon: 'member-add', html: `<b>${actor}</b>님이 <b>${target}</b>님을 멤버로 초대했습니다` }
    case 'member.role_changed':
      return {
        ...base,
        tone: 'member',
        icon: 'member-check',
        html: `<b>${target}</b>님의 역할이 <b>${pstr(p, 'roleType') === 'admin' ? '관리자' : '멤버'}</b>(으)로 변경되었습니다`,
      }
    case 'member.removed':
      return { ...base, tone: 'member', icon: 'member-remove', html: `<b>${actor}</b>님이 <b>${target}</b>님을 멤버에서 제거했습니다` }
    case 'task.created':
      return { ...base, tone: 'task', icon: 'pencil', html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무를 지시했습니다` }
    case 'task.status_changed': {
      // 알림·업무 상세 활동 탭과 동일한 행위 중심 문구(from→to 로 파생)
      const from = pstr(p, 'statusFrom')
      const to = pstr(p, 'statusTo')
      const tgt = `<span class="tgt">${title}</span>`
      if (to === 'prog') {
        const verb = from === 'changes' ? '다시 시작' : '시작'
        return { ...base, tone: 'task', icon: 'check', html: `<b>${actor}</b>님이 ${tgt} 업무를 <span class="st prog">${verb}</span>했습니다` }
      }
      if (to === 'review') {
        return { ...base, tone: 'task', icon: 'check', html: `<b>${actor}</b>님이 ${tgt} 업무의 승인을 요청했습니다` }
      }
      if (to === 'changes') {
        return { ...base, tone: 'task', icon: 'check', html: `<b>${actor}</b>님이 ${tgt} 업무의 수정을 요청했습니다` }
      }
      if (to === 'done') {
        return { ...base, tone: 'task', icon: 'check', html: `<b>${actor}</b>님이 ${tgt} 업무를 <span class="st done">완료(승인)</span>했습니다` }
      }
      return { ...base, tone: 'task', icon: 'check', html: `<b>${actor}</b>님이 ${tgt} 업무의 상태를 변경했습니다` }
    }
    case 'task.comment_added':
      return { ...base, tone: 'task', icon: 'check', html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무에 댓글을 남겼습니다` }
    case 'task.file_attached':
      return {
        ...base,
        tone: 'task',
        icon: 'check',
        html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무에 파일 <b>${escapeHtml(pstr(p, 'fileName'))}</b>을(를) 첨부했습니다`,
      }
    case 'task.assignees_changed':
      return { ...base, tone: 'task', icon: 'pencil', html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무의 담당자를 변경했습니다` }
    case 'task.due_changed': {
      const due = pstr(p, 'dueDate')
      const body = due
        ? `마감기한을 <b>${escapeHtml(monthDayKo(due))}</b>(으)로 설정했습니다`
        : `마감기한을 해제했습니다`
      return { ...base, tone: 'task', icon: 'pencil', html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무의 ${body}` }
    }
    case 'task.edited':
      return { ...base, tone: 'task', icon: 'pencil', html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무를 수정했습니다` }
    case 'task.file_removed':
      return {
        ...base,
        tone: 'task',
        icon: 'pencil',
        html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무의 첨부 <b>${escapeHtml(pstr(p, 'fileName'))}</b>을(를) 삭제했습니다`,
      }
    case 'task.removed':
      return { ...base, tone: 'task', icon: 'pencil', html: `<b>${actor}</b>님이 <span class="tgt">${title}</span> 업무를 삭제했습니다` }
    default:
      return { ...base, tone: 'task', icon: 'check', html: `<b>${actor}</b>님의 활동` }
  }
}

// 활동 스토어 — 프로젝트 활동 피드(날짜 그룹)
export const useActivityStore = defineStore('activity', () => {
  const days = ref<ProjectActivityDay[]>([])
  const loading = ref(false)

  const activityApi = useActivity()

  // 프로젝트 활동 조회 → 날짜 그룹으로 묶기(목록은 최신순이라 같은 날은 연속)
  async function fetch(projectId: string): Promise<void> {
    loading.value = true
    try {
      const list = await activityApi.list(projectId)
      const groups: ProjectActivityDay[] = []
      let current: ProjectActivityDay | null = null
      for (const a of list) {
        const day = dayGroupKo(a.createdAt)
        if (!current || current.day !== day) {
          current = { day, items: [] }
          groups.push(current)
        }
        current.items.push(toProjectActivityItem(a))
      }
      days.value = groups
    } finally {
      loading.value = false
    }
  }

  return { days, loading, fetch }
})
