/**
 * useFlowEditor.js — Global reactive store for the Flow Editor dialog.
 *
 * Odoo-style "inline create from anywhere": any page can call openFlow()
 * to pop the editor without having to route to Settings.
 *
 * The shared state (singleton module-level refs) is consumed by
 * <FlowEditorDialog /> mounted in MainLayout. Pages simply call
 * `const fe = useFlowEditor(); fe.openTemplate('FT-00001')`.
 *
 * API (all methods optimised to avoid redundant fetches):
 *   openTemplate(name, opts?)  — load an existing FT by name and open editor
 *   openNew(opts?)             — open editor with a blank draft
 *   close()                    — close + clear state
 *   isOpen       Ref<boolean>
 *   template     Ref<Object|null>  — current FT doc being edited
 *   loading      Ref<boolean>
 *   error        Ref<string|null>
 *   dirty        Ref<boolean>      — unsaved changes flag
 *
 * Options accepted by openTemplate / openNew:
 *   { category, applies_to, kind }  — preset fields for new templates
 *   { onSaved(tpl) }                — callback after a successful save
 *   { context }                     — opaque host context (for telemetry)
 */

import { ref, reactive, readonly } from 'vue'
import {
  getFlowTemplate,
  createFlowTemplate,
  updateFlowTemplate,
  duplicateFlowTemplate,
  deleteFlowTemplate,
} from 'src/api/flow-templates'

// ── Module-level shared state (singleton) ───────────────────────────────────

const isOpen      = ref(false)
const template    = ref(null)        // the doc currently being edited
const templateName = ref(null)       // non-null once saved once
const loading     = ref(false)
const saving      = ref(false)
const error       = ref(null)
const dirty       = ref(false)
const onSavedCbs  = ref([])          // callbacks from the caller
const mode        = ref('edit')      // 'new' | 'edit' | 'view'

/** Build a blank FT draft with sensible defaults. */
function blankTemplate (opts = {}) {
  return {
    template_name: '',
    category: opts.category || 'other',
    applies_to: opts.applies_to || null,
    icon: opts.icon || 'account_tree',
    is_active: 1,
    is_system: 0,
    version: 1,
    description: '',
    trigger_event: opts.trigger_event || null,
    trigger_condition: '',
    flow_definition: {
      version: 1,
      trigger: { type: opts.kind === 'agent' ? 'manual' : 'on_flow_start' },
      variables: {},
      steps: [],
    },
    tags: '',
    notes: '',
  }
}

// ── Actions ─────────────────────────────────────────────────────────────────

/**
 * Open the editor on an existing template.
 * Fetches full body (incl. flow_definition) from the Hub.
 */
async function openTemplate (name, opts = {}) {
  if (!name) return openNew(opts)
  error.value = null
  loading.value = true
  isOpen.value = true
  mode.value = 'edit'
  templateName.value = name
  onSavedCbs.value = opts.onSaved ? [opts.onSaved] : []
  try {
    const tpl = await getFlowTemplate(name)
    // Ensure flow_definition is a live object (Hub returns parsed JSON)
    if (!tpl.flow_definition || typeof tpl.flow_definition === 'string') {
      try { tpl.flow_definition = JSON.parse(tpl.flow_definition || '{}') }
      catch { tpl.flow_definition = { steps: [] } }
    }
    if (!tpl.flow_definition.steps) tpl.flow_definition.steps = []
    template.value = tpl
    dirty.value = false
  } catch (e) {
    error.value = e.message
    isOpen.value = false
  } finally {
    loading.value = false
  }
}

/** Open the editor on a fresh draft. Save-on-Enregistrer creates it. */
function openNew (opts = {}) {
  error.value = null
  isOpen.value = true
  mode.value = 'new'
  templateName.value = null
  template.value = blankTemplate(opts)
  dirty.value = false
  onSavedCbs.value = opts.onSaved ? [opts.onSaved] : []
}

/** Close the editor. Caller is responsible for confirming unsaved changes. */
function close (force = false) {
  if (dirty.value && !force) {
    if (!window.confirm('Modifications non sauvegardées. Fermer quand même ?')) return
  }
  isOpen.value = false
  template.value = null
  templateName.value = null
  dirty.value = false
  error.value = null
}

/** Mark the editor state as dirty (called by child on any mutation). */
function markDirty () { dirty.value = true }

/**
 * Save the current draft. Creates if new, else patches.
 * Returns the saved template on success; throws on error.
 */
async function save () {
  if (!template.value) return
  saving.value = true
  error.value = null
  try {
    let saved
    const body = { ...template.value }
    // flow_definition will be stringified server-side
    if (mode.value === 'new') {
      saved = await createFlowTemplate(body)
      templateName.value = saved.name
      mode.value = 'edit'
    } else {
      saved = await updateFlowTemplate(templateName.value, body)
    }
    template.value = { ...template.value, ...saved, flow_definition: template.value.flow_definition }
    dirty.value = false
    for (const cb of onSavedCbs.value) { try { cb(saved) } catch { /* noop */ } }
    return saved
  } catch (e) {
    error.value = e.message
    throw e
  } finally {
    saving.value = false
  }
}

/** Duplicate the current template (only valid in edit mode). */
async function duplicate (newName) {
  if (mode.value !== 'edit' || !templateName.value) return
  const dup = await duplicateFlowTemplate(templateName.value, newName)
  await openTemplate(dup.name)
  return dup
}

/** Delete the current template (only valid in edit mode + non-system). */
async function remove () {
  if (mode.value !== 'edit' || !templateName.value) return
  if (template.value?.is_system) {
    throw new Error('Impossible de supprimer un template système (utilisez "Dupliquer")')
  }
  await deleteFlowTemplate(templateName.value)
  close(true)
}

// ── Public API ──────────────────────────────────────────────────────────────

export function useFlowEditor () {
  return {
    // state (read-only refs so consumers can't accidentally mutate)
    isOpen:   readonly(isOpen),
    loading:  readonly(loading),
    saving:   readonly(saving),
    error:    readonly(error),
    dirty:    readonly(dirty),
    mode:     readonly(mode),
    templateName: readonly(templateName),
    // mutable state (only the draft content, by design)
    template,
    // actions
    openTemplate,
    openNew,
    close,
    save,
    duplicate,
    remove,
    markDirty,
  }
}

// Named default for convenience
export default useFlowEditor
