<script setup lang="ts">
/**
 * FlowBoard – Das neue V2 Dashboard
 *
 * Layout:
 *   Kompakter Status + priorisierte Live-Orchestrierung + kompakte Task-Zeile.
 *   Iris Chat bleibt standardmäßig verborgen und öffnet als Dialog.
 *
 * Datenquellen:
 *   - Vue Query OpenClaw overview: agents, sessions, models and runtime state
 *   - Vue Query task board: compact active-task strip and blocker state
 *   - AgentStore: local selection and modal activity only
 */
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { buildAgentDetail, useAgentStore } from '../../stores/agents'
import { useAgentActivityQuery } from '../../api/agentDetail'
import { useTaskBoard, type TaskBoardCardDto } from '../../api/taskBoard'
import {
  projectOpenClawAgentNodes,
  projectOpenClawModels,
  useOpenClawOverviewQuery,
} from '../../api/openclawRuntime'
import type { TaskItem } from '../../components/dashboard/v2/types'
import AlertBar from '../../components/dashboard/v2/AlertBar.vue'
import FlowCanvas from '../../components/dashboard/v2/FlowCanvas.vue'
import TaskStrip from '../../components/dashboard/v2/TaskStrip.vue'
import AgentDetailModal from '../../components/dashboard/v2/AgentDetailModal.vue'
import { useFlowBoardState } from '../../composables/useFlowBoardState'
import AsyncStatePanel from '../../components/mission-control/AsyncStatePanel.vue'

/* ── Stores ──────────────────────────────────────── */
const agentStore = useAgentStore()
const selectedAgentId = computed(() => agentStore.selectedAgentId ?? '')
const selectedAgentActivityQuery = useAgentActivityQuery(
  selectedAgentId,
  computed(() => Boolean(selectedAgentId.value)),
)
const taskBoard = useTaskBoard(50)
const overviewQuery = useOpenClawOverviewQuery()
const router = useRouter()
const agentNodes = computed(() => projectOpenClawAgentNodes(overviewQuery.data.value))
const availableModels = computed(() => projectOpenClawModels(overviewQuery.data.value))
const agentOrder = computed(() => [
  ...agentNodes.value.filter(agent => agent.id === 'iris'),
  ...agentNodes.value.filter(agent => agent.id !== 'iris'),
].map(agent => agent.id))
const selectedAgent = computed(() => {
  if (!agentStore.selectedAgentId) return null
  const agent = agentNodes.value.find(item => item.id === agentStore.selectedAgentId)
  if (!agent) return null
  return {
    ...buildAgentDetail(agent, availableModels.value),
    activity: (selectedAgentActivityQuery.data.value ?? [])
      .slice(0, 5)
      .map(item => ({
        time: item.relativeTime || new Date(item.at).toLocaleString('de-DE', {
          day: '2-digit',
          month: 'short',
          hour: '2-digit',
          minute: '2-digit',
        }),
        text: item.message,
      })),
  }
})
const activeCount = computed(() => agentNodes.value.filter(agent => agent.status === 'work').length)
const thinkCount = computed(() => agentNodes.value.filter(agent => agent.status === 'think').length)
const idleCount = computed(() => agentNodes.value.filter(agent => agent.status === 'idle').length)
const todayTokens = computed(() => {
  const total = agentNodes.value.reduce((sum, agent) => {
    if (!agent.tokens) return sum
    const value = Number.parseFloat(agent.tokens)
    if (!Number.isFinite(value)) return sum
    if (agent.tokens.includes('M')) return sum + value * 1_000_000
    if (agent.tokens.includes('k')) return sum + value * 1_000
    return sum + value
  }, 0)
  if (!total) return null
  return total >= 1000 ? `${Math.round(total / 1000)}k` : String(Math.round(total))
})

const flowAgentAdapter = {
  get agents() {
    return agentNodes.value
  },
  get models() {
    return availableModels.value
  },
  changeModel(agentId: string, modelId: string) {
    void agentStore.changeModel(agentId, modelId)
  },
  selectAgent(id: string | null) {
    agentStore.selectAgent(id)
  },
}

const {
  agentPositions,
  changeModel,
  closeAgent,
  enteringIds,
  resetLayout,
  selectAgent,
  updatePositions,
} = useFlowBoardState(flowAgentAdapter)

function mapTask(task: TaskBoardCardDto): TaskItem {
  const priority = task.priority.toLowerCase()
  const state = task.state.toLowerCase()
  return {
    id: task.id,
    title: task.title,
    agent: task.assignedTo ?? '—',
    priority: priority === 'high' || priority === 'critical' || priority === 'urgent'
      ? 'high'
      : priority === 'low' || priority === 'minor'
        ? 'low'
        : 'medium',
    status: state === 'blocked'
      ? 'blocked'
      : state === 'in progress' || state === 'active' || state === 'working'
        ? 'active'
        : 'pending',
    progress: state === 'blocked'
      ? 30
      : state === 'in progress' || state === 'active' || state === 'working'
        ? 50
        : 0,
    detail: task.detail,
    source: task.source,
  }
}

const activeCards = computed(() => [
  ...taskBoard.board.value.offen,
  ...taskBoard.board.value.inProgress,
  ...taskBoard.board.value.review,
  ...taskBoard.board.value.blocked,
])
const taskItems = computed(() => activeCards.value.map(mapTask))
const blockedTasks = computed(() =>
  activeCards.value.filter(task => task.state.toLowerCase() === 'blocked'),
)
function handleBlockerClick() {
  const blockedTask = blockedTasks.value[0]
  if (!blockedTask) return
  router.push(`/tasks/${encodeURIComponent(blockedTask.id)}`)
}

function blockerLabel() {
  const blockedTask = blockedTasks.value[0]
  if (!blockedTask) return undefined
  return `${blockedTasks.value.length} Blocker — ${blockedTask.title}`
}

function blockerCount() {
  return blockedTasks.value.length
}

</script>

<template>
  <div class="flow-board">
    <!-- Orchestration workspace -->
    <div class="board-body">
      <div class="stage">
        <AlertBar
          :active-count="activeCount"
          :think-count="thinkCount"
          :idle-count="idleCount"
          :blocker-count="blockerCount()"
          :today-cost="null"
          :today-tokens="todayTokens"
          :blocker-label="blockerLabel()"
          @blocker-click="handleBlockerClick"
        />

        <AsyncStatePanel
          v-if="overviewQuery.isPending.value && !agentNodes.length"
          class="orchestration-state"
          state="loading"
          title="Live-Orchestrierung wird geladen"
        />
        <AsyncStatePanel
          v-else-if="overviewQuery.error.value && !agentNodes.length"
          class="orchestration-state"
          state="offline"
          title="Live-Orchestrierung nicht erreichbar"
          :problem="overviewQuery.error.value"
          @action="overviewQuery.refetch()"
        />
        <FlowCanvas
          v-else
          :agents="agentNodes"
          :positions="agentPositions"
          :entering-ids="enteringIds"
          @select="selectAgent"
          @reset-layout="resetLayout"
          @update-positions="updatePositions"
        />

        <TaskStrip
          :tasks="taskItems"
          :loading="taskBoard.query.isLoading.value"
          :error="taskBoard.query.error.value"
          @retry="taskBoard.query.refetch()"
        />
      </div>
    </div>

    <!-- Agent Detail Modal -->
    <AgentDetailModal
      v-if="selectedAgent"
      :agent="selectedAgent"
      :agent-order="agentOrder"
      @close="closeAgent"
      @select="selectAgent"
      @change-model="changeModel"
    />
  </div>
</template>

<style scoped>
.flow-board {
  height: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
  animation: fade-in 0.35s ease-out;
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

.board-body {
  flex: 1;
  display: flex;
  padding: 12px 20px;
  overflow: hidden;
  min-height: 0;
}

.stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

.orchestration-state {
  flex: 1;
  align-content: center;
}

@media (max-width: 767px) {
  .board-body {
    padding: 8px;
  }

  .stage {
    flex: 1;
  }
}
</style>
