<script setup lang="ts">
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useAdminConfigStore } from '@/store/adminConfigStore'
import type { EnterpriseAgentItem } from '@/types/admin-config'
import { ExtractionMode, isFieldRequired } from '@/types/admin-config'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import Button from '@/components/ui/button/Button.vue'

interface Props {
  sidebarOpen: boolean
}

defineProps<Props>()

const store = useAdminConfigStore()
const route = useRoute()
const router = useRouter()

const activeSection = computed({
  get: () => (route.query.section as string) || 'system',
  set: (value: string) => {
    router.push({ query: { ...route.query, section: value } })
  },
})

const sections = [
  { id: 'system', label: 'Core Settings', icon: 'dku-icon-gear-16' },
  { id: 'enterprise-agents', label: 'Enterprise Agents', icon: 'dku-icon-briefcase-16' },
  { id: 'my-agents', label: 'My Agents', icon: 'dku-icon-user-16' },
  { id: 'prompts', label: 'Prompt Library', icon: 'dku-icon-file-text-16' },
  { id: 'charts', label: 'Charts Generation', icon: 'dku-icon-chart-16' },
  { id: 'conversation-files', label: 'Upload in Conversation', icon: 'dku-icon-file-upload-16' },
  { id: 'user-experience', label: 'User Experience', icon: 'dku-icon-project-blank-16' },
]

function isMissing(v?: string) {
  return !v || !v.trim()
}

function requireDescription(): boolean {
  return isFieldRequired(store.draft, 'enterpriseAgentsDescription')
}

function agentTitle(it: EnterpriseAgentItem): string {
  const fallback = [it.projectKey, it.sourceAgentName].filter(Boolean).join(' _ ')
  return it.name?.trim() || fallback || '(unnamed)'
}

function myAgentsEnabled(): boolean {
  return !!store.draft?.myAgentsEnabled
}

function requireMA_TextCompletionModels(): boolean {
  return isFieldRequired(store.draft, 'myAgentsTextCompletionModels')
}

function requireMA_EmbeddingModel(): boolean {
  return isFieldRequired(store.draft, 'myAgentsEmbeddingModel')
}

function requireMA_FileSystem(): boolean {
  return isFieldRequired(store.draft, 'myAgentsFsConnection')
}

function requireMA_Folder(): boolean {
  return isFieldRequired(store.draft, 'myAgentsFolder')
}

function requireMA_NumDocs(): boolean {
  return isFieldRequired(store.draft, 'myAgentsNumDocs')
}

function chartsEnabled(): boolean {
  return store.draft?.chartsGenerationMode !== 'disabled'
}

function requireCharts_MaxArtifactsSize(): boolean {
  return isFieldRequired(store.draft, 'chartsMaxArtifactsSize')
}

function requireAgentHub_LLM(): boolean {
  return isFieldRequired(store.draft, 'agentHubLLM')
}

function requireUploadManagedFolder(): boolean {
  return isFieldRequired(store.draft, 'uploadManagedFolder')
}

function documentUploadEnabled(): boolean {
  return !!store.draft?.enableDocumentUpload
}

function isExtractionModeScreenshots(): boolean {
  return (
    store.draft?.extractionMode === ExtractionMode.PagesScreenshots || !store.draft?.extractionMode
  )
}

interface ValidationError {
  section: string
  field: string
  message: string
  index?: number
}

const validationErrors = computed<ValidationError[]>(() => {
  const c = store.draft
  if (!c) return []
  const errs: ValidationError[] = []

  if (requireDescription()) {
    c.enterpriseAgents?.forEach((it, idx) => {
      if (isMissing(it.description)) {
        errs.push({
          section: 'enterprise-agents',
          field: `description-${idx}`,
          message: `"${agentTitle(it)}": Description is required`,
          index: idx,
        })
      }
      if (it.allowInsightsCreation && isMissing(it.storiesWorkspace)) {
        errs.push({
          section: 'enterprise-agents',
          field: `workspace-${idx}`,
          message: `"${agentTitle(
            it
          )}": Workspace for stories is required when insights creation is enabled`,
          index: idx,
        })
      }
    })
  }

  if (myAgentsEnabled()) {
    if (
      requireMA_TextCompletionModels() &&
      (!c.myAgentsTextCompletionModels || c.myAgentsTextCompletionModels.length === 0)
    ) {
      errs.push({
        section: 'my-agents',
        field: 'textCompletionModels',
        message: 'At least one LLM is required',
      })
    }
    if (requireMA_EmbeddingModel() && isMissing(c.myAgentsEmbeddingModel)) {
      errs.push({
        section: 'my-agents',
        field: 'embeddingModel',
        message: 'Embedding Model is required',
      })
    }
    if (requireMA_FileSystem() && isMissing(c.myAgentsFsConnection)) {
      errs.push({
        section: 'my-agents',
        field: 'fsConnection',
        message: 'File System Connection is required',
      })
    }
    if (requireMA_Folder() && isMissing(c.myAgentsFolder)) {
      errs.push({
        section: 'my-agents',
        field: 'folder',
        message: 'Folder where My Agents will be created is required',
      })
    }
    const nd = c.myAgentsNumDocs
    if (
      requireMA_NumDocs() &&
      (nd === undefined || nd === null || isNaN(Number(nd)) || Number(nd) < 1)
    ) {
      errs.push({
        section: 'my-agents',
        field: 'numDocs',
        message: 'Number of documents to retrieve must be an integer ≥ 1',
      })
    }
  }

  if (chartsEnabled()) {
    const maxSize = c.chartsMaxArtifactsSize
    if (
      requireCharts_MaxArtifactsSize() &&
      (maxSize === undefined || maxSize === null || isNaN(Number(maxSize)) || Number(maxSize) < 1)
    ) {
      errs.push({
        section: 'charts',
        field: 'maxArtifactsSize',
        message: 'Max Artifacts Size must be an integer ≥ 1',
      })
    }
  }

  if (requireAgentHub_LLM() && isMissing(c.agentHubLLM)) {
    errs.push({
      section: 'system',
      field: 'agentHubLLM',
      message: 'Agent Hub LLM is required',
    })
  }

  if (documentUploadEnabled() && requireUploadManagedFolder() && isMissing(c.uploadManagedFolder)) {
    errs.push({
      section: 'conversation-files',
      field: 'uploadManagedFolder',
      message: 'Upload Managed Folder is required',
    })
  }

  if (documentUploadEnabled() && isExtractionModeScreenshots()) {
    const maxImages = c.maxImagesInConversation
    if (
      maxImages === undefined ||
      maxImages === null ||
      isNaN(Number(maxImages)) ||
      Number(maxImages) < 1
    ) {
      errs.push({
        section: 'conversation-files',
        field: 'maxImagesInConversation',
        message: 'Max Images in Conversation must be an integer ≥ 1',
      })
    }
  }

  return errs
})

function sectionHasErrors(sectionId: string): boolean {
  return validationErrors.value.some((err) => err.section === sectionId)
}

function handleSectionClick(sectionId: string) {
  activeSection.value = sectionId
}
</script>

<template>
  <div v-if="sidebarOpen" class="pt-2 pb-3 px-2">
    <Button
      v-for="section in sections"
      :key="section.id"
      variant="ghost"
      @click="handleSectionClick(section.id)"
      class="w-full justify-start p-2 mb-1 admin-sidebar-item flex items-center"
      :class="{ 'admin-sidebar-item-active': activeSection === section.id }"
    >
      <span class="flex flex-1 text-left truncate items-center">
        <Tooltip :key="`tooltip-changes-${section.id}`" class="flex-1">
          <TooltipTrigger as-child>
            <span class="inline-flex items-center">
              <span>
                {{ section.label }}
              </span>
              <i
                v-if="store.isSectionDirty(section.id)"
                class="dku-icon-history-12 text-warning ml-1 pt-0.5"
              ></i>
            </span>
          </TooltipTrigger>
          <TooltipContent
            v-if="store.isSectionDirty(section.id)"
            side="right"
            :side-offset="10"
            hide-arrow
          >
            <div class="text-xs text-warning">Unsaved changes</div>
          </TooltipContent>
        </Tooltip>
      </span>
      <Tooltip v-if="sectionHasErrors(section.id)" :key="`tooltip-${section.id}`">
        <TooltipTrigger>
          <span class="flex items-center flex-shrink-0">
            <i
              v-if="store.isSectionDirty(section.id)"
              class="dku-icon-circle-fill-12 admin-text-error"
            ></i>
            <i v-else class="dku-icon-error-circle-outline-16 admin-text-error"></i>
          </span>
        </TooltipTrigger>
        <TooltipContent side="right" :side-offset="10" hide-arrow>
          <div class="text-xs admin-text-error">Required fields missing</div>
        </TooltipContent>
      </Tooltip>
    </Button>
  </div>

  <div v-else class="flex flex-col pt-2 pb-3">
    <Tooltip v-for="section in sections" :key="`collapsed-tooltip-${section.id}`">
      <TooltipTrigger asChild>
        <Button
          variant="ghost"
          @click="handleSectionClick(section.id)"
          class="justify-start p-2 mx-1 admin-sidebar-item relative"
          :class="{ 'admin-sidebar-item-active': activeSection === section.id }"
        >
          <i :class="section.icon" class="admin-icon-default"></i>
          <span
            v-if="store.isSectionDirty(section.id)"
            class="absolute top-1 right-1 w-1.5 h-1.5 bg-warning rounded-full"
          >
          </span>
          <span
            v-if="sectionHasErrors(section.id)"
            class="absolute bottom-1 right-1 w-1.5 h-1.5 rounded-full"
            style="background-color: #dc2626"
          >
          </span>
        </Button>
      </TooltipTrigger>
      <TooltipContent side="right" :side-offset="10" hide-arrow>
        <div>
          <div>{{ section.label }}</div>
          <div v-if="sectionHasErrors(section.id)" class="text-xs admin-text-error">
            Required fields missing
          </div>
          <div v-if="store.isSectionDirty(section.id)" class="text-xs text-warning">
            Unsaved changes
          </div>
        </div>
      </TooltipContent>
    </Tooltip>
  </div>
</template>
