import { computed, ref } from 'vue'
import { defineStore } from 'pinia'
import { useTask } from '@/composables/useTask'
import { toAbsoluteApiUrl } from '@/composables/useApi'
import { DEFAULT_PAGE_SIZE } from '@/types/pagination'
import {
  escapeHtml,
  formatBytes,
  monthDayKo,
  relativeTimeKo,
  taskDueInfo,
  taskStatusLabel,
} from '@/shared/utils/format'
import type {
  ApiMember,
} from '@/types/repo'
import type {
  ApiAttachment,
  ApiComment,
  ApiProjectTask,
  ApiTaskDetail,
  ChecklistReviewItem,
  CreateTaskPayload,
  TaskListQuery,
  TaskSegmentCounts,
  UpdateTaskPayload,
} from '@/types/task'
import type { ApiActivity } from '@/types/activity'
import type {
  Activity as ActivityView,
  Attachment as AttachmentView,
  Comment as CommentView,
  ChecklistWorkStatus,
  ProjectTask as ProjectTaskView,
  TaskDetail as TaskDetailView,
  TaskStatus,
  User as UserView,
} from '@/mock/relay.mock'

// API 멤버 → 화면용 User(이니셜/색상 파생)
function toUserView(m: ApiMember): UserView {
  return {
    id: m.id,
    name: m.name,
    role: m.role ?? '',
    avatarUrl: m.avatarUrl,
  }
}

// 지시자 없음(SET NULL) 대비 폴백 사용자
const UNKNOWN_USER: UserView = {
  id: '',
  name: '알 수 없음',
  role: '',
}

// API 업무 목록 행 → 화면용 ProjectTask
function toProjectTaskView(api: ApiProjectTask): ProjectTaskView {
  const due = taskDueInfo(api.dueDate, api.status === 'done')
  const [, total] = api.checklist
  return {
    id: api.id,
    title: api.title,
    status: api.status,
    dueLabel: due.listLabel || undefined,
    overdue: due.overdue || undefined,
    checklist: total > 0 ? api.checklist : undefined,
    comments: api.commentCount > 0 ? api.commentCount : undefined,
    files: api.fileCount > 0 ? api.fileCount : undefined,
    assignees: api.assignees.map(toUserView),
  }
}

// API 첨부 → 화면용 Attachment(바이트 → 표시 크기)
function toAttachmentView(a: ApiAttachment): AttachmentView {
  return {
    id: a.id,
    name: a.name,
    size: formatBytes(a.size),
    kind: a.kind,
    // 다운로드 앵커용 절대 URL(백엔드 오리진) — 상대경로면 프론트로 가서 404 페이지가 됨
    url: toAbsoluteApiUrl(a.url),
  }
}

// API 댓글 → 화면용 Comment(작성자/시간 파생, 지시자면 역할 배지)
function toCommentView(c: ApiComment, issuerId: string | null): CommentView {
  return {
    id: c.id,
    author: c.author ? toUserView(c.author) : UNKNOWN_USER,
    roleBadge: c.author && issuerId && c.author.id === issuerId ? '지시자' : undefined,
    time: relativeTimeKo(c.createdAt),
    text: c.text,
    file: c.file?.name,
    replies: c.replies.map((r) => ({
      id: r.id,
      author: r.author ? toUserView(r.author) : UNKNOWN_USER,
      time: relativeTimeKo(r.createdAt),
      text: r.text,
    })),
  }
}

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

// API 활동 → 업무 상세 활동 탭 뷰(Activity). 사용자 입력은 escapeHtml 로 안전 삽입
function toTaskActivityView(api: ApiActivity): ActivityView {
  const actor = escapeHtml(api.actor?.name ?? '알 수 없음')
  const p = api.payload
  const time = relativeTimeKo(api.createdAt)
  switch (api.type) {
    case 'task.created':
      return { tone: 'accent', icon: 'flag', html: `<b>${actor}</b>님이 업무를 생성했습니다`, time }
    case 'task.status_changed': {
      const from = pstr(p, 'statusFrom')
      const to = pstr(p, 'statusTo')
      if (to === 'review') {
        return {
          tone: 'amber',
          icon: 'check-circle',
          html: `<b>${actor}</b>님이 승인을 요청했습니다`,
          time,
          statusFrom: taskStatusLabel(from as TaskStatus),
          statusTo: taskStatusLabel(to as TaskStatus),
        }
      }
      if (to === 'done') {
        return { tone: 'green', icon: 'check', html: `<b>${actor}</b>님이 업무를 완료(승인)했습니다`, time }
      }
      if (to === 'changes') {
        return { tone: 'amber', icon: 'check-circle', html: `<b>${actor}</b>님이 수정을 요청했습니다`, time }
      }
      if (to === 'prog') {
        return {
          tone: 'blue',
          icon: 'flag',
          html: `<b>${actor}</b>님이 업무를 ${from === 'changes' ? '다시 진행' : '시작'}했습니다`,
          time,
        }
      }
      return { tone: '', icon: 'check', html: `<b>${actor}</b>님이 상태를 변경했습니다`, time }
    }
    case 'task.comment_added':
      return { tone: '', icon: 'check', html: `<b>${actor}</b>님이 댓글을 남겼습니다`, time }
    case 'task.file_attached':
      return { tone: '', icon: 'paperclip', html: `<b>${actor}</b>님이 파일을 첨부했습니다`, time, file: pstr(p, 'fileName') }
    case 'task.assignees_changed':
      return { tone: 'blue', icon: 'users', html: `<b>${actor}</b>님이 담당자를 변경했습니다`, time }
    case 'task.due_changed': {
      const due = pstr(p, 'dueDate')
      const body = due
        ? `마감기한을 <b>${escapeHtml(taskDueInfo(due, false).dateLabel)}</b>(으)로 설정했습니다`
        : '마감기한을 해제했습니다'
      return { tone: 'blue', icon: 'calendar', html: `<b>${actor}</b>님이 ${body}`, time }
    }
    case 'task.edited':
      return { tone: '', icon: 'check', html: `<b>${actor}</b>님이 업무를 수정했습니다`, time }
    case 'task.file_removed':
      return { tone: '', icon: 'paperclip', html: `<b>${actor}</b>님이 첨부 파일을 삭제했습니다`, time, file: pstr(p, 'fileName') }
    default:
      return { tone: '', icon: 'check', html: `<b>${actor}</b>님의 활동`, time }
  }
}

// API 업무 상세 → 화면용 TaskDetail
function toTaskDetailView(api: ApiTaskDetail): TaskDetailView {
  const due = taskDueInfo(api.dueDate, api.status === 'done')
  const issuerId = api.issuer?.id ?? null
  return {
    id: api.id,
    projectId: api.projectId,
    projectName: api.projectName,
    title: api.title,
    status: api.status,
    statusLabel: taskStatusLabel(api.status),
    content: api.content,
    checklist: api.checklist.map((c) => ({
      id: c.id,
      text: c.text,
      done: c.done,
      category: c.category,
      reviewNote: c.reviewNote,
      workStatus: c.workStatus,
    })),
    comments: api.comments.map((c) => toCommentView(c, issuerId)),
    activities: api.activities.map(toTaskActivityView),
    assignees: api.assignees.map(toUserView),
    issuer: api.issuer ? toUserView(api.issuer) : UNKNOWN_USER,
    dueLabel: due.dateLabel,
    dday: due.dday,
    dueAt: api.dueDate,
    files: api.files.map(toAttachmentView),
    approval: api.approval
      ? {
          requester: api.approval.requester?.name ?? '알 수 없음',
          requestedAgo: api.approval.requestedAt
            ? relativeTimeKo(api.approval.requestedAt)
            : '',
          note: api.approval.note ?? '',
        }
      : undefined,
    changesNote: api.changesNote ?? undefined,
    issuedLabel: `${monthDayKo(api.createdAt)} 지시 · #${api.id}`,
    checkpoints: api.checkpoints.map((c) => ({
      id: c.id,
      checkAt: c.checkAt,
      dateLabel: monthDayKo(c.checkAt),
    })),
    checkpointReports: api.checkpointReports.map((r) => ({
      id: r.id,
      checkpointId: r.checkpointId,
      reporterName: r.reporter?.name ?? '알 수 없음',
      note: r.note,
      items: r.items.map((it) => ({
        text: it.text,
        category: it.category,
        workStatus: it.workStatus,
      })),
      dateLabel: r.checkAt ? monthDayKo(r.checkAt) : '',
      timeLabel: relativeTimeKo(r.createdAt),
    })),
  }
}

// 업무 스토어 — 프로젝트 업무 목록 + 현재 상세 + CRUD/상태 액션
// 빈 세그먼트 카운트(초기값)
const EMPTY_COUNTS: TaskSegmentCounts = { all: 0, prog: 0, todo: 0, done: 0 }

export const useTaskStore = defineStore('task', () => {
  const tasks = ref<ProjectTaskView[]>([])
  const current = ref<TaskDetailView | null>(null)
  const loading = ref(false)
  // 목록 페이지네이션(더보기) + 세그먼트 카운트 상태
  const total = ref(0)
  const page = ref(0)
  const counts = ref<TaskSegmentCounts>({ ...EMPTY_COUNTS })
  const loadingMore = ref(false)
  const hasMore = computed(() => tasks.value.length < total.value)

  const taskApi = useTask()

  // 목록 첫 페이지 조회(리셋) — 세그먼트/검색은 백엔드에서 필터, 카운트도 응답에서 수신
  async function fetchList(projectId: string, query: TaskListQuery = {}): Promise<void> {
    loading.value = true
    try {
      const res = await taskApi.list(projectId, query, 1, DEFAULT_PAGE_SIZE)
      tasks.value = res.items.map(toProjectTaskView)
      total.value = res.total
      counts.value = res.counts
      page.value = 1
    } finally {
      loading.value = false
    }
  }

  // 다음 페이지 이어붙이기(더보기) — 같은 세그먼트/검색 조건 유지
  async function loadMore(projectId: string, query: TaskListQuery = {}): Promise<void> {
    if (loadingMore.value || !hasMore.value) return
    loadingMore.value = true
    try {
      const res = await taskApi.list(projectId, query, page.value + 1, DEFAULT_PAGE_SIZE)
      tasks.value.push(...res.items.map(toProjectTaskView))
      total.value = res.total
      counts.value = res.counts
      page.value += 1
    } finally {
      loadingMore.value = false
    }
  }

  // 단건 상세 조회
  async function fetchOne(projectId: string, taskId: number): Promise<TaskDetailView | null> {
    loading.value = true
    try {
      current.value = toTaskDetailView(await taskApi.get(projectId, taskId))
      return current.value
    } finally {
      loading.value = false
    }
  }

  // 생성 — 생성된 상세 반환
  async function create(projectId: string, payload: CreateTaskPayload): Promise<TaskDetailView> {
    const view = toTaskDetailView(await taskApi.create(projectId, payload))
    current.value = view
    return view
  }

  // 수정
  async function update(
    projectId: string,
    taskId: number,
    payload: UpdateTaskPayload,
  ): Promise<TaskDetailView> {
    const view = toTaskDetailView(await taskApi.update(projectId, taskId, payload))
    current.value = view
    return view
  }

  // 삭제 — 목록에서 제외하고 총계도 보정(세그먼트 카운트는 목록 재진입 시 재조회로 갱신)
  async function remove(projectId: string, taskId: number): Promise<void> {
    await taskApi.remove(projectId, taskId)
    const before = tasks.value.length
    tasks.value = tasks.value.filter((t) => t.id !== taskId)
    if (tasks.value.length < before) total.value = Math.max(0, total.value - 1)
    if (current.value?.id === taskId) current.value = null
  }

  // 상태 변경
  async function changeStatus(
    projectId: string,
    taskId: number,
    status: TaskDetailView['status'],
  ): Promise<TaskDetailView> {
    const view = toTaskDetailView(await taskApi.changeStatus(projectId, taskId, status))
    current.value = view
    return view
  }

  // 중간 점검 — 보고 전송(항목 상태 + 메모)
  async function submitCheckpointReport(
    projectId: string,
    taskId: number,
    checkpointId: string,
    items: { id: string; workStatus: ChecklistWorkStatus }[],
    note?: string,
  ): Promise<TaskDetailView> {
    const view = toTaskDetailView(
      await taskApi.submitCheckpointReport(projectId, taskId, checkpointId, items, note),
    )
    current.value = view
    return view
  }

  // 부속 변경 후 상세를 다시 받아 일관된 뷰로 갱신하는 공통 헬퍼
  async function refresh(projectId: string, taskId: number): Promise<TaskDetailView> {
    const view = toTaskDetailView(await taskApi.get(projectId, taskId))
    current.value = view
    return view
  }

  /* ===================== 댓글 / 답글 (5단계) ===================== */

  async function addComment(
    projectId: string,
    taskId: number,
    text: string,
  ): Promise<TaskDetailView> {
    await taskApi.addComment(projectId, taskId, text)
    return refresh(projectId, taskId)
  }

  async function addReply(
    projectId: string,
    taskId: number,
    commentId: string,
    text: string,
  ): Promise<TaskDetailView> {
    await taskApi.addReply(projectId, taskId, commentId, text)
    return refresh(projectId, taskId)
  }

  /* ===================== 승인 워크플로우 (5단계) ===================== */

  async function requestApproval(
    projectId: string,
    taskId: number,
    note?: string,
  ): Promise<TaskDetailView> {
    const view = toTaskDetailView(await taskApi.requestApproval(projectId, taskId, note))
    current.value = view
    return view
  }

  async function approve(projectId: string, taskId: number): Promise<TaskDetailView> {
    const view = toTaskDetailView(await taskApi.approve(projectId, taskId))
    current.value = view
    return view
  }

  async function requestChanges(
    projectId: string,
    taskId: number,
    note: string | undefined,
    checklist?: ChecklistReviewItem[],
  ): Promise<TaskDetailView> {
    const view = toTaskDetailView(
      await taskApi.requestChanges(projectId, taskId, note, checklist),
    )
    current.value = view
    return view
  }

  return {
    tasks,
    current,
    loading,
    total,
    counts,
    hasMore,
    loadingMore,
    fetchList,
    loadMore,
    fetchOne,
    create,
    update,
    remove,
    changeStatus,
    submitCheckpointReport,
    addComment,
    addReply,
    requestApproval,
    approve,
    requestChanges,
  }
})
