<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { Bot, CheckCircle2, Clock3, MessageSquareText, Send, ShieldAlert, Zap, ChevronLeft, ChevronRight, Edit2, Save, X, Trash2 } from '@lucide/vue'
import type { AgentInfo, OperationsSnapshot, RoutingTarget } from '../types'
import { TASK_STATES } from '../types'
import { apiFetch } from '../services/api'
import { useAuthStore } from '../stores/auth'
import { useOperationsStore, type PendingApprovalTask } from '../stores/operations'

const props = defineProps<{ view: string; snapshot: OperationsSnapshot; routing: RoutingTarget[] }>()
const emit = defineEmits<{
  createProject: [name: string]
  createTask: [title: string, priority: string]
  updateTaskState: [id: string, state: string]
}>()
const store = useOperationsStore()
const auth = useAuthStore()
const agents = ref<AgentInfo[]>([])
const agentsLoading = ref(false)
const pendingApprovals = ref<PendingApprovalTask[]>([])
const pendingApprovalsLoading = ref(false)
const pendingApprovalsError = ref('')
const canModerateApprovals = computed(() => auth.user?.role === 'owner')

async function loadAgents() {
  if (agentsLoading.value) return
  agentsLoading.value = true
  agents.value = await store.fetchAgents()
  agentsLoading.value = false
}

async function loadPendingApprovals() {
  if (!canModerateApprovals.value) {
    pendingApprovals.value = []
    pendingApprovalsError.value = ''
    return
  }

  pendingApprovalsLoading.value = true
  pendingApprovalsError.value = ''
  try {
    pendingApprovals.value = await store.fetchPendingApprovals()
  } catch (e) {
    pendingApprovalsError.value = e instanceof Error ? e.message : 'Failed to load pending approvals'
  } finally {
    pendingApprovalsLoading.value = false
  }
}

onMounted(() => {
  if (props.view === 'Agents') loadAgents()
  if (props.view === 'Task Board') void loadPendingApprovals()
})

watch(() => props.view, (v) => {
  if (v === 'Agents') loadAgents()
  if (v === 'Task Board') void loadPendingApprovals()
})

watch(canModerateApprovals, (value) => {
  if (props.view !== 'Task Board') return
  if (value) {
    void loadPendingApprovals()
    return
  }

  pendingApprovals.value = []
  pendingApprovalsError.value = ''
})

const newProject = ref('')
const newTask = ref('')
const message = ref('')
const chatMessages = ref<Array<{ role: 'owner' | 'iris' | 'error'; content: string }>>([])
const chatPending = ref(false)
const conversationId = ref(localStorage.getItem('nexus-conversation-id') ?? crypto.randomUUID())
localStorage.setItem('nexus-conversation-id', conversationId.value)

// Task editing state
const editingTaskId = ref<string | null>(null)

// Task approval / rejection state
const approvingTaskId = ref<string | null>(null)
const taskActionError = ref('')

async function handleApproveTask(id: string) {
  approvingTaskId.value = id
  taskActionError.value = ''
  try {
    await store.approveTask(id)
    pendingApprovals.value = pendingApprovals.value.filter(task => task.id !== id)
  } catch (e) {
    taskActionError.value = e instanceof Error ? e.message : 'Failed to approve task'
  } finally {
    approvingTaskId.value = null
  }
}

async function handleRejectTask(id: string) {
  approvingTaskId.value = id
  taskActionError.value = ''
  try {
    await store.rejectTask(id)
    pendingApprovals.value = pendingApprovals.value.filter(task => task.id !== id)
  } catch (e) {
    taskActionError.value = e instanceof Error ? e.message : 'Failed to reject task'
  } finally {
    approvingTaskId.value = null
  }
}

// Task deletion state
const deletingTaskId = ref<string | null>(null)
const deleteError = ref('')

async function confirmDeleteTask(id: string) {
  deleteError.value = ''
  try {
    await store.deleteTask(id)
    deletingTaskId.value = null
  } catch (e) {
    deleteError.value = e instanceof Error ? e.message : 'Failed to delete task'
  }
}

function cancelDeleteTask() {
  deletingTaskId.value = null
  deleteError.value = ''
}
const editTaskTitle = ref('')
const editTaskPriority = ref('')
const editTaskProjectId = ref<string | null>(null)

// Activity filtering and pagination
const activityTypeFilter = ref('')
const activitySort = ref('newest')
const activityPage = ref(1)
const activityPageSize = 20
const activityTotalPages = ref(1)
const activityTotalCount = ref(0)

const columns = computed(() =>
  TASK_STATES.map(state => ({ name: state, items: props.snapshot.tasks.filter(x => x.state === state) })))

const availableTypes = computed(() => {
  const types = new Set(props.snapshot.activity.map(e => e.type))
  return Array.from(types)
})

const filteredActivity = computed(() => {
  let items = [...props.snapshot.activity]
  if (activityTypeFilter.value) {
    items = items.filter(e => e.type === activityTypeFilter.value)
  }
  if (activitySort.value === 'oldest') {
    items.reverse()
  }
  const total = items.length
  activityTotalCount.value = total
  activityTotalPages.value = Math.max(1, Math.ceil(total / activityPageSize))
  const start = (activityPage.value - 1) * activityPageSize
  return items.slice(start, start + activityPageSize)
})

watch(activityTypeFilter, () => { activityPage.value = 1 })
watch(activitySort, () => { activityPage.value = 1 })

function startEditTask(task: { id: string; title: string; priority: string; projectId?: string | null }) {
  editingTaskId.value = task.id
  editTaskTitle.value = task.title
  editTaskPriority.value = task.priority
  editTaskProjectId.value = task.projectId ?? null
}

async function saveEditTask(id: string) {
  try {
    await store.updateTask(id, {
      title: editTaskTitle.value.trim() || undefined,
      priority: editTaskPriority.value || undefined,
      projectId: editTaskProjectId.value || undefined,
    })
    editingTaskId.value = null
  } catch (e) {
    console.error('Failed to update task', e)
  }
}

function cancelEditTask() {
  editingTaskId.value = null
}

async function sendMessage() {
  const value = message.value.trim()
  if (!value || chatPending.value) return
  chatMessages.value.push({ role: 'owner', content: value })
  message.value = ''
  chatPending.value = true
  try {
    const response = await apiFetch('/api/v1/chat', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ message: value, conversationId: conversationId.value, agentId: 'iris' }),
    })
    const payload = await response.json()
    if (!response.ok) throw new Error(payload.detail ?? 'Iris is currently unavailable.')
    conversationId.value = payload.conversationId
    localStorage.setItem('nexus-conversation-id', payload.conversationId)
    chatMessages.value.push({ role: 'iris', content: payload.content })
  } catch (error) {
    chatMessages.value.push({ role: 'error', content: error instanceof Error ? error.message : 'Iris is currently unavailable.' })
  } finally {
    chatPending.value = false
  }
}
</script>

<template>
  <form v-if="view === 'Projects'" class="quick-create" @submit.prevent="newProject.trim() && (emit('createProject', newProject.trim()), newProject = '')"><input v-model="newProject" placeholder="New project name" /><button>Create project</button></form>
  <div v-if="view === 'Projects'" class="module-grid">
    <article v-for="project in snapshot.projects" :key="project.id" class="module-card project-card" @click="$router.push(`/projects/${project.id}`)">
      <div class="module-card-head"><span class="project-letter">{{ project.name[0] }}</span><span class="badge positive">{{ project.status }}</span></div>
      <h3>{{ project.name }}</h3><p>Operational workspace managed through Nexus.</p>
      <div class="progress"><i :style="{ width: `${project.progress}%` }"></i></div>
      <footer><span>Progress</span><strong>{{ project.progress }}%</strong></footer>
    </article>
  </div>

  <form v-else-if="view === 'Task Board'" class="quick-create" @submit.prevent="newTask.trim() && (emit('createTask', newTask.trim(), 'Normal'), newTask = '')"><input v-model="newTask" placeholder="New task title" /><button>Create task</button></form>
  <section v-if="view === 'Task Board' && canModerateApprovals" class="approval-strip">
    <header class="approval-strip-head">
      <div>
        <span class="kicker">Owner approvals</span>
        <h3>Pending approvals</h3>
      </div>
      <span class="badge">{{ pendingApprovals.length }}</span>
    </header>
    <p v-if="pendingApprovalsLoading" class="approval-strip-note">Loading owner approval queue…</p>
    <p v-else-if="pendingApprovalsError" class="approval-strip-note error">{{ pendingApprovalsError }}</p>
    <p v-else-if="!pendingApprovals.length" class="approval-strip-note">No tasks are waiting for Bao approval.</p>
    <div v-else class="approval-list">
      <article v-for="task in pendingApprovals" :key="task.id" class="approval-card">
        <div>
          <strong>{{ task.title }}</strong>
          <p>{{ task.priority }} · {{ new Date(task.updatedAt).toLocaleString() }}</p>
        </div>
        <div class="approval-actions">
          <button class="task-approve-btn" :disabled="approvingTaskId === task.id" @click="handleApproveTask(task.id)"><CheckCircle2 :size="13" /></button>
          <button class="task-reject-btn" :disabled="approvingTaskId === task.id" @click="handleRejectTask(task.id)"><X :size="13" /></button>
        </div>
      </article>
    </div>
    <p v-if="taskActionError" class="approval-strip-note error">{{ taskActionError }}</p>
  </section>
  <div v-if="view === 'Task Board'" class="kanban">
    <section v-for="column in columns" :key="column.name" class="kanban-column">
      <header><span>{{ column.name }}</span><b>{{ column.items.length }}</b></header>
      <article v-for="task in column.items" :key="task.id" class="task-card">
        <template v-if="editingTaskId === task.id">
          <input v-model="editTaskTitle" class="task-edit-input" placeholder="Task title" maxlength="240" />
          <div class="task-edit-row">
            <select v-model="editTaskPriority">
              <option value="Critical">Critical</option>
              <option value="High">High</option>
              <option value="Normal">Normal</option>
              <option value="Low">Low</option>
            </select>
            <select v-model="editTaskProjectId">
              <option :value="null">No project</option>
              <option v-for="p in snapshot.projects" :key="p.id" :value="p.id">{{ p.name }}</option>
            </select>
          </div>
          <div class="task-edit-actions">
            <button class="task-edit-save" @click="saveEditTask(task.id)"><Save :size="13" /> Save</button>
            <button class="task-edit-cancel" @click="cancelEditTask"><X :size="13" /> Cancel</button>
          </div>
        </template>
        <template v-else>
          <div class="task-card-head">
            <span :class="['priority', task.priority.toLowerCase()]">{{ task.priority }}</span>
            <div class="task-card-actions">
              <template v-if="task.state === 'In progress' && canModerateApprovals">
                <button
                  class="task-approve-btn"
                  title="Approve"
                  :disabled="approvingTaskId === task.id"
                  @click="handleApproveTask(task.id)"
                ><CheckCircle2 :size="13" /></button>
                <button
                  class="task-reject-btn"
                  title="Reject"
                  :disabled="approvingTaskId === task.id"
                  @click="handleRejectTask(task.id)"
                ><X :size="13" /></button>
              </template>
              <button class="task-edit-btn" @click="startEditTask(task)" title="Edit task"><Edit2 :size="12" /></button>
              <button
                v-if="task.state === 'Done' || task.state === 'Backlog'"
                class="task-delete-btn"
                title="Delete task"
                @click="deletingTaskId = task.id; deleteError = ''"
              ><Trash2 :size="12" /></button>
            </div>
          </div>
          <h3>{{ task.title }}</h3>
          <select :value="task.state" @change="emit('updateTaskState', task.id, ($event.target as HTMLSelectElement).value)">
            <option v-for="state in TASK_STATES" :key="state" :value="state">{{ state }}</option>
          </select>
          <footer><Clock3 :size="13" /> {{ new Date(task.updatedAt).toLocaleString() }}</footer>
        </template>
      </article>
      <div v-if="!column.items.length" class="empty-state">No tasks</div>
    </section>
  </div>

  <div v-else-if="view === 'Agents'" class="module-grid">
    <div v-if="agentsLoading" class="loading-agents">Loading agents…</div>
    <article v-for="agent in agents" :key="agent.id" class="module-card agent-card">
      <div class="agent-avatar" :class="agent.role === 'orchestrator' ? 'violet' : ''">
        <Bot v-if="agent.role === 'orchestrator'" :size="22" />
        <Zap v-else :size="22" />
      </div>
      <div>
        <span class="kicker">{{ agent.role.toUpperCase() }}</span>
        <h3>{{ agent.name }}</h3>
        <p>{{ agent.description || agent.model }}</p>
      </div>
      <div class="agent-status-group">
        <span v-if="agent.model" class="agent-model-tag">{{ agent.model.replace(/^[^/]*\//, '') }}</span>
        <span :class="['badge', agent.status === 'Online' ? 'positive' : agent.status === 'Degraded' ? 'warning' : 'negative']">{{ agent.status }}</span>
      </div>
    </article>
    <div v-if="!agentsLoading && !agents.length" class="empty-state">No agents available</div>
  </div>

  <div v-else-if="view === 'Models'" class="module-list panel">
    <div v-for="model in routing" :key="model.model" class="model-detail">
      <div class="route-rank">0{{ model.priority }}</div><div><span class="kicker">{{ model.purpose }}</span><h3>{{ model.model }}</h3><p>{{ model.provider }} · {{ model.detail }}</p></div><span :class="['badge', model.status === 'Online' ? 'positive' : 'warning']">{{ model.status }}</span>
    </div>
  </div>

  <div v-else-if="view === 'Activity'" class="activity-panel panel">
    <div class="activity-filters">
      <div class="filter-group">
        <label>Type</label>
        <select v-model="activityTypeFilter">
          <option value="">All types</option>
          <option v-for="type in availableTypes" :key="type" :value="type">{{ type }}</option>
        </select>
      </div>
      <div class="filter-group">
        <label>Sort</label>
        <select v-model="activitySort">
          <option value="newest">Newest first</option>
          <option value="oldest">Oldest first</option>
        </select>
      </div>
    </div>
    <div class="timeline">
      <article v-for="event in filteredActivity" :key="event.message + event.at">
        <div :class="['timeline-icon', event.type]">
          <CheckCircle2 v-if="event.type !== 'security'" :size="15" />
          <ShieldAlert v-else :size="15" />
        </div>
        <div>
          <span class="kicker">{{ event.type }}</span>
          <h3>{{ event.message }}</h3>
          <p>{{ new Date(event.at).toLocaleString() }}</p>
        </div>
      </article>
    </div>
    <div v-if="activityTotalPages > 1" class="activity-pagination">
      <button :disabled="activityPage <= 1" @click="activityPage--"><ChevronLeft :size="14" /></button>
      <span>{{ activityPage }} / {{ activityTotalPages }}</span>
      <button :disabled="activityPage >= activityTotalPages" @click="activityPage++"><ChevronRight :size="14" /></button>
    </div>
  </div>

  <div v-else-if="view === 'Settings'" class="settings-redirect">
    <p>Use the <router-link to="/settings">full Settings page</router-link> for profile management and password changes.</p>
  </div>

  <div v-else-if="view === 'Mobile Chat'" class="chat-shell panel">
    <header><div class="agent-avatar"><MessageSquareText :size="20" /></div><div><h3>Iris Mobile</h3><p>Secure owner operations channel</p></div><span class="badge warning">Preview</span></header>
    <div class="messages"><div class="message iris"><strong>Iris</strong><p>Nexus is online. Messages are routed through the OpenClaw runtime.</p></div><div v-for="(item, index) in chatMessages" :key="index" :class="['message', item.role]"><strong>{{ item.role === 'owner' ? 'Owner' : item.role === 'iris' ? 'Iris' : 'Runtime' }}</strong><p>{{ item.content }}</p></div><div v-if="chatPending" class="message iris pending"><strong>Iris</strong><p>Working...</p></div></div>
    <form @submit.prevent="sendMessage"><input v-model="message" :disabled="chatPending" placeholder="Ask for status or create a task..." /><button :disabled="chatPending"><Send :size="15" /></button></form>
  </div>

  <!-- Task deletion confirmation dialog -->
  <Teleport to="body">
    <div v-if="deletingTaskId" class="delete-overlay" @click.self="cancelDeleteTask">
      <div class="delete-dialog">
        <h3>Delete Task?</h3>
        <p>This action cannot be undone. The task will be permanently removed.</p>
        <p v-if="deleteError" class="delete-error">{{ deleteError }}</p>
        <div class="delete-actions">
          <button class="delete-cancel" @click="cancelDeleteTask">Cancel</button>
          <button class="delete-confirm" @click="confirmDeleteTask(deletingTaskId)">Delete</button>
        </div>
      </div>
    </div>
  </Teleport>
</template>

<style scoped>
.approval-strip {
  margin: 0 0 18px;
  padding: 14px 16px;
  border: 1px solid var(--line, #1e2030);
  border-radius: 14px;
  background: rgba(255,255,255,.025);
}
.approval-strip-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
}
.approval-strip-head h3 {
  margin: 2px 0 0;
}
.approval-strip-note {
  margin: 10px 0 0;
  color: #8e96a8;
}
.approval-strip-note.error {
  color: #e16e75;
}
.approval-list {
  display: grid;
  gap: 10px;
  margin-top: 12px;
}
.approval-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 12px;
  background: rgba(8, 10, 18, .35);
}
.approval-card p {
  margin: 4px 0 0;
  color: #8e96a8;
  font-size: 12px;
}
.approval-actions {
  display: flex;
  gap: 8px;
}
.task-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}
.task-card-actions {
  display: flex;
  gap: 0.15rem;
  align-items: center;
}
.task-edit-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0.15rem;
  opacity: 0;
  transition: opacity 0.15s;
}
.task-card:hover .task-edit-btn {
  opacity: 1;
}
.task-edit-btn:hover {
  color: var(--nx-accent);
}
.task-delete-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0.15rem;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
}
.task-card:hover .task-delete-btn {
  opacity: 1;
}
.task-delete-btn:hover {
  color: var(--danger, #e74c3c);
}
.task-edit-input {
  width: 100%;
  padding: 0.35rem 0.5rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.9rem;
  color: var(--text-primary);
  margin-bottom: 0.4rem;
}
.task-edit-row {
  display: flex;
  gap: 0.35rem;
  margin-bottom: 0.4rem;
}
.task-edit-row select {
  flex: 1;
  padding: 0.25rem 0.4rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.8rem;
  color: var(--text-primary);
}
.task-edit-actions {
  display: flex;
  gap: 0.35rem;
}
.task-edit-save {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0.5rem;
  background: var(--nx-accent);
  color: #fff;
  border: none;
  border-radius: 4px;
  font-size: 0.78rem;
  cursor: pointer;
}
.task-edit-cancel {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0.5rem;
  background: var(--surface-raised);
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.78rem;
  cursor: pointer;
}
.activity-panel {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.activity-filters {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}
.filter-group {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.filter-group label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
}
.filter-group select {
  padding: 0.35rem 0.5rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.85rem;
  color: var(--text-primary);
}
.activity-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}
.activity-pagination button {
  display: flex;
  align-items: center;
  padding: 0.3rem 0.5rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-secondary);
  cursor: pointer;
}
.activity-pagination button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.activity-pagination span {
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.project-card {
  cursor: pointer;
  transition: transform 0.15s, box-shadow 0.15s;
}
.project-card:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.settings-redirect {
  padding: 2rem;
  text-align: center;
  color: var(--text-secondary);
}
.settings-redirect a {
  color: var(--nx-accent);
  text-decoration: none;
}
.settings-redirect a:hover {
  text-decoration: underline;
}

/* Task deletion confirmation */
.delete-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.delete-dialog {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.5rem;
  max-width: 380px;
  width: 90%;
  box-shadow: 0 8px 24px rgba(0,0,0,0.3);
}
.delete-dialog h3 {
  margin: 0 0 0.5rem;
  font-size: 1.1rem;
}
.delete-dialog p {
  margin: 0 0 1rem;
  color: var(--text-secondary);
  font-size: 0.9rem;
  line-height: 1.4;
}
.delete-error {
  color: var(--danger, #e74c3c) !important;
  font-weight: 600;
}
.delete-actions {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
}
.delete-cancel {
  padding: 0.45rem 1rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 0.85rem;
}
.delete-confirm {
  padding: 0.45rem 1rem;
  background: var(--danger, #e74c3c);
  border: none;
  border-radius: 6px;
  color: #fff;
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
}
.delete-confirm:hover {
  opacity: 0.9;
}

/* Agent card enhancements */
.agent-status-group {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.3rem;
}
.agent-model-tag {
  font-size: 0.7rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.1rem 0.35rem;
  color: var(--text-muted);
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.loading-agents {
  grid-column: 1 / -1;
  text-align: center;
  padding: 2rem;
  color: var(--text-secondary);
}

/* Task approve/reject buttons */
.task-approve-btn,
.task-reject-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.15rem;
  display: flex;
  align-items: center;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
}
.task-card:hover .task-approve-btn,
.task-card:hover .task-reject-btn {
  opacity: 1;
}
.task-approve-btn {
  color: var(--success, #27ae60);
}
.task-approve-btn:hover {
  color: var(--success, #27ae60);
  filter: brightness(1.2);
}
.task-reject-btn {
  color: var(--warning, #f39c12);
}
.task-reject-btn:hover {
  color: var(--danger, #e74c3c);
}
.task-approve-btn:disabled,
.task-reject-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
</style>
