<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useServicesStore } from '@PeopleManager/stores/servicesStore'
import { CollectionObject } from '@PeopleManager/models/collection'
import type { ServiceObject } from '@PeopleManager/models/service'

// Store
const servicesStore = useServicesStore()

// Props
const props = defineProps<{
  modelValue: boolean
  collection: CollectionObject | null
  mode: 'create' | 'edit'
}>()

// Emits
const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  'save': [collection: CollectionObject, service: ServiceObject]
  'delete': [collection: CollectionObject]
}>()

// State
const services = ref<ServiceObject[]>([])
const editingCollection = ref<CollectionObject | null>(null)
const editingCollectionService = ref<ServiceObject | null>(null)
const editingCollectionValidated = ref(false)
const colorMenuOpen = ref(false)
const colorOptions = [
  '#FF6B6B', '#FF8E4D', '#FFB347', '#FFD166', '#E5FF7F', '#B5E86D',
  '#7CD992', '#46CBB7', '#2ECCCB', '#27B1E6', '#2196F3', '#2E6FE3',
  '#3A4CC9', '#5A3FC0', '#7F3FBF', '#B339AE', '#DE3A9B', '#FF6FB7'
]

const COLORS_PER_ROW = 6
const colorRows = computed(() => {
  const rows: string[][] = []
  for (let i = 0; i < colorOptions.length; i += COLORS_PER_ROW) {
    rows.push(colorOptions.slice(i, i + COLORS_PER_ROW))
  }
  return rows
})

// Computed
const dialogOpen = computed({
  get: () => props.modelValue,
  set: (value: boolean) => emit('update:modelValue', value)
})

// Functions
const onOpen = async () => {
  if (services.value.length === 0) {
    services.value = Object.values(await servicesStore.list())
  }

  if (!props.collection) {
    return
  }

  // Clone the collection to avoid mutating the original
  editingCollection.value = props.collection.clone()
  
  if (props.collection.identifier) {
    // Edit mode - find the service
    editingCollectionService.value = services.value.find(s =>
      `${s.provider}:${s.identifier}` === String(props.collection!.service)
    ) || null
  } else {
    // Create mode - use first service that can create
    editingCollectionService.value = services.value.filter(s => s.capable('CollectionCreate'))[0] || null
  }
}

const onSave = () => {
  if (!editingCollection.value || !editingCollectionService.value) {
    return
  }
  emit('save', editingCollection.value, editingCollectionService.value)
  dialogOpen.value = false
}

const onDelete = () => {
  if (!editingCollection.value) {
    return
  }
  emit('delete', editingCollection.value)
  dialogOpen.value = false
}

const onColorSelect = (color: string | null, closeMenu = true) => {
  if (!editingCollection.value) {
    return
  }
  editingCollection.value.properties.color = color
  if (closeMenu) {
    colorMenuOpen.value = false
  }
}

const onCustomColorChange = (color: string) => {
  if (!color) {
    return
  }
  onColorSelect(color, false)
}

// Watch for dialog opening
watch(() => props.modelValue, async (newValue) => {
  if (newValue) {
    await onOpen()
  }
})
</script>

<template>
  <v-dialog
    v-model="dialogOpen"
    max-width="500"
    persistent
  >
    <v-card>
      <v-card-title>
        <v-icon icon="mdi-book-plus" class="mr-2" />
        {{ mode === 'create' ? 'Create New Address Book' : 'Edit Address Book' }}
      </v-card-title>

      <v-divider />

      <v-card-text v-if="editingCollection" class="pt-4">
        <v-form v-model="editingCollectionValidated" ref="collectionEditor">
          <v-combobox v-show="mode === 'create' && services.length > 1"
            v-model="editingCollectionService"
            label="Service"
            :items="services.filter(s => s.capable('CollectionCreate'))"
            item-title="label"
            item-value="identifier"
            required
            :rules="[(v: ServiceObject) => !!v || 'Service is required']"
          />

          <div class="mb-4"><strong>Service </strong> {{ editingCollection.service }}</div>

          <v-text-field
            v-model="editingCollection.properties.label"
            label="Label"
            required
            :rules="[(v: string) => !!v || 'Label is required']"
          >
            <template #append-inner>
              <v-menu
                v-model="colorMenuOpen"
                :close-on-content-click="false"
                location="bottom end"
                offset="8"
              >
                <template #activator="{ props: menuProps }">
                  <v-btn
                    v-bind="menuProps"
                    icon
                    variant="text"
                    size="small"
                    :style="{ color: editingCollection.properties.color || 'var(--v-theme-on-surface)' }"
                    aria-label="Select book color"
                    title="Select color"
                  >
                    <v-icon icon="mdi-palette" />
                  </v-btn>
                </template>

                <v-card class="pa-2 color-menu" elevation="4">
                  <div class="color-menu-header">
                    <v-btn
                      variant="text"
                      size="small"
                      class="color-menu-header__close"
                      aria-label="Close"
                      title="Close"
                    >
                      <v-icon icon="mdi-close" />
                    </v-btn>
                  </div>
                  <div class="color-menu-body__presets">
                    <div
                      v-for="(rowColors, rowIndex) in colorRows"
                      :key="`color-row-${rowIndex}`"
                      class="color-menu-body__row"
                    >
                      <v-btn
                        v-for="color in rowColors"
                        :key="color"
                        variant="flat"
                        size="small"
                        class="color-menu-body__presets--swatch"
                        :class="{ 'color-menu-body__presets--swatch--active': editingCollection.properties.color === color }"
                        :style="{ backgroundColor: color }"
                        @click="onColorSelect(color)">
                        <v-icon
                          v-if="editingCollection.properties.color === color"
                          icon="mdi-check"
                          size="x-small"
                          color="white"
                        />
                      </v-btn>
                    </div>
                  </div>

                  <div class="color-menu-body__picker">
                    <v-color-picker
                      v-model="editingCollection.properties.color"
                      mode="hex"
                      hide-canvas
                      width="100%"
                      elevation="0"
                      @update:model-value="onCustomColorChange"
                    />
                  </div>
                </v-card>
              </v-menu>
            </template>
          </v-text-field>

          <v-textarea
            v-model="editingCollection.properties.description"
            label="Description"
            rows="2"
          />
        </v-form>
      </v-card-text>

      <v-divider />

      <v-card-actions class="justify-space-between align-center">
        <div>
          <v-btn
            v-if="mode === 'edit' && editingCollectionService?.capable('CollectionDelete')"
            color="error"
            variant="text"
            @click="onDelete"
          >
            Delete
          </v-btn>
        </div>

        <div class="d-flex align-center">
          <v-btn
            variant="text"
            @click="dialogOpen = false"
          >
            Cancel
          </v-btn>
          <v-btn
            color="primary"
            variant="flat"
            :disabled="!editingCollectionValidated"
            @click="onSave"
          >
            {{ mode === 'create' ? 'Create' : 'Save' }}
          </v-btn>
        </div>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<style scoped>
.color-menu {
  max-width: 320px;
}

.color-menu-header {
  display: flex;
  justify-content: flex-end;
  width: 100%;
  margin-bottom: 16px;
}

.color-menu-header__close {
  margin-left: auto;
}

.color-menu-body__presets {
  width: 100%;
  margin-bottom: 20px;
}

.color-menu-body__row {
  display: flex;
  gap: 8px;
}

.color-menu-body__picker {
  margin-top: 20px;
}
</style>
