/**
 * Task Store – V2 Dashboard + Task Board
 *
 * Fetches tasks from /api/dashboard/tasks and /api/dashboard/tasks/board
 * and maps them into TaskItem[] format for the TaskStrip component.
 *
 * Board state: grouped by column (offen, inProgress, delegated, review, done, blocked)
 * Auto-refresh: every 30 seconds.
 */
import { defineStore } from 'pinia'
import { apiFetch } from '../services/api'
import type { TaskItem } from '../components/dashboard/v2/types'

/* ── API Response Shapes ──────────────────────────── */

export interface DashboardTaskDto {
  id: string
  title: string
  detail: string | null
  source: string
  state: string
  priority: string
  assignedTo: string | null
  parentTaskId?: string | null
  dueDate?: string | null
  createdAt: string
  updatedAt: string
  isAgentTask?: boolean
  expectedFrom?: string | null
}

export interface BoardGroup {
  offen: DashboardTaskDto[]
  inProgress: DashboardTaskDto[]
  delegated: DashboardTaskDto[]
  review: DashboardTaskDto[]
  done: DashboardTaskDto[]
  blocked: DashboardTaskDto[]
}

export interface AgentWorkflowOverview {
  waitingForBao: DashboardTaskDto[]
  waitingForIris: DashboardTaskDto[]
  waitingForOthers: DashboardTaskDto[]
  staleTasks: DashboardTaskDto[]
  staleThreshold: string
}

/* ── State Mapping ────────────────────────────────── */

function mapPriority(priority: string): TaskItem['priority'] {
  const p = priority.toLowerCase()
  if (p === 'high' || p === 'critical' || p === 'urgent') return 'high'
  if (p === 'low' || p === 'minor') return 'low'
  return 'medium'
}

function mapState(state: string): TaskItem['status'] {
  const s = state.toLowerCase()
  if (s === 'in progress' || s === 'active' || s === 'working') return 'active'
  if (s === 'blocked' || s === 'block') return 'blocked'
  return 'pending'
}

function mapProgress(state: string): number {
  const s = state.toLowerCase()
  if (s === 'in progress' || s === 'active' || s === 'working') return 50
  if (s === 'done') return 100
  if (s === 'blocked') return 30
  return 0
}

function mapTask(t: DashboardTaskDto): TaskItem {
  return {
    id: t.id,
    title: t.title,
    agent: t.assignedTo ?? '—',
    priority: mapPriority(t.priority),
    status: mapState(t.state),
    progress: mapProgress(t.state),
    detail: t.detail,
    source: t.source,
  }
}

export const useTaskStore = defineStore('tasks', {
  state: () => ({
    tasks: [] as TaskItem[],
    loading: false,
    error: null as string | null,
    refreshInterval: null as ReturnType<typeof setInterval> | null,
    boardRefreshInterval: null as ReturnType<typeof setInterval> | null,

    // Board state
    board: {
      offen: [] as DashboardTaskDto[],
      inProgress: [] as DashboardTaskDto[],
      delegated: [] as DashboardTaskDto[],
      review: [] as DashboardTaskDto[],
      done: [] as DashboardTaskDto[],
      blocked: [] as DashboardTaskDto[],
    } as BoardGroup,
    boardLoading: false,
    boardError: null as string | null,

    // Agent Workflow Overview (for Iris)
    agentOverview: null as AgentWorkflowOverview | null,
    agentOverviewLoading: false,
    agentOverviewError: null as string | null,
  }),

  getters: {
    taskList: (state) => state.tasks,

    // Iris helpers
    waitingForIrisTasks: (state) => state.agentOverview?.waitingForIris ?? [],
    waitingForBaoTasks: (state) => state.agentOverview?.waitingForBao ?? [],
    waitingForOthersTasks: (state) => state.agentOverview?.waitingForOthers ?? [],
    staleTasksList: (state) => state.agentOverview?.staleTasks ?? [],
    agentTaskCount: (state) => {
      if (!state.agentOverview) return 0
      return state.agentOverview.waitingForBao.length +
             state.agentOverview.waitingForIris.length +
             state.agentOverview.waitingForOthers.length +
             state.agentOverview.staleTasks.length
    },
  },

  actions: {
    /* ── API: Fetch tasks (for TaskStrip) ─────────── */
    async fetchTasks() {
      this.loading = true
      try {
        const res = await apiFetch('/api/dashboard/tasks')
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        const data: DashboardTaskDto[] = await res.json()
        this.tasks = data.map(mapTask)
        this.error = null
      } catch (err) {
        console.warn('[TaskStore] fetchTasks failed', err)
        this.error = 'Tasks could not be loaded'
      } finally {
        this.loading = false
      }
    },

    /* ── API: Fetch board (for TaskBoardView) ─────── */
    async fetchBoard() {
      this.boardLoading = true
      try {
        const res = await apiFetch('/api/dashboard/tasks/board')
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        const data: BoardGroup = await res.json()
        this.board = data
        this.boardError = null
      } catch (err) {
        console.warn('[TaskStore] fetchBoard failed', err)
        this.boardError = 'Board could not be loaded'
      } finally {
        this.boardLoading = false
      }
    },

    /* ── API: Move task (Drag & Drop) ─────────────── */
    async moveTask(id: string, newState: string) {
      // Map board group key to canonical state string for the API payload
      const canonicalMap: Record<string, string> = {
        offen: 'Backlog',
        inProgress: 'In progress',
        delegated: 'Delegated',
        review: 'Review',
        done: 'Done',
        blocked: 'Blocked',
      }

      // Save previous state for rollback
      const prevBoard = JSON.parse(JSON.stringify(this.board)) as BoardGroup

      // Optimistic: find the task in current board and move it
      const findAndRemove = (arr: DashboardTaskDto[]): DashboardTaskDto | null => {
        const idx = arr.findIndex(t => t.id === id)
        if (idx === -1) return null
        return arr.splice(idx, 1)[0]
      }

      const task =
        findAndRemove(this.board.offen) ??
        findAndRemove(this.board.inProgress) ??
        findAndRemove(this.board.delegated) ??
        findAndRemove(this.board.review) ??
        findAndRemove(this.board.blocked) ??
        findAndRemove(this.board.done)

      if (task) {
        const canonicalState = canonicalMap[newState] ?? newState
        task.state = canonicalState
        const targetKey = newState as keyof BoardGroup
        if (this.board[targetKey]) {
          this.board[targetKey].push(task)
        }
      }

      // Actually call API with the board group key (backend handles mapping)
      try {
        const res = await apiFetch(`/api/dashboard/tasks/${id}/move`, {
          method: 'PATCH',
          body: JSON.stringify({ state: newState }),
        })
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
      } catch (err) {
        console.warn('[TaskStore] moveTask failed, rolling back', err)
        this.board = prevBoard
      }
    },

    /* ── API: Create task ─────────────────────────── */
    async createTask(data: { title: string; detail?: string | null; priority?: string; assignedTo?: string }) {
      try {
        const res = await apiFetch('/api/dashboard/tasks', {
          method: 'POST',
          body: JSON.stringify({
            title: data.title,
            detail: data.detail ?? null,
            priority: data.priority ?? 'Medium',
            assignedTo: data.assignedTo ?? 'bao',
            source: 'bao',
          }),
        })
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        // Refresh board + task list
        await this.fetchBoard()
        await this.fetchTasks()
      } catch (err) {
        console.warn('[TaskStore] createTask failed', err)
        throw err
      }
    },

    /* ── API: Add task (for TaskStrip) ────────────── */
    async addTask(title: string, detail?: string, priority?: string, assignedTo?: string) {
      try {
        const res = await apiFetch('/api/dashboard/tasks', {
          method: 'POST',
          body: JSON.stringify({
            title,
            detail: detail ?? null,
            priority: priority ?? null,
            assignedTo: assignedTo ?? null,
            source: 'bao',
          }),
        })
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        // Refresh task list
        await this.fetchTasks()
      } catch (err) {
        console.warn('[TaskStore] addTask failed', err)
      }
    },

    /* ── API: Update task ─────────────────────────── */
    async updateTask(id: string, updates: { title?: string; detail?: string | null; priority?: string; assignedTo?: string | null; dueDate?: string | null }) {
      try {
        const res = await apiFetch(`/api/dashboard/tasks/${id}`, {
          method: 'PUT',
          body: JSON.stringify(updates),
        })
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        await this.fetchTasks()
        await this.fetchBoard()
      } catch (err) {
        console.warn('[TaskStore] updateTask failed', err)
        throw err
      }
    },

    async fetchTaskChildren(id: string) {
      try {
        const res = await apiFetch(`/api/dashboard/tasks/${id}/children`)
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        return await res.json() as DashboardTaskDto[]
      } catch (err) {
        console.warn('[TaskStore] fetchTaskChildren failed', err)
        throw err
      }
    },

    async fetchTaskActivity(id: string) {
      try {
        const res = await apiFetch(`/api/dashboard/tasks/${id}/activity`)
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        return await res.json() as Array<{ id?: string; message?: string; type?: string; createdAt?: string; timestamp?: string }>
      } catch (err) {
        console.warn('[TaskStore] fetchTaskActivity failed', err)
        throw err
      }
    },

    /* ── API: Fetch agent workflow overview ──────── */
    async fetchAgentOverview(staleHours = 2) {
      this.agentOverviewLoading = true
      try {
        const res = await apiFetch(`/api/dashboard/tasks/agent-overview?staleHours=${staleHours}`)
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        const data: AgentWorkflowOverview = await res.json()
        this.agentOverview = data
        this.agentOverviewError = null
      } catch (err) {
        console.warn('[TaskStore] fetchAgentOverview failed', err)
        this.agentOverviewError = 'Agent overview could not be loaded'
      } finally {
        this.agentOverviewLoading = false
      }
    },

    /* ── API: Create agent task ───────────────────── */
    async createAgentTask(data: {
      title: string
      detail?: string | null
      source?: string
      priority?: string
      assignedTo?: string
      expectedFrom?: string
    }) {
      try {
        const res = await apiFetch('/api/dashboard/tasks/agent', {
          method: 'POST',
          body: JSON.stringify({
            title: data.title,
            detail: data.detail ?? null,
            source: data.source ?? 'iris',
            priority: data.priority ?? 'Medium',
            assignedTo: data.assignedTo ?? null,
            expectedFrom: data.expectedFrom ?? null,
          }),
        })
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        await this.fetchBoard()
        await this.fetchAgentOverview()
        return await res.json() as DashboardTaskDto
      } catch (err) {
        console.warn('[TaskStore] createAgentTask failed', err)
        throw err
      }
    },

    /* ── Polling ──────────────────────────────────── */
    startPolling() {
      if (this.refreshInterval) return
      this.fetchTasks()
      this.refreshInterval = setInterval(() => {
        this.fetchTasks()
      }, 30000)
    },

    stopPolling() {
      if (this.refreshInterval) {
        clearInterval(this.refreshInterval)
        this.refreshInterval = null
      }
    },

    startBoardPolling() {
      if (this.boardRefreshInterval) return
      this.fetchBoard()
      this.boardRefreshInterval = setInterval(() => {
        this.fetchBoard()
      }, 30000)
    },

    stopBoardPolling() {
      if (this.boardRefreshInterval) {
        clearInterval(this.boardRefreshInterval)
        this.boardRefreshInterval = null
      }
    },
  },
})
