import { defineStore } from 'pinia'
import { ref } from 'vue'
import { apiFetch } from '@/lib/tauri'
import { useWindowsStore } from './windows'
import {
  getScriptLog,
  clearScriptLog,
  getWindowDefinitions,
  clearWindowDefinitions,
  type WindowDefinitionEntry
} from '../services/tools/handlers/canvasHandlers'

const API_URL = ''

// ============================================
// TYPES
// ============================================

export interface SnapshotWindow {
  id: string
  title: string
  x: number
  y: number
  width: number
  height: number
  zIndex: number
  source: 'db' | 'inline'
  componentId?: string
  definition?: {
    id: string
    name: string
    template: string
    setup?: string
    style?: string
    imports?: string[]
    props?: string[]
  }
  componentProps: Record<string, any>
}

export interface SnapshotCSSBlock {
  id: string
  css: string
}

export interface CanvasSnapshot {
  id: string
  name: string
  created: number
  baseHTML: string | null
  baseScripts: string[]
  cssBlocks: SnapshotCSSBlock[]
  windows: SnapshotWindow[]
}

export interface SnapshotSummary {
  id: string
  name: string
  thumbnail: string | null
  created_at: number
}

// ============================================
// STORE
// ============================================

export const useSnapshotsStore = defineStore('snapshots', () => {
  const snapshots = ref<SnapshotSummary[]>([])

  // ---- Capture current canvas state ----
  function captureState(name: string): CanvasSnapshot {
    const windowsStore = useWindowsStore()
    const winDefs = getWindowDefinitions()

    // 1. Capture base HTML (excluding floating window containers)
    const container = document.getElementById('canvas-content')
    let baseHTML: string | null = null
    if (container) {
      const clone = container.cloneNode(true) as HTMLElement
      // Remove dynamic component wrappers (floating windows)
      clone.querySelectorAll('.dynamic-component-wrapper').forEach(el => el.remove())
      const html = clone.innerHTML.trim()
      baseHTML = html || null
    }

    // 2. Capture scripts
    const baseScripts = getScriptLog()

    // 3. Capture CSS blocks
    const cssBlocks: SnapshotCSSBlock[] = []
    document.querySelectorAll('style[id^="canvas-css-"]').forEach(style => {
      const id = style.id.replace('canvas-css-', '')
      cssBlocks.push({ id, css: style.textContent || '' })
    })

    // 4. Capture windows with definitions
    const windows: SnapshotWindow[] = []
    for (const win of windowsStore.windowsList) {
      const entry: WindowDefinitionEntry | undefined = winDefs.get(win.id)
      const snapWin: SnapshotWindow = {
        id: win.id,
        title: win.title,
        x: win.x,
        y: win.y,
        width: win.width,
        height: win.height,
        zIndex: win.zIndex,
        source: entry?.source || 'inline',
        componentProps: entry?.componentProps || {}
      }

      if (entry?.source === 'db' && entry.componentId) {
        snapWin.componentId = entry.componentId
      }

      if (entry?.definition) {
        snapWin.definition = {
          id: entry.definition.id,
          name: entry.definition.name,
          template: entry.definition.template,
          setup: entry.definition.setup,
          style: entry.definition.style,
          imports: entry.definition.imports,
          props: entry.definition.props
        }
      }

      windows.push(snapWin)
    }

    return {
      id: `snap-${Date.now()}`,
      name,
      created: Date.now(),
      baseHTML,
      baseScripts,
      cssBlocks,
      windows
    }
  }

  // ---- Save snapshot to backend ----
  async function save(name: string): Promise<string> {
    const snapshot = captureState(name)

    const res = await apiFetch(`${API_URL}/api/snapshots`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        id: snapshot.id,
        name: snapshot.name,
        data: snapshot,
        created_at: snapshot.created
      })
    })
    const result = await res.json()
    await list() // refresh list
    return result.id
  }

  // ---- List snapshots ----
  async function list(): Promise<SnapshotSummary[]> {
    const res = await apiFetch(`${API_URL}/api/snapshots`)
    const data = await res.json()
    snapshots.value = data
    return data
  }

  // ---- Load full snapshot ----
  async function load(id: string): Promise<CanvasSnapshot> {
    const res = await apiFetch(`${API_URL}/api/snapshots/${id}`)
    const row = await res.json()
    return row.data
  }

  // ---- Remove snapshot ----
  async function remove(id: string): Promise<void> {
    await apiFetch(`${API_URL}/api/snapshots/${id}`, { method: 'DELETE' })
    await list()
  }

  // ---- Restore a snapshot ----
  async function restore(id: string): Promise<void> {
    const snapshot = await load(id)
    const windowsStore = useWindowsStore()

    // 1. Close all current windows
    for (const win of windowsStore.windowsList) {
      const container = document.getElementById(`inline-${win.id}`)
      if (container) container.remove()
      document.getElementById(`style-${win.id}`)?.remove()
    }
    windowsStore.clear()
    clearWindowDefinitions()
    clearScriptLog()

    // 2. Remove existing canvas CSS
    document.querySelectorAll('style[id^="canvas-css-"]').forEach(el => el.remove())

    // 3. Restore base HTML
    const canvasEl = document.getElementById('canvas-content')
    if (canvasEl) {
      if (snapshot.baseHTML) {
        canvasEl.innerHTML = snapshot.baseHTML
        // Execute inline scripts
        canvasEl.querySelectorAll('script').forEach(oldScript => {
          const newScript = document.createElement('script')
          Array.from(oldScript.attributes).forEach(attr => {
            newScript.setAttribute(attr.name, attr.value)
          })
          newScript.textContent = oldScript.textContent
          oldScript.parentNode?.replaceChild(newScript, oldScript)
        })
      } else {
        canvasEl.innerHTML = ''
      }
    }

    // 4. Restore CSS blocks
    for (const block of snapshot.cssBlocks) {
      const styleEl = document.createElement('style')
      styleEl.id = `canvas-css-${block.id}`
      document.head.appendChild(styleEl)
      styleEl.textContent = block.css
    }

    // 5. Re-execute scripts
    if (canvasEl && snapshot.baseScripts.length > 0) {
      for (const code of snapshot.baseScripts) {
        try {
          const context = {
            canvas: canvasEl,
            windows: windowsStore.windowsList,
            getWindow: (wid: string) => document.querySelector(`[data-window-id="${wid}"]`),
            $: (selector: string) => canvasEl.querySelector(selector),
            $$: (selector: string) => canvasEl.querySelectorAll(selector)
          }
          const fn = new Function('ctx', `with(ctx) { ${code} }`)
          fn(context)
        } catch (e) {
          console.warn('[Snapshot] Script replay error:', e)
        }
      }
    }

    // 6. Restore windows — dynamically import to avoid circular deps
    const { renderInlineComponent } = await import('../services/dynamicComponents')
    if (canvasEl) {
      for (const win of snapshot.windows) {
        if (!win.definition) continue

        const definition = {
          id: win.id,
          name: win.definition.name,
          template: win.definition.template,
          setup: win.definition.setup,
          style: win.definition.style,
          props: win.definition.props,
          imports: win.definition.imports || ['ref', 'reactive', 'computed']
        }

        const layout = { x: win.x, y: win.y, width: win.width, height: win.height }
        renderInlineComponent(definition, canvasEl, win.componentProps || {}, true, layout)

        // Re-track definition
        getWindowDefinitions().set(win.id, {
          source: win.source,
          componentId: win.componentId,
          definition,
          componentProps: win.componentProps || {}
        })
      }
    }
  }

  return {
    snapshots,
    captureState,
    save,
    list,
    load,
    remove,
    restore
  }
})
