<template>
  <v-dialog v-model="dialog" max-width="640px" persistent>
    <v-card>
      <v-card-title class="d-flex align-center p-3 gap-2">
        <v-icon class="mr-3" color="primary">mdi-shield-check</v-icon>
        <span>{{ isEdit ? 'ویرایش سریال گارانتی' : 'افزودن سریال گارانتی جدید' }}</span>
      </v-card-title>

      <v-card-text>
        <v-form ref="form" v-model="valid">
          <v-row>
            <v-col cols="12" md="6">
              <v-text-field v-model="formData.serialNumber" label="شماره سریال *" :rules="[rules.serialNumber]" required
                :disabled="isEdit" variant="outlined" density="comfortable" hide-details="auto" maxlength="50" counter>
                <template #append>
                  <v-btn icon small @click="openScanner" :disabled="isEdit" color="primary" variant="text">
                    <v-icon size="20">mdi-qrcode-scan</v-icon>
                  </v-btn>
                </template>
              </v-text-field>
            </v-col>

            <v-col cols="12" md="6">
              <Hcommoditysearch
                :model-value="formData.commodity_id ?? undefined"
                @update:modelValue="(val: number | Record<string, any>) => { formData.commodity_id = typeof val === 'number' ? val : (val as any)?.id ?? null }"
                :return-object="false"
                label="محصول *"
                :rules="[rules.commodity]"
                required
                class="serial-commodity"
              />
            </v-col>

            <v-col cols="12" md="6">
              <h-date-picker v-model="formData.warrantyStartDate" label="تاریخ شروع گارانتی" :rules="[rules.date]" :ignore-year-range="true" dense
                outlined hide-details="auto" />
            </v-col>

            <v-col cols="12" md="6">
              <h-date-picker v-model="formData.warrantyEndDate" label="تاریخ پایان گارانتی"
                :rules="[(v: any) => rules.endDate(v, formData.warrantyStartDate)]" :ignore-year-range="true" dense outlined
                hide-details="auto" />
            </v-col>

            <v-col cols="12" md="6">
              <v-select v-model="formData.status" label="وضعیت" :items="statusOptions" item-title="title"
                item-value="value" variant="outlined" density="comfortable" hide-details="auto" />
            </v-col>

            <v-col v-if="isEdit" cols="12" md="6">
              <v-select v-model="formData.activation" label="وضعیت فعال‌سازی" :items="activationOptions"
                item-title="title" item-value="value" variant="outlined" density="comfortable" hide-details="auto" />
            </v-col>

            <v-col cols="12">
              <v-textarea v-model="formData.description" label="توضیحات" rows="3" auto-grow variant="outlined"
                density="comfortable" hide-details="auto" />
            </v-col>
          </v-row>
        </v-form>
      </v-card-text>

      <v-card-actions>
        <v-spacer />
        <v-btn color="grey" @click="close">انصراف</v-btn>
        <v-btn color="primary" @click="save" :loading="loading" :disabled="!valid">
          {{ isEdit ? 'ویرایش' : 'ذخیره' }}
        </v-btn>
      </v-card-actions>
    </v-card>

    <v-dialog v-model="showQrScanner" :max-width="isMobile ? '95vw' : 560" persistent>
      <v-card class="qr-card">
        <v-card-title class="qr-title">
          <v-icon left color="primary">mdi-qrcode-scan</v-icon>
          اسکن کد QR/بارکد
        </v-card-title>

        <v-card-text>
          <div class="qr-wrap">
            <div id="reader" ref="readerRef" class="qr-reader"></div>
          </div>
          <div class="qr-status">
            <v-alert v-if="scanError" type="error" variant="tonal" density="comfortable">
              {{ scanError }}
            </v-alert>
            <v-progress-circular v-if="loadingScan" indeterminate size="28" class="mt-3" color="primary" />
          </div>
        </v-card-text>

        <v-card-actions class="qr-actions">
          <v-btn :disabled="loadingScan" variant="outlined" color="primary" prepend-icon="mdi-camera-switch"
            @click="switchCamera">
            تغییر دوربین
          </v-btn>
          <v-spacer />
          <v-btn variant="text" @click="closeScanner">انصراف</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-snackbar v-model="showNotification" :color="notificationColor" :timeout="3000" location="top">
      {{ notificationText }}
      <template #actions>
        <v-btn color="white" text @click="showNotification = false">بستن</v-btn>
      </template>
    </v-snackbar>
  </v-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onBeforeUnmount } from 'vue'
import { Html5Qrcode, Html5QrcodeSupportedFormats, Html5QrcodeScannerState } from 'html5-qrcode'
import Hcommoditysearch from '@/components/forms/Hcommoditysearch.vue'

const props = defineProps<{
  modelValue: boolean
  serial?: any
  commodities: any[]
}>()

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  save: [data: any]
  close: []
}>()

const loading = ref(false)
const valid = ref(false)
const form = ref()
const commodityModel = ref<any>(null)

const formData = ref({
  serialNumber: '',
  commodity_id: null as number | null,
  description: '',
  warrantyStartDate: '',
  warrantyEndDate: '',
  status: 'available',
  activation: 'deactive',
  notes: ''
})

const rules = {
  required: (v: any) => !!v || 'این فیلد الزامی است',
  serialNumber: (v: any) => {
    if (!v) return 'شماره سریال الزامی است'
    if (!/^[A-Za-z0-9\-_.]+$/.test(v)) return 'شماره سریال نامعتبر است'
    if (v.length < 3) return 'شماره سریال باید حداقل ۳ کاراکتر باشد'
    if (v.length > 50) return 'شماره سریال نمی‌تواند بیشتر از ۵۰ کاراکتر باشد'
    return true
  },
  commodity: (v: any) => !!v || 'انتخاب محصول الزامی است',
  date: (v: any) => {
    if (!v) return true
    const d = new Date(v)
    return !isNaN(d.getTime()) || 'تاریخ نامعتبر است'
  },
  endDate: (v: any, s: any) => {
    if (!v || !s) return true
    const end = new Date(v); const start = new Date(s)
    return end > start || 'تاریخ پایان باید بعد از تاریخ شروع باشد'
  }
}

const statusOptions = [
  { title: 'آزاد', value: 'available' },
  { title: 'تخصیص یافته', value: 'allocated' },
  { title: 'تأیید شده', value: 'verified' },
  { title: 'متصل', value: 'bound' },
  { title: 'مصرف شده', value: 'consumed' },
  { title: 'باطل', value: 'void' }
]

const activationOptions = [
  { title: 'غیرفعال', value: 'deactive' },
  { title: 'فعال', value: 'active' }
]

const dialog = computed({
  get: () => props.modelValue,
  set: (v) => emit('update:modelValue', v)
})
const isEdit = computed(() => !!props.serial)
const isMobile = computed(() => window.innerWidth <= 768)

const showNotification = ref(false)
const notificationText = ref('')
const notificationColor = ref<'success' | 'error' | 'warning' | 'info'>('success')
const showNotify = (t: string, c: 'success' | 'error' | 'warning' | 'info' = 'success') => {
  notificationText.value = t
  notificationColor.value = c
  showNotification.value = true
}

const showQrScanner = ref(false)
const readerRef = ref<HTMLElement | null>(null)
let qr: Html5Qrcode | null = null
const loadingScan = ref(false)
const scanError = ref('')
const cameras = ref<{ id: string; label: string }[]>([])
const currentCamIndex = ref(0)
const qrboxSize = ref(240)

const computeQrBox = () => {
  const el = readerRef.value
  if (!el) return 260
  const w = Math.max(320, Math.floor(el.clientWidth))
  const size = Math.max(220, Math.min(380, Math.floor(w * 0.66)))
  return size
}

const openScanner = async () => {
  showQrScanner.value = true
  await nextTick()
  await startScanner()
}

const startScanner = async () => {
  try {
    loadingScan.value = true
    scanError.value = ''
    qrboxSize.value = computeQrBox()

    const devices = await Html5Qrcode.getCameras()
    if (!devices.length) { throw new Error('دوربین یافت نشد') }
    cameras.value = devices.map(d => ({ id: d.id, label: d.label }))
    if (currentCamIndex.value >= cameras.value.length) currentCamIndex.value = 0

    if (qr && (qr.getState?.() === Html5QrcodeScannerState.SCANNING)) await stopScanner()
    if (!qr) qr = new Html5Qrcode('reader', {
      verbose: false,
      formatsToSupport: [
        Html5QrcodeSupportedFormats.QR_CODE,
        Html5QrcodeSupportedFormats.CODE_128,
        Html5QrcodeSupportedFormats.CODE_39,
        Html5QrcodeSupportedFormats.EAN_13,
        Html5QrcodeSupportedFormats.UPC_A,
        Html5QrcodeSupportedFormats.DATA_MATRIX
      ],
      experimentalFeatures: { useBarCodeDetectorIfSupported: true }
    })

    await qr.start(
      { deviceId: { exact: cameras.value[currentCamIndex.value].id } },
      { fps: 12, qrbox: { width: qrboxSize.value, height: qrboxSize.value }, aspectRatio: 1.333 },
      (decodedText: string) => {
        if (decodedText) {
          formData.value.serialNumber = decodedText.trim()
          showNotify('کد با موفقیت اسکن شد', 'success')
          closeScanner()
        }
      },
      (_err: string) => { }
    )
  } catch (e: any) {
    scanError.value = e?.message || 'خطا در راه‌اندازی دوربین'
  } finally {
    loadingScan.value = false
  }
}

const stopScanner = async () => {
  if (!qr) return
  try {
    const state = qr.getState?.()
    if (state === Html5QrcodeScannerState.SCANNING) await qr.stop()
    await qr.clear()
  } catch { }
}

const closeScanner = async () => {
  await stopScanner()
  showQrScanner.value = false
}

const switchCamera = async () => {
  if (!cameras.value.length) return
  currentCamIndex.value = (currentCamIndex.value + 1) % cameras.value.length
  await stopScanner()
  await nextTick()
  await startScanner()
}

const save = async () => {
  const res = await form.value?.validate()
  const ok = typeof res === 'object' ? res.valid : !!res
  if (!ok) return
  if (!formData.value.serialNumber || !formData.value.commodity_id) return
  try {
    loading.value = true
    emit('save', { ...formData.value })
  } finally {
    loading.value = false
  }
}

const close = () => {
  closeScanner()
  emit('close')
}

const resetForm = () => {
  formData.value = {
    serialNumber: '',
    commodity_id: null,
    description: '',
    warrantyStartDate: '',
    warrantyEndDate: '',
    status: 'available',
    activation: 'deactive',
    notes: ''
  }
  commodityModel.value = null
  form.value?.resetValidation()
}

const loadSerialData = () => {
  if (props.serial) {
    formData.value = {
      serialNumber: props.serial.serialNumber || '',
      commodity_id: Number(props.serial.commodity?.id) || null,
      description: props.serial.description || '',
      warrantyStartDate: props.serial.warrantyStartDate || '',
      warrantyEndDate: props.serial.warrantyEndDate || '',
      status: props.serial.status || 'available',
      activation: props.serial.activation || 'deactive',
      notes: props.serial.notes || ''
    }
    commodityModel.value = props.commodities.find(c => c.id === formData.value.commodity_id) || null
  } else {
    resetForm()
  }
}

const customFilter = (item: any, q: string) => {
  const t = String(item?.name || '').toLowerCase()
  const s = String(q || '').toLowerCase()
  return t.indexOf(s) > -1
}

const handleCommoditySelect = (c: any) => {
  formData.value.commodity_id = c?.id ? Number(c.id) : null
}

watch(() => props.serial, () => nextTick(loadSerialData), { immediate: true })
watch(() => props.modelValue, v => { if (v) nextTick(loadSerialData) })
onBeforeUnmount(() => { closeScanner() })
</script>

<style>
/* normalize Hcommoditysearch height with other inputs */
.serial-commodity :deep(.v-field) { min-height: 56px; }
.serial-commodity :deep(.v-field__input) { padding-top: 14px; padding-bottom: 14px; }
#qr-shaded-region {
  display: none !important;
}

video {
  border-radius: 12px;
  padding: 2px;
}

.v-dialog {
  direction: rtl
}

.qr-card {
  max-width: 95vw;
  border-radius: 16px
}

.qr-title {
  text-align: center;
  padding: 14px 16px
}

.qr-wrap {
  position: relative;
  width: 100%;
  max-width: 560px;
  margin: 0 auto
}

.qr-reader {
  width: 100%;
  min-height: 320px;
  border-radius: 12px;
  border: 1px solid #e5e7eb;
  overflow: hidden;
  background: #000;
}

/* ویدئو تولیدی کتابخانه */
:deep(#reader video) {
  width: 100% !important;
  height: auto !important;
  display: block !important;
  object-fit: cover;
  min-height: 240px;
}

/* کانتینر داخلی کتابخانه راست به چپ نشه */
:deep(#reader div) {
  direction: ltr
}

/* وضعیت‌ها */
.qr-status {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 12px
}

.qr-actions {
  padding: 12px 16px
}

/* ریسپانسیو */
@media (max-width:1024px) {
  .qr-reader {
    min-height: 300px
  }

  :deep(#reader video) {
    min-height: 220px
  }
}

@media (max-width:768px) {
  .qr-card {
    max-width: 95vw
  }

  .qr-reader {
    min-height: 260px
  }

  :deep(#reader video) {
    min-height: 200px
  }
}

@media (max-width:480px) {
  .qr-reader {
    min-height: 220px
  }

  :deep(#reader video) {
    min-height: 180px
  }
}

.v-input.v-input--horizontal.v-input--center-affix.v-input--density-compact.v-theme--light.v-locale--is-rtl.v-input--error.v-text-field.my-0 {
    height: 3rem;
}
</style>
