<script setup lang="ts">
import { computed, onMounted, onBeforeUnmount, ref, nextTick } from 'vue'
import { useAdminConfigStore } from '@/store/adminConfigStore'
import type { AdminConfig, EnterpriseAgentItem } from '@/types/admin-config'
import { API } from '@/Api'

import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { Separator } from '@/components/ui/separator'
import { Switch } from '@/components/ui/switch'
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectGroup,
  SelectItem,
} from '@/components/ui/select'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import AddEnterpriseAgentsDialog from './AddEnterpriseAgentsDialog.vue'
import StringListEditor from './StringListEditor.vue'

const store = useAdminConfigStore()

function updateDraft(mutator: (cfg: AdminConfig) => void) {
  if (!store.draft) return
  const next = JSON.parse(JSON.stringify(store.draft)) as AdminConfig
  mutator(next)
  store.draft = next
}

const items = computed<EnterpriseAgentItem[]>(() => store.draft?.enterpriseAgents ?? [])

const projects = ref<{ key: string; name: string }[]>([])
const workspaces = ref<{ id: string; label: string }[]>([])

const projectNameByKey = computed(() =>
  projects.value.reduce((acc, p) => ((acc[p.key] = p.name), acc), {} as Record<string, string>)
)

// Listen for events to expand agents programmatically
const handleExpandAgent = (event: CustomEvent<{ index: number }>) => {
  const { index } = event.detail
  if (!openSet.value.has(index)) {
    toggleOpen(index)
  }
}

onMounted(async () => {
  try {
    const { data } = await API.listEnterpriseProjects()
    projects.value = data?.projects ?? []
    workspaces.value = data?.workspaces ?? []
  } catch {
    /* best-effort */
  }

  window.addEventListener('expand-enterprise-agent', handleExpandAgent as EventListener)
})

onBeforeUnmount(() => {
  window.removeEventListener('expand-enterprise-agent', handleExpandAgent as EventListener)
})

const addOpen = ref(false)

const existingKeys = computed(
  () =>
    new Set(
      items.value.filter((it) => it.projectKey && it.id).map((it) => `${it.projectKey}::${it.id}`)
    )
)

async function onAddSelected(payload: {
  projectKey: string
  projectName: string
  agents: { id: string; name: string }[]
}) {
  const startIdx = items.value.length

  updateDraft((cfg) => {
    if (!cfg.enterpriseAgents) cfg.enterpriseAgents = []
    const arr = cfg.enterpriseAgents
    for (const a of payload.agents) {
      arr.push({
        id: a.id,
        projectKey: payload.projectKey,
        name: '',
        sourceAgentName: a.name || undefined,
        description: '',
        exampleQuestions: [],
        additionalInstructions: '',
        allowInsightsCreation: false,
        storiesWorkspace: undefined,
      })
    }
  })

  // Expand all newly added agents
  const next = new Set(openSet.value)
  for (let i = startIdx; i < startIdx + payload.agents.length; i++) {
    next.add(i)
  }
  openSet.value = next

  // Wait for DOM to update, then scroll and focus on the first agent's description
  await nextTick()

  const firstAgentDescriptionTextarea = document.querySelector(
    `[data-agent-index="${startIdx}"] textarea[placeholder="Describe what this agent does"]`
  ) as HTMLTextAreaElement

  if (firstAgentDescriptionTextarea) {
    firstAgentDescriptionTextarea.scrollIntoView({ behavior: 'smooth', block: 'center' })
    setTimeout(() => {
      firstAgentDescriptionTextarea.focus()
    }, 300) // Small delay to allow scroll animation to complete
  }
}

function removeAt(index: number) {
  updateDraft((cfg) => {
    if (!cfg.enterpriseAgents) cfg.enterpriseAgents = []
    cfg.enterpriseAgents.splice(index, 1)
  })
}

const openSet = ref<Set<number>>(new Set())
function toggleOpen(i: number) {
  const next = new Set(openSet.value)
  next.has(i) ? next.delete(i) : next.add(i)
  openSet.value = next
}

const editingNameIdx = ref<number | null>(null)
const tempName = ref('')

function startEditName(i: number, it: EnterpriseAgentItem) {
  editingNameIdx.value = i
  // If custom name is empty, pre-fill with the source agent name so user can edit it
  tempName.value = it.name?.trim() || it.sourceAgentName || ''
  // Focus the input after DOM updates
  nextTick(() => {
    const agentContainer = document.querySelector(`[data-agent-index="${i}"]`)
    const inputEl = agentContainer?.querySelector(
      'input[placeholder="Display name (optional)"]'
    ) as HTMLInputElement
    if (inputEl) {
      inputEl.focus()
    }
  })
}
function cancelEditName() {
  editingNameIdx.value = null
}
function applyEditName() {
  if (editingNameIdx.value === null) return
  const idx = editingNameIdx.value
  const newName = (tempName.value || '').trim()
  updateDraft((cfg) => {
    if (!cfg.enterpriseAgents) cfg.enterpriseAgents = []
    cfg.enterpriseAgents[idx].name = newName
  })
  editingNameIdx.value = null
}

const missing = (v?: string) => !v || !v.trim()

// Check if an agent has been saved (exists in original config)
function hasBeenSaved(agent: EnterpriseAgentItem): boolean {
  if (!store.original?.enterpriseAgents || !agent.projectKey || !agent.id) {
    return false
  }
  const found = store.original.enterpriseAgents.some(
    (orig) => orig.projectKey === agent.projectKey && orig.id === agent.id
  )
  return found
}

function titleFor(it: EnterpriseAgentItem): string {
  const proj = projectNameByKey.value[it.projectKey || ''] || it.projectKey || ''
  const backend = it.sourceAgentName || ''
  const fallback = [proj, backend].filter(Boolean).join(' _ ')
  if (it.name?.trim()) {
    return [proj, it.name?.trim()].filter(Boolean).join(' _ ')
  } else {
    return fallback || '(unnamed)'
  }
}

function updateAgentField<K extends keyof EnterpriseAgentItem>(
  index: number,
  field: K,
  value: EnterpriseAgentItem[K]
) {
  updateDraft((cfg) => {
    if (!cfg.enterpriseAgents) cfg.enterpriseAgents = []
    if (cfg.enterpriseAgents[index]) {
      cfg.enterpriseAgents[index][field] = value
    }
  })
}
</script>

<template>
  <div class="space-y-3">
    <div class="flex items-center justify-between">
      <h3 class="text-base font-semibold">Agents Management</h3>
      <Button size="lg" class="admin-btn admin-btn--secondary" @click="addOpen = true">
        <i class="dku-icon-plus-16 mr-1" /> Add Agent(s)
      </Button>
    </div>

    <div v-if="items.length === 0" class="bg-gray-50 p-8 text-center">
      <p class="text-sm text-muted-foreground">
        Add an agent to manage its settings and view it here
      </p>
    </div>

    <div v-else class="space-y-3">
      <div
        v-for="(it, i) in items"
        :key="`${it.projectKey ?? ''}:${i}`"
        :data-agent-index="i"
        class="admin-card bg-white rounded-lg"
      >
        <div
          class="flex items-center justify-between px-4 py-3 cursor-pointer"
          @click="toggleOpen(i)"
        >
          <div class="min-w-0 flex-1 flex items-center gap-2">
            <template v-if="editingNameIdx === i">
              <Input
                v-model="tempName"
                class="w-[420px] max-w-full admin-input"
                placeholder="Display name (optional)"
                @click.stop
                @keydown.enter.prevent="applyEditName"
                @keydown.esc.prevent="cancelEditName"
                @blur="applyEditName"
              />
            </template>
            <template v-else>
              <h3 class="font-semibold truncate min-w-0">
                {{ titleFor(it) }}
              </h3>
              <Button
                size="sm"
                variant="ghost"
                class="flex-shrink-0 p-1"
                title="Edit name"
                @click.stop="startEditName(i, it)"
              >
                <i class="dku-icon-edit-16"></i>
              </Button>
              <Tooltip>
                <TooltipTrigger as-child>
                  <Button
                    size="sm"
                    variant="ghost"
                    class="admin-icon--trash p-1"
                    @click.stop="removeAt(i)"
                  >
                    <i class="dku-icon-trash-16"></i>
                  </Button>
                </TooltipTrigger>
                <TooltipContent hide-arrow> Remove </TooltipContent>
              </Tooltip>
            </template>
          </div>

          <div class="flex items-center gap-2 flex-shrink-0">
            <i
              class="dku-icon-chevron-down-16 admin-icon text-xl transition-transform duration-200"
              :class="{ 'rotate-180': openSet.has(i) }"
            ></i>
          </div>
        </div>

        <div v-show="openSet.has(i)" class="px-4 pb-4">
          <Separator class="mb-4" />

          <div class="space-y-4 max-w-3xl">
            <!-- Description -->
            <div>
              <label class="admin-field-label"
                >Description<span class="text-red-600">*</span></label
              >

              <Textarea
                :id="`field-description-${i}`"
                :modelValue="it.description"
                @update:modelValue="(val: string | number) => updateAgentField(i, 'description', String(val))"
                rows="3"
                class="w-full !border !border-border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary text-sm py-2 px-3 resize-y placeholder-muted-foreground min-h-[120px]"
                :class="
                  hasBeenSaved(it) && missing(it.description)
                    ? '!border-red-500 focus:!ring-red-500 focus:!border-red-500'
                    : ''
                "
                placeholder="Describe what this agent does"
              />
              <div
                v-if="hasBeenSaved(it) && missing(it.description)"
                class="text-[11px] mt-1 text-red-600"
              >
                <i class="dku-icon-warning-12 mr-1"></i>Description is required
              </div>
              <p class="admin-field-description">
                Describe what this agent does. This helps users understand the agent's purpose and
                guides the LLM in selecting the appropriate agent when multiple agents are selected
              </p>
            </div>

            <div>
              <label class="admin-field-label">Example questions</label>
              <StringListEditor
                :modelValue="it.exampleQuestions"
                @update:modelValue="(val: string[] | undefined) => updateAgentField(i, 'exampleQuestions', val)"
                placeholder="Ask me about…"
              />
            </div>

            <Separator />

            <div>
              <label class="admin-field-label">Additional instructions</label>
              <Textarea
                :modelValue="it.additionalInstructions"
                @update:modelValue="(val: string | number) => updateAgentField(i, 'additionalInstructions', String(val))"
                rows="3"
                class="w-full !border !border-border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary text-sm py-2 px-3 resize-y placeholder-muted-foreground min-h-[120px]"
                placeholder="Optional additional instructions for the agent"
              />
              <p class="admin-field-description">
                Optional additional instructions for the agent. The system instructions will be used
                to fine-tune the Agent's tone or style. It adjusts behavior without replacing the
                existing setup
              </p>
            </div>

            <div>
              <div class="flex items-center gap-2">
                <Switch
                  class="admin-switch"
                  :modelValue="!!it.allowInsightsCreation"
                  @update:modelValue="(v: boolean) => updateAgentField(i, 'allowInsightsCreation', v)"
                />
                <label class="font-medium text-sm cursor-pointer"
                  >Allow users to create Insights in Dataiku Stories</label
                >
              </div>
              <p class="admin-field-description ml-10">
                Dataiku Stories need to be installed and enabled in the instance to use this
                feature. Dataiku Stories uses Generative AI to instantly create dynamic, trusted
                presentations from data
              </p>
            </div>

            <div v-if="it.allowInsightsCreation" :id="`field-workspace-${i}`">
              <label class="admin-field-label">
                Workspace for stories<span class="text-red-600">*</span>
              </label>
              <p class="admin-field-description">
                Dataiku Stories will be created in this workspace. Agent datasets must be included
                in this workspace.
              </p>
              <Select
                :modelValue="it.storiesWorkspace"
                @update:modelValue="
                  (val) =>
                    updateAgentField(i, 'storiesWorkspace', val != null ? String(val) : undefined)
                "
              >
                <SelectTrigger
                  class="w-full lg:w-[256px] admin-select-trigger"
                  :class="{ 'admin-dropdown-trigger': true }"
                >
                  <SelectValue placeholder="Choose a workspace" />
                </SelectTrigger>
                <SelectContent hide-indicator>
                  <SelectGroup>
                    <SelectItem
                      v-for="ws in workspaces"
                      :key="ws.id"
                      :value="ws.id"
                      class="admin-select-item"
                    >
                      {{ ws.label }}
                    </SelectItem>
                  </SelectGroup>
                </SelectContent>
              </Select>
            </div>
          </div>
        </div>
      </div>
    </div>

    <AddEnterpriseAgentsDialog
      v-model:open="addOpen"
      :existing-keys="existingKeys"
      @selected="onAddSelected"
    />
  </div>
</template>

<style scoped>
.line-clamp-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-clamp: 3;
}
</style>
