<template>
  <AlertDialog :open="open" @update:open="$emit('update:open', $event)">
    <AlertDialogContent class="sm:w-[425px] min-h-[326px]">
      <AlertDialogHeader>
        <AlertDialogTitle class="text-xl font-semibold text-foreground">
          <i class="dku-icon-share-16 my-auto"></i>
          Share {{ agentName || 'this agent' }}</AlertDialogTitle
        >
      </AlertDialogHeader>

      <div class="space-y-6">
        <!-- Searchable Select -->
        <div>
          <Select v-model="selectedValue" @update:model-value="handleSelectChange">
            <SelectTrigger class="w-full">
              <SelectValue placeholder="Share with users and groups" />
            </SelectTrigger>
            <SelectContent>
              <!-- Search Input inside dropdown -->
              <div class="p-2 border-b">
                <Input
                  v-model="query"
                  placeholder="Search users or groups"
                  class="w-full"
                  @click.stop
                />
              </div>

              <!-- Loading State -->
              <div v-if="loadingResults" class="p-3 text-sm text-muted-foreground text-center">
                Searching…
              </div>

              <!-- Results -->
              <div v-else-if="filteredResults.length" class="max-h-40 overflow-y-auto">
                <div
                  v-for="p in highlightedResults"
                  :key="p.principal"
                  @click="
                    (e) => {
                      e.preventDefault()
                      e.stopPropagation()
                      addPrincipal(p)
                    }
                  "
                  class="p-3 flex items-center justify-between transition-colors cursor-pointer hover:bg-gray-100"
                  :class="{
                    'opacity-50 cursor-not-allowed':
                      pendingShares.some((s) => s.principal === p.principal) ||
                      p.principal === userId,
                  }"
                >
                  <span v-html="boldMatch(p.displayName)"></span>
                  <Badge variant="secondary" class="uppercase">{{ p.type }}</Badge>
                </div>
              </div>

              <!-- No Results -->
              <div v-else-if="query.trim()" class="p-3 text-sm text-muted-foreground text-center">
                No users or groups found
              </div>

              <!-- Initial State -->
              <div v-else class="p-3 text-sm text-muted-foreground text-center">
                Start typing to search users and groups
              </div>
            </SelectContent>
          </Select>
        </div>

        <div>
          <div class="flex items-center mb-2">
            <h3 class="font-semibold">Access granted to</h3>
            <Badge class="agent-badge my-auto ml-1">{{ pendingShares.length }} </Badge>
          </div>
          <ul class="space-y-4 max-h-40 overflow-y-scroll pr-4">
            <li
              v-for="p in pendingShares"
              :key="p.principal"
              class="flex items-center justify-between"
            >
              <span class="truncate max-w-[240px]">{{ p.displayName }}</span>
              <div class="flex items-center space-x-2">
                <Badge variant="secondary" class="uppercase">{{ p.type }}</Badge>
                <i
                  class="dku-icon-trash-16 hover:text-destructive cursor-pointer"
                  @click="revoke(p)"
                ></i>
              </div>
            </li>
            <li v-if="!pendingShares.length" class="text-sm text-foreground">
              No one else has access yet. Add users or groups to share it
            </li>
          </ul>
        </div>
      </div>

      <AlertDialogFooter class="flex-row justify-end">
        <AlertDialogCancel class="my-0">Cancel</AlertDialogCancel>
        <AlertDialogAction class="my-0" @click="saveChanges" :disabled="saving">
          Save
        </AlertDialogAction>
      </AlertDialogFooter>
    </AlertDialogContent>
  </AlertDialog>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, computed } from 'vue'
import { Input } from '@/components/ui/input'
import { Badge } from '@/components/ui/badge'
import { Select, SelectContent, SelectTrigger, SelectValue } from '@/components/ui/select'
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogFooter,
  AlertDialogCancel,
  AlertDialogAction,
} from '@/components/ui/alert-dialog'
import { API } from '@/Api'
import { useAgentCatalogStore } from '@/store/agentCatalogStore'
import debounce from 'lodash/debounce'
import { getAppConfig, type AppConfig } from '@/lib/utils'
import { WT1iser } from '@/lib/wt1'

interface Principal {
  principal: string
  type: 'user' | 'group'
  displayName: string
}

interface Props {
  open: boolean
  agentId: string
  agentName?: string
}

const props = defineProps<Props>()
defineEmits<{
  'update:open': [value: boolean]
}>()

const catalog = useAgentCatalogStore()

const appConfig: AppConfig | null = getAppConfig()
const userId = computed(() => appConfig?.user?.login || null)

const query = ref('')
const searchResults = ref<Principal[]>([])
const currentShares = ref<Principal[]>([])
const pendingShares = ref<Principal[]>([])
const loadingResults = ref(false)
const saving = ref(false)
const selectedValue = ref('')

const filteredResults = computed(() =>
  searchResults.value.filter((p) => !pendingShares.value.some((s) => s.principal === p.principal))
)
const highlightedResults = computed(() => searchResults.value)

// Utility to escape regex special chars
function escapeRegExp(str: string): string {
  return str.replace(/[.*+?^${}()|[\\\\]\\\\]/g, '\\\\$&')
}
function boldMatch(text: string): string {
  const q = query.value.trim()
  if (!q) return text
  const re = new RegExp(`(${escapeRegExp(q)})`, 'gi')
  return text.replace(re, '<strong>$1</strong>')
}

// Handle select value change (not used for actual selection, just for the select component)
function handleSelectChange(value: any) {
  // This is just to satisfy the Select component's v-model
  // The actual selection is handled by the click events on the items
  selectedValue.value = String(value || '')
}

async function loadShares() {
  if (props.agentId) {
    currentShares.value = (await API.getAgentShares(props.agentId)).data.shares
    pendingShares.value = [...currentShares.value]
  }
}

// Load shares when dialog opens
watch(
  () => props.open,
  (isOpen) => {
    if (isOpen) {
      loadShares()
    } else {
      // Reset pending shares when dialog closes
      pendingShares.value = [...currentShares.value]
      // Reset search state
      query.value = ''
      searchResults.value = []
      selectedValue.value = ''
    }
  }
)

onMounted(() => {
  if (props.open) {
    loadShares()
  }
})

const doSearch = debounce(async (q: string) => {
  if (!q) {
    searchResults.value = []
    return
  }
  loadingResults.value = true
  try {
    searchResults.value = (await API.searchPrincipals(q)).data.results
  } finally {
    loadingResults.value = false
  }
}, 400)

watch(query, (val) => doSearch(val.trim()))

async function updateShares(list: Principal[]) {
  saving.value = true
  try {
    await API.updateAgentShares(props.agentId, list)
    currentShares.value = list
    pendingShares.value = [...list]
    await catalog.load(true)
  } finally {
    saving.value = false
    query.value = ''
    searchResults.value = []
    selectedValue.value = ''
  }
}

// Add or revoke (now just updates pending shares)
function addPrincipal(p: Principal) {
  if (
    !pendingShares.value.find((s) => s.principal === p.principal) &&
    p.principal !== userId.value
  ) {
    pendingShares.value = [...pendingShares.value, p]
  }
}

function revoke(p: Principal) {
  pendingShares.value = pendingShares.value.filter((s) => s.principal !== p.principal)
}

async function saveChanges() {
  WT1iser.shareAgent()
  await updateShares(pendingShares.value)
}
</script>
