<script setup lang="ts">
import { computed, ref } from 'vue'

export interface KsCheckboxProps {
  modelValue: boolean | string[]
  label?: string
  value?: any
  disabled?: boolean
  readonly?: boolean
  indeterminate?: boolean
  inputId?: string
  description?: string
  error?: string
  size?: 'sm' | 'md' | 'lg'
}

const props = withDefaults(defineProps<KsCheckboxProps>(), {
  disabled: false,
  readonly: false,
  indeterminate: false,
  size: 'md',
})

const emit = defineEmits<{
  'update:modelValue': [value: boolean | string[]]
  change: [value: boolean | string[]]
}>()

const isFocused = ref(false)
const id = computed(() => props.inputId || `checkbox-${Math.random().toString(36).substr(2, 9)}`)

const isChecked = computed(() => {
  if (Array.isArray(props.modelValue)) {
    return props.modelValue.includes(props.value)
  }
  return props.modelValue === true
})

const containerClass = computed(() => [
  'ks-checkbox',
  `ks-checkbox--${props.size}`,
  {
    'ks-checkbox--focused': isFocused.value,
    'ks-checkbox--checked': isChecked.value,
    'ks-checkbox--indeterminate': props.indeterminate,
    'ks-checkbox--disabled': props.disabled,
    'ks-checkbox--error': !!props.error,
  },
])

const handleChange = (event: Event) => {
  const target = event.target as HTMLInputElement
  let newValue

  if (Array.isArray(props.modelValue)) {
    newValue = target.checked
      ? [...props.modelValue, props.value]
      : props.modelValue.filter(v => v !== props.value)
  } else {
    newValue = target.checked
  }

  emit('update:modelValue', newValue)
  emit('change', newValue)
}

const handleFocus = () => {
  isFocused.value = true
}

const handleBlur = () => {
  isFocused.value = false
}
</script>

<template>
  <div :class="containerClass">
    <div class="ks-checkbox__wrapper">
      <input
        :id="id"
        type="checkbox"
        class="ks-checkbox__input"
        :checked="isChecked"
        :disabled="disabled"
        :readonly="readonly"
        :value="value"
        :aria-label="label"
        :aria-invalid="!!error"
        :aria-describedby="error || description ? `${id}-hint` : undefined"
        @change="handleChange"
        @focus="handleFocus"
        @blur="handleBlur"
      />
      <div class="ks-checkbox__box">
        <svg v-if="isChecked && !indeterminate" class="ks-checkbox__check" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <polyline points="20 6 9 17 4 12" />
        </svg>
        <div v-if="indeterminate" class="ks-checkbox__indeterminate" />
      </div>
    </div>

    <div class="ks-checkbox__content">
      <label :for="id" class="ks-checkbox__label">{{ label }}</label>
      <div v-if="description || error" :id="`${id}-hint`" :class="{ 'ks-checkbox__error': error, 'ks-checkbox__description': description }">
        {{ error || description }}
      </div>
    </div>
  </div>
</template>

<style scoped>
.ks-checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-3);
  cursor: pointer;
  user-select: none;
}

.ks-checkbox--sm {
  --box-size: 16px;
  --font-size: var(--font-size-xs);
}

.ks-checkbox--md {
  --box-size: 20px;
  --font-size: var(--font-size-sm);
}

.ks-checkbox--lg {
  --box-size: 24px;
  --font-size: var(--font-size-base);
}

/* Input wrapper */
.ks-checkbox__wrapper {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 2px;
}

/* Hidden input */
.ks-checkbox__input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  pointer-events: none;
}

/* Checkbox box */
.ks-checkbox__box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--box-size);
  height: var(--box-size);
  border: 2px solid var(--color-border-primary);
  border-radius: var(--border-radius-sm);
  background-color: var(--color-background-primary);
  transition: all var(--transition-normal);
  color: transparent;
}

/* Hover state */
.ks-checkbox:not(.ks-checkbox--disabled) .ks-checkbox__input:hover ~ .ks-checkbox__box {
  border-color: var(--color-primary-500);
}

/* Checked state */
.ks-checkbox--checked .ks-checkbox__box {
  background-color: var(--color-primary-500);
  border-color: var(--color-primary-500);
  color: white;
}

.ks-checkbox--checked:not(.ks-checkbox--disabled) .ks-checkbox__input:hover ~ .ks-checkbox__box {
  background-color: var(--color-primary-600);
  border-color: var(--color-primary-600);
}

/* Indeterminate state */
.ks-checkbox--indeterminate .ks-checkbox__box {
  background-color: var(--color-primary-500);
  border-color: var(--color-primary-500);
}

/* Focus state */
.ks-checkbox--focused .ks-checkbox__box {
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

/* Disabled state */
.ks-checkbox--disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Error state */
.ks-checkbox--error .ks-checkbox__box {
  border-color: var(--color-danger-500);
}

.ks-checkbox--error.ks-checkbox--checked .ks-checkbox__box {
  background-color: var(--color-danger-500);
  border-color: var(--color-danger-500);
}

/* Check icon */
.ks-checkbox__check {
  width: 12px;
  height: 12px;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Indeterminate icon */
.ks-checkbox__indeterminate {
  width: 8px;
  height: 2px;
  background-color: white;
  border-radius: 1px;
}

/* Content */
.ks-checkbox__content {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1);
  flex: 1;
}

/* Label */
.ks-checkbox__label {
  font-size: var(--font-size);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-primary);
  cursor: pointer;
  line-height: 1.4;
}

.ks-checkbox--disabled .ks-checkbox__label {
  cursor: not-allowed;
}

/* Description/Error text */
.ks-checkbox__description {
  font-size: var(--font-size-xs);
  color: var(--color-text-secondary);
  line-height: 1.4;
}

.ks-checkbox__error {
  font-size: var(--font-size-xs);
  color: var(--color-danger-500);
  line-height: 1.4;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .ks-checkbox__box {
    transition: none;
  }
}
</style>
