<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue'
import { useFdsI18n } from '../../plugin/useFdsI18n'
import FdsBlockInfo from '../Blocks/FdsBlockInfo/FdsBlockInfo.vue'
import FdsButtonPrimary from '../Buttons/FdsButtonPrimary/FdsButtonPrimary.vue'
import FdsButtonSecondary from '../Buttons/FdsButtonSecondary/FdsButtonSecondary.vue'
import FdsModal from '../FdsModal/FdsModal.vue'
import FdsInput from '../Form/FdsInput/FdsInput.vue'
import FdsTabs from '../Tabs/FdsTabs/FdsTabs.vue'
import FdsTabsItem from '../Tabs/FdsTabsItem/FdsTabsItem.vue'
import type { DevModeAction } from './types'

type StorageEntry = {
  key: string
  value: string
}

const props = withDefaults(
  defineProps<{
    open?: boolean
    customActions?: DevModeAction[]
  }>(),
  {
    open: false,
    customActions: () => [],
  },
)

const emit = defineEmits<{
  (e: 'update:open', value: boolean): void
}>()

const isOpen = computed({
  get: () => props.open,
  set: (value: boolean) => emit('update:open', value),
})
const { t } = useFdsI18n()

const activeTab = ref<'local' | 'session' | 'cookies' | 'actions'>('local')

const localStorageEntries = ref<StorageEntry[]>([])
const sessionStorageEntries = ref<StorageEntry[]>([])
const cookieEntries = ref<StorageEntry[]>([])

const localEditKey = ref('')
const localEditValue = ref('')
const sessionEditKey = ref('')
const sessionEditValue = ref('')
const cookieEditKey = ref('')
const cookieEditValue = ref('')

const localTextareaRef = ref<HTMLTextAreaElement | null>(null)
const sessionTextareaRef = ref<HTMLTextAreaElement | null>(null)
const cookieTextareaRef = ref<HTMLTextAreaElement | null>(null)

// Track input values for custom actions
const actionInputValues = ref<Record<number, string>>({})

const getActionInputValue = (index: number, defaultValue?: string): string => {
  if (actionInputValues.value[index] === undefined) {
    actionInputValues.value[index] = defaultValue ?? ''
  }
  return actionInputValues.value[index]
}

const setActionInputValue = (index: number, value: string) => {
  actionInputValues.value[index] = value
}

const runAction = (index: number, action: DevModeAction) => {
  const inputValue = action.input ? actionInputValues.value[index] : undefined
  action.action(inputValue)
}

const resizeTextarea = (el: HTMLTextAreaElement | null) => {
  if (!el) return
  // Reset to default when empty
  if (!el.value) {
    el.style.height = ''
    return
  }
  el.style.height = 'auto'
  el.style.height = `${el.scrollHeight}px`
}

const loadStorageEntries = () => {
  if (typeof window === 'undefined') {
    localStorageEntries.value = []
    sessionStorageEntries.value = []
    cookieEntries.value = []
    return
  }

  const extractEntries = (storage: Storage): StorageEntry[] => {
    const entries: StorageEntry[] = []
    for (let i = 0; i < storage.length; i += 1) {
      const key = storage.key(i)
      if (!key) continue
      let value: string
      try {
        value = storage.getItem(key) ?? ''
      } catch {
        value = '[unreadable value]'
      }
      entries.push({ key, value })
    }
    return entries
  }

  localStorageEntries.value = extractEntries(window.localStorage)
  sessionStorageEntries.value = extractEntries(window.sessionStorage)

  const cookiesSource = typeof document !== 'undefined' && document.cookie ? document.cookie.split('; ') : []
  cookieEntries.value = cookiesSource.filter(Boolean).map((cookie) => {
    const [rawKey, ...rest] = cookie.split('=')
    const key = decodeURIComponent(rawKey || '')
    const value = decodeURIComponent(rest.join('='))
    return {
      key,
      value,
    }
  })
}

const handleOpenChange = (value: boolean) => {
  if (value) {
    loadStorageEntries()
  }
  isOpen.value = value
}

watch(
  () => props.open,
  (newVal) => {
    if (newVal) {
      loadStorageEntries()
    }
  },
)

const refreshStorageEntries = () => {
  loadStorageEntries()
}

const selectLocalEntry = (entry: StorageEntry) => {
  localEditKey.value = entry.key
  localEditValue.value = entry.value
  nextTick(() => resizeTextarea(localTextareaRef.value))
}

const selectSessionEntry = (entry: StorageEntry) => {
  sessionEditKey.value = entry.key
  sessionEditValue.value = entry.value
  nextTick(() => resizeTextarea(sessionTextareaRef.value))
}

const selectCookieEntry = (entry: StorageEntry) => {
  cookieEditKey.value = entry.key
  cookieEditValue.value = entry.value
  nextTick(() => resizeTextarea(cookieTextareaRef.value))
}

const saveLocalEntry = () => {
  if (typeof window === 'undefined') return
  if (!localEditKey.value) return
  window.localStorage.setItem(localEditKey.value, localEditValue.value)
  // Clear selection after save
  localEditKey.value = ''
  localEditValue.value = ''
  nextTick(() => resizeTextarea(localTextareaRef.value))
  loadStorageEntries()
}

const deleteLocalEntry = () => {
  if (typeof window === 'undefined') return
  if (!localEditKey.value) return
  window.localStorage.removeItem(localEditKey.value)
  localEditKey.value = ''
  localEditValue.value = ''
  nextTick(() => resizeTextarea(localTextareaRef.value))
  loadStorageEntries()
}

const saveSessionEntry = () => {
  if (typeof window === 'undefined') return
  if (!sessionEditKey.value) return
  window.sessionStorage.setItem(sessionEditKey.value, sessionEditValue.value)
  sessionEditKey.value = ''
  sessionEditValue.value = ''
  nextTick(() => resizeTextarea(sessionTextareaRef.value))
  loadStorageEntries()
}

const deleteSessionEntry = () => {
  if (typeof window === 'undefined') return
  if (!sessionEditKey.value) return
  window.sessionStorage.removeItem(sessionEditKey.value)
  sessionEditKey.value = ''
  sessionEditValue.value = ''
  nextTick(() => resizeTextarea(sessionTextareaRef.value))
  loadStorageEntries()
}

const saveCookieEntry = () => {
  if (typeof document === 'undefined') return
  if (!cookieEditKey.value) return
  // Basic cookie setter; consumers can override domain/path via browser devtools if needed
  document.cookie = `${encodeURIComponent(cookieEditKey.value)}=${encodeURIComponent(cookieEditValue.value)}; path=/`
  cookieEditKey.value = ''
  cookieEditValue.value = ''
  nextTick(() => resizeTextarea(cookieTextareaRef.value))
  loadStorageEntries()
}

const deleteCookieEntry = () => {
  if (typeof document === 'undefined') return
  if (!cookieEditKey.value) return
  // Expire cookie
  document.cookie = `${encodeURIComponent(cookieEditKey.value)}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
  cookieEditKey.value = ''
  cookieEditValue.value = ''
  nextTick(() => resizeTextarea(cookieTextareaRef.value))
  loadStorageEntries()
}
</script>

<template>
  <FdsModal
    :open="isOpen"
    heading="DevTools"
    size="xl"
    movable
    resizable
    @update:open="handleOpenChange"
    @close="() => handleOpenChange(false)"
  >
    <div class="space-y-6">
      <FdsTabs variant="secondary" class="flex-wrap overflow-visible! *:w-auto!">
        <FdsTabsItem
          :label="t('FdsDevModeStorage.tabs.localStorage')"
          :active="activeTab === 'local'"
          as="button"
          @click="activeTab = 'local'"
        />
        <FdsTabsItem
          :label="t('FdsDevModeStorage.tabs.sessionStorage')"
          :active="activeTab === 'session'"
          as="button"
          @click="activeTab = 'session'"
        />
        <FdsTabsItem
          :label="t('FdsDevModeStorage.tabs.cookies')"
          :active="activeTab === 'cookies'"
          as="button"
          @click="activeTab = 'cookies'"
        />
        <FdsTabsItem
          :label="t('FdsDevModeStorage.tabs.actions')"
          :active="activeTab === 'actions'"
          as="button"
          @click="activeTab = 'actions'"
        />
      </FdsTabs>

      <!-- localStorage TAB -->
      <FdsBlockInfo
        v-if="activeTab === 'local'"
        :heading="t('FdsDevModeStorage.tabs.localStorage')"
        icon="information"
        iconSize="small"
      >
        <div v-if="!localStorageEntries.length" class="text-sm text-gray-600">
          {{ t('FdsDevModeStorage.empty.localStorage') }}
        </div>
        <div v-else class="max-h-72 overflow-auto border border-gray-200 rounded-md">
          <table class="w-full text-left text-xs border-collapse">
            <thead class="bg-gray-50">
              <tr>
                <th class="py-2 px-3 font-semibold">{{ t('FdsDevModeStorage.keyLabel') }}</th>
                <th class="py-2 px-3 font-semibold">{{ t('FdsDevModeStorage.valueLabel') }}</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="entry in localStorageEntries"
                :key="`local-${entry.key}`"
                class="border-t border-gray-200 align-top cursor-pointer hover:bg-gray-50"
                @click="selectLocalEntry(entry)"
              >
                <td class="py-1.5 px-3 font-mono break-all">
                  {{ entry.key }}
                </td>
                <td class="py-1.5 px-3 font-mono whitespace-pre-wrap break-all">
                  {{ entry.value }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <div class="mt-4 space-y-2">
          <div class="flex flex-col gap-1">
            <label class="text-xs font-semibold">{{ t('FdsDevModeStorage.keyLabel') }}</label>
            <input
              v-model="localEditKey"
              class="border border-gray-300 rounded px-2 py-1 text-xs font-mono bg-white"
              :placeholder="t('FdsDevModeStorage.placeholders.localStorageKey')"
            />
          </div>
          <div class="flex flex-col gap-1">
            <label class="text-xs font-semibold">{{ t('FdsDevModeStorage.valueLabel') }}</label>
            <textarea
              v-model="localEditValue"
              rows="3"
              ref="localTextareaRef"
              class="border border-gray-300 rounded px-2 py-1 text-xs font-mono bg-white overflow-hidden"
              :placeholder="t('FdsDevModeStorage.placeholders.valueAsString')"
            />
          </div>

          <div v-if="localEditKey" class="mt-2 flex flex-wrap gap-2">
            <FdsButtonSecondary :text="t('FdsDevModeStorage.actions.delete')" size="sm" @click="deleteLocalEntry" />
            <FdsButtonPrimary :text="t('FdsDevModeStorage.actions.save')" size="sm" @click="saveLocalEntry" />
          </div>
        </div>
      </FdsBlockInfo>

      <!-- sessionStorage TAB -->
      <FdsBlockInfo
        v-else-if="activeTab === 'session'"
        :heading="t('FdsDevModeStorage.tabs.sessionStorage')"
        icon="information"
        iconSize="small"
      >
        <div v-if="!sessionStorageEntries.length" class="text-sm text-gray-600">
          {{ t('FdsDevModeStorage.empty.sessionStorage') }}
        </div>
        <div v-else class="max-h-72 overflow-auto border border-gray-200 rounded-md">
          <table class="w-full text-left text-xs border-collapse">
            <thead class="bg-gray-50">
              <tr>
                <th class="py-2 px-3 font-semibold">{{ t('FdsDevModeStorage.keyLabel') }}</th>
                <th class="py-2 px-3 font-semibold">{{ t('FdsDevModeStorage.valueLabel') }}</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="entry in sessionStorageEntries"
                :key="`session-${entry.key}`"
                class="border-t border-gray-200 align-top cursor-pointer hover:bg-gray-50"
                @click="selectSessionEntry(entry)"
              >
                <td class="py-1.5 px-3 font-mono break-all">
                  {{ entry.key }}
                </td>
                <td class="py-1.5 px-3 font-mono whitespace-pre-wrap break-all">
                  {{ entry.value }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <div class="mt-4 space-y-2">
          <div class="flex flex-col gap-1">
            <label class="text-xs font-semibold">{{ t('FdsDevModeStorage.keyLabel') }}</label>
            <input
              v-model="sessionEditKey"
              class="border border-gray-300 rounded px-2 py-1 text-xs font-mono bg-white"
              :placeholder="t('FdsDevModeStorage.placeholders.sessionStorageKey')"
            />
          </div>
          <div class="flex flex-col gap-1">
            <label class="text-xs font-semibold">{{ t('FdsDevModeStorage.valueLabel') }}</label>
            <textarea
              v-model="sessionEditValue"
              rows="3"
              ref="sessionTextareaRef"
              class="border border-gray-300 rounded px-2 py-1 text-xs font-mono bg-white overflow-hidden"
              :placeholder="t('FdsDevModeStorage.placeholders.valueAsString')"
            />
          </div>

          <div v-if="sessionEditKey" class="mt-2 flex flex-wrap gap-2">
            <FdsButtonSecondary :text="t('FdsDevModeStorage.actions.delete')" size="sm" @click="deleteSessionEntry" />
            <FdsButtonPrimary :text="t('FdsDevModeStorage.actions.save')" size="sm" @click="saveSessionEntry" />
          </div>
        </div>
      </FdsBlockInfo>

      <!-- Cookies TAB -->
      <FdsBlockInfo
        v-else-if="activeTab === 'cookies'"
        :heading="t('FdsDevModeStorage.tabs.cookies')"
        icon="information"
        iconSize="small"
      >
        <div v-if="!cookieEntries.length" class="text-sm text-gray-600">
          {{ t('FdsDevModeStorage.empty.cookies') }}
        </div>
        <div v-else class="max-h-72 overflow-auto border border-gray-200 rounded-md">
          <table class="w-full text-left text-xs border-collapse">
            <thead class="bg-gray-50">
              <tr>
                <th class="py-2 px-3 font-semibold">{{ t('FdsDevModeStorage.nameLabel') }}</th>
                <th class="py-2 px-3 font-semibold">{{ t('FdsDevModeStorage.valueLabel') }}</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="entry in cookieEntries"
                :key="`cookie-${entry.key}`"
                class="border-t border-gray-200 align-top cursor-pointer hover:bg-gray-50"
                @click="selectCookieEntry(entry)"
              >
                <td class="py-1.5 px-3 font-mono break-all">
                  {{ entry.key }}
                </td>
                <td class="py-1.5 px-3 font-mono whitespace-pre-wrap break-all">
                  {{ entry.value }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <div class="mt-4 space-y-2">
          <div class="flex flex-col gap-1">
            <label class="text-xs font-semibold">{{ t('FdsDevModeStorage.nameLabel') }}</label>
            <input
              v-model="cookieEditKey"
              class="border border-gray-300 rounded px-2 py-1 text-xs font-mono bg-white"
              :placeholder="t('FdsDevModeStorage.placeholders.cookieName')"
            />
          </div>
          <div class="flex flex-col gap-1">
            <label class="text-xs font-semibold">{{ t('FdsDevModeStorage.valueLabel') }}</label>
            <textarea
              v-model="cookieEditValue"
              rows="3"
              ref="cookieTextareaRef"
              class="border border-gray-300 rounded px-2 py-1 text-xs font-mono bg-white overflow-hidden"
              :placeholder="t('FdsDevModeStorage.placeholders.valueAsString')"
            />
          </div>

          <div v-if="cookieEditKey" class="mt-2 flex flex-wrap gap-2">
            <FdsButtonSecondary :text="t('FdsDevModeStorage.actions.delete')" size="sm" @click="deleteCookieEntry" />
            <FdsButtonPrimary :text="t('FdsDevModeStorage.actions.save')" size="sm" @click="saveCookieEntry" />
          </div>
        </div>
      </FdsBlockInfo>

      <!-- Actions TAB -->
      <FdsBlockInfo
        v-else-if="activeTab === 'actions'"
        :heading="t('FdsDevModeStorage.tabs.actions')"
        icon="information"
        iconSize="small"
      >
        <div v-if="!customActions?.length" class="text-sm text-gray-600">
          {{ t('FdsDevModeStorage.actions.emptyState') }}
        </div>
        <div v-else class="space-y-3">
          <div v-for="(action, index) in customActions" :key="index" class="p-3 border border-gray-200 rounded-md">
            <div class="flex items-center justify-between">
              <div class="flex-1 min-w-0 mr-3">
                <div class="font-semibold text-sm">{{ action.label }}</div>
                <div v-if="action.description" class="text-xs text-gray-500 mt-0.5">
                  {{ action.description }}
                </div>
              </div>
              <FdsButtonSecondary :text="action.label" size="sm" @click="runAction(index, action)" />
            </div>
            <div v-if="action.input" class="mt-2">
              <FdsInput
                :type="action.input.type ?? 'text'"
                :modelValue="getActionInputValue(index, action.input.defaultValue)"
                :placeholder="action.input.placeholder"
                @update:modelValue="setActionInputValue(index, $event ?? '')"
              />
            </div>
          </div>
        </div>
      </FdsBlockInfo>

      <div class="mt-4 flex justify-end gap-3">
        <FdsButtonSecondary :text="t('FdsDevModeStorage.actions.refresh')" @click="refreshStorageEntries" />
        <FdsButtonPrimary :text="t('FdsDevModeStorage.actions.close')" @click="handleOpenChange(false)" />
      </div>
    </div>
  </FdsModal>
</template>
