<script setup lang="ts">
/**
 * Save / load templates against the iDempiere CUST_LabelTemplate CRUD
 * (server/api/integrations/label-templates/*). Reads the current design from
 * the injected `ldDesigner`; "Save" overwrites when the design already has an
 * id, otherwise creates. Loading parses CUST_DesignJSON back into the model.
 */
import { toast } from 'bulma-toast'
import type { LabelTemplate } from '~/composables/useLabelDesign'

const open = defineModel<boolean>('open', { default: false })

const designer = inject('ldDesigner') as ReturnType<typeof useLabelDesign>
const { template } = designer

const orgId = useCookie('logship_organization_id')

interface Row { id: number; name: string; description: string; design: LabelTemplate | null }

const rows = ref<Row[]>([])
const loading = ref(false)
const saving = ref(false)
const alert = ref({ status: '', message: '' })

const mapRecord = (rec: any): Row => {
  const raw = rec?.CUST_DesignJSON ?? rec?.cust_designjson ?? rec?.CUST_DesignJson ?? ''
  let design: LabelTemplate | null = null
  try { design = raw ? JSON.parse(raw) : null } catch { design = null }
  return {
    id: Number(rec?.id),
    name: rec?.Name ?? rec?.name ?? 'Untitled',
    description: rec?.Description ?? rec?.description ?? '',
    design
  }
}

const fetchList = async () => {
  loading.value = true
  alert.value = { status: '', message: '' }
  try {
    const res: any = await $fetch('/api/integrations/label-templates', { headers: useRequestHeaders(['cookie']) })
    const records = Array.isArray(res?.records) ? res.records : []
    rows.value = records.map(mapRecord).filter((r: Row) => Number.isFinite(r.id) && r.id > 0)
  } catch (err: any) {
    alert.value = { status: '500', message: err?.message || 'Failed to load templates' }
  } finally {
    loading.value = false
  }
}

watch(open, (v) => { if (v) fetchList() })

const save = async (asCopy = false) => {
  saving.value = true
  alert.value = { status: '', message: '' }
  try {
    const isUpdate = !asCopy && !!template.value.id
    const name = asCopy ? `${template.value.name} copy` : (template.value.name || 'Untitled label')
    if (asCopy) template.value.id = undefined
    template.value.name = name
    const design = JSON.stringify(template.value)
    let res: any
    if (isUpdate) {
      res = await $fetch('/api/integrations/label-templates/update', {
        method: 'PUT',
        headers: useRequestHeaders(['cookie']),
        body: { id: template.value.id, name, description: template.value.description || '', isActive: true, design }
      })
    } else {
      res = await $fetch('/api/integrations/label-templates/store', {
        method: 'POST',
        headers: useRequestHeaders(['cookie']),
        body: { organizationId: orgId.value, name, description: template.value.description || '', design }
      })
      if (res?.id) template.value.id = Number(res.id)
    }
    if (Number(res?.status) === 200 || res?.id) {
      toast({ message: 'Template saved', type: 'is-success', duration: 2000, position: 'bottom-right' })
      await fetchList()
    } else {
      alert.value = { status: String(res?.status || '500'), message: res?.message || 'Save failed' }
    }
  } catch (err: any) {
    alert.value = { status: '500', message: err?.message || 'Save failed' }
  } finally {
    saving.value = false
  }
}

const load = (row: Row) => {
  if (!row.design) {
    alert.value = { status: '500', message: 'This template could not be parsed.' }
    return
  }
  const tpl = createTemplate(row.design)
  tpl.id = row.id
  tpl.name = row.name
  designer.loadTemplate(tpl)
  open.value = false
}

const remove = async (row: Row) => {
  try {
    await $fetch('/api/integrations/label-templates/destroy', {
      method: 'DELETE',
      headers: useRequestHeaders(['cookie']),
      body: { ids: [row.id] }
    })
    if (template.value.id === row.id) template.value.id = undefined
    await fetchList()
    toast({ message: 'Template deleted', type: 'is-success', duration: 1800, position: 'bottom-right' })
  } catch (err: any) {
    alert.value = { status: '500', message: err?.message || 'Delete failed' }
  }
}
</script>

<template>
  <UModal v-model:open="open" :ui="{ content: 'sm:max-w-2xl' }">
    <template #content>
      <div class="ldModal">
        <div class="ldModal__head">
          <h3><span class="ti ti-device-floppy mr-1"></span> Templates</h3>
          <button type="button" class="ldModal__close" @click="open = false"><span class="ti ti-x"></span></button>
        </div>

        <div class="ldModal__body">
          <div v-if="alert.status" class="notification is-danger is-light py-2 px-3">
            {{ alert.message }}
          </div>

          <div class="ldSaveRow">
            <input class="input" placeholder="Template name" v-model="template.name" />
            <button type="button" class="button is-primary" :class="{ 'is-loading': saving }" @click="save(false)">
              {{ template.id ? 'Save' : 'Create' }}
            </button>
            <button v-if="template.id" type="button" class="button" :class="{ 'is-loading': saving }" @click="save(true)">Save as copy</button>
          </div>

          <hr class="my-3" />

          <p class="ldModal__sub">Saved templates</p>
          <div v-if="loading" class="ldModal__loading"><span class="ti ti-loader ldSpin"></span> Loading…</div>
          <div v-else-if="!rows.length" class="ldModal__empty">No saved templates yet.</div>
          <ul v-else class="ldList">
            <li v-for="row in rows" :key="row.id" class="ldList__item" :class="{ 'is-current': row.id === template.id }">
              <div class="ldList__info">
                <span class="ldList__name">{{ row.name }}</span>
                <span v-if="row.design" class="ldList__meta">{{ row.design.size.wMm }} × {{ row.design.size.hMm }} mm · {{ row.design.elements.length }} elements</span>
                <span v-else class="ldList__meta ldList__meta--bad">unreadable design</span>
              </div>
              <div class="ldList__actions">
                <button type="button" class="button is-small is-link is-light" @click="load(row)">Load</button>
                <button type="button" class="button is-small is-danger is-light" @click="remove(row)"><span class="ti ti-trash"></span></button>
              </div>
            </li>
          </ul>
        </div>
      </div>
    </template>
  </UModal>
</template>

<style scoped>
.ldModal { background: var(--theme-bg-primary, #fff); border-radius: 12px; overflow: hidden; }
.ldModal__head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid var(--theme-border, #ececef); }
.ldModal__head h3 { font-size: 16px; font-weight: 700; }
.ldModal__close { background: none; border: none; cursor: pointer; font-size: 20px; line-height: 1; opacity: 0.6; }
.ldModal__close:hover { opacity: 1; }
.ldModal__body { padding: 16px 18px; }
.ldModal__sub { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.55; margin-bottom: 8px; }
.ldModal__loading, .ldModal__empty { padding: 16px 2px; opacity: 0.6; font-size: 13px; }
.ldSaveRow { display: flex; gap: 8px; }
.ldSaveRow .input { flex: 1; }
.ldList { display: flex; flex-direction: column; gap: 6px; max-height: 320px; overflow: auto; }
.ldList__item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px; border: 1px solid var(--theme-border, #ececef); border-radius: 8px; }
.ldList__item.is-current { border-color: #3b82f6; background: rgba(59, 130, 246, 0.06); }
.ldList__info { display: flex; flex-direction: column; }
.ldList__name { font-weight: 600; font-size: 14px; }
.ldList__meta { font-size: 11px; opacity: 0.6; }
.ldList__meta--bad { color: #d64545; }
.ldList__actions { display: flex; gap: 6px; }
.ldSpin { display: inline-block; animation: ldspin 0.8s linear infinite; }
@keyframes ldspin { to { transform: rotate(360deg); } }
</style>
