<template>
  <div class="form-group">
    <label :for="fieldId" class="form-label">
      {{ label }}
      <span v-if="required" class="text-danger" aria-label="required">(필수)</span>
    </label>
    <input
      v-if="inputComponent === 'input'"
      :id="fieldId"
      :value="modelValue"
      :type="htmlInputType"
      :class="['form-control', { 'is-invalid': !!error }]"
      :aria-invalid="!!error"
      :aria-describedby="error ? `${fieldId}-error` : undefined"
      :required="required"
      :placeholder="placeholder"
      :min="min"
      :max="max"
      :pattern="pattern"
      @blur="$emit('blur')"
      @input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)"
    />
    <input
      v-else-if="inputComponent === 'checkbox'"
      :id="fieldId"
      type="checkbox"
      :checked="modelValue"
      :class="['form-check-input', { 'is-invalid': !!error }]"
      :aria-invalid="!!error"
      :aria-describedby="error ? `${fieldId}-error` : undefined"
      :required="required"
      @blur="$emit('blur')"
      @change="$emit('update:modelValue', ($event.target as HTMLInputElement).checked)"
    />
    <select
      v-else-if="inputComponent === 'select'"
      :id="fieldId"
      :value="modelValue"
      :class="['form-control', { 'is-invalid': !!error }]"
      :aria-invalid="!!error"
      :aria-describedby="error ? `${fieldId}-error` : undefined"
      :required="required"
      @blur="$emit('blur')"
      @change="$emit('update:modelValue', ($event.target as HTMLSelectElement).value)"
    >
      <slot name="options" />
    </select>
    <textarea
      v-else
      :id="fieldId"
      :value="modelValue"
      :class="['form-control', { 'is-invalid': !!error }]"
      :aria-invalid="!!error"
      :aria-describedby="error ? `${fieldId}-error` : undefined"
      :required="required"
      :placeholder="placeholder"
      @blur="$emit('blur')"
      @input="$emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)"
    />
    <small v-if="displayHint" :id="`${fieldId}-hint`" class="form-text text-muted">
      {{ displayHint }}
    </small>
    <div v-if="error" :id="`${fieldId}-error`" class="invalid-feedback d-block">
      {{ error }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { schemaTypeToInputType, type InputType, getHintText } from '@/utils/fieldTypes'

interface Props {
  modelValue: string | number | boolean
  label: string
  fieldId?: string
  type?: InputType | 'password' | 'select' | 'textarea'
  schemaType?: string // JSON schema type (auto-infers input type)
  schemaFormat?: string // JSON schema format (e.g., 'email', 'date')
  enumValues?: any[] // For select inputs
  error?: string
  hint?: string
  placeholder?: string
  required?: boolean
  min?: number
  max?: number
  step?: number // For number inputs (e.g., 0.01 for currency)
  pattern?: string
}

const props = withDefaults(defineProps<Props>(), {
  required: false
})

defineEmits<{
  'update:modelValue': [value: string | number | boolean]
  blur: []
  input: []
}>()

const fieldId = computed(() => props.fieldId || `field-${Math.random().toString(36).slice(7)}`)

// 자동 타입 추론: 명시적 type이 없으면 schemaType/schemaFormat에서 추론
const resolvedType = computed<InputType | 'password' | 'select' | 'textarea'>(() => {
  if (props.type) {
    return props.type
  }

  // schemaType/schemaFormat에서 자동 추론
  const inferred = schemaTypeToInputType(props.schemaType, props.schemaFormat, props.enumValues)
  return inferred
})

const inputComponent = computed(() => {
  switch (resolvedType.value) {
    case 'select': return 'select'
    case 'textarea': return 'textarea'
    case 'checkbox': return 'checkbox'
    default: return 'input'
  }
})

// 힌트 자동 생성 (props.hint가 없으면)
const displayHint = computed(() => {
  if (props.hint) return props.hint
  return getHintText(resolvedType.value as InputType, {
    min: props.min,
    max: props.max,
    pattern: props.pattern
  })
})

// 타입별 HTML input type 결정
const htmlInputType = computed(() => {
  const type = resolvedType.value
  // HTML input type과 Vue용 type 구분
  if (type === 'select' || type === 'textarea' || type === 'password') {
    return 'text' // placeholder만 사용
  }
  return type === 'checkbox' ? 'checkbox' : (type as any)
})
</script>

<style scoped>
.form-group {
  margin-bottom: 1rem;
}

.form-label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.5rem;
  font-size: 0.95rem;
}

.text-danger {
  color: #dc3545;
  margin-left: 0.25rem;
}

.form-control {
  display: block;
  width: 100%;
  padding: 0.5rem 0.75rem;
  font-size: 1rem;
  line-height: 1.5;
  color: #495057;
  background-color: #fff;
  border: 1px solid #ced4da;
  border-radius: 0.25rem;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.form-control:focus {
  color: #495057;
  background-color: #fff;
  border-color: #80bdff;
  outline: 0;
  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}

.form-control.is-invalid {
  border-color: #dc3545;
}

.form-control.is-invalid:focus {
  border-color: #dc3545;
  box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}

.form-text {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: #6c757d;
}

.invalid-feedback {
  display: block;
  color: #dc3545;
  font-size: 0.875rem;
  margin-top: 0.25rem;
}

textarea.form-control {
  resize: vertical;
  min-height: 6rem;
}

select.form-control {
  appearance: none;
  padding-right: 1.5rem;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 16px 12px;
}
</style>
