/**
 * UltiAI embed bootstrap — must run before OpenWebUI SvelteKit init.
 * Layout requires localStorage.token; without embed signin it redirects to /auth → redirect loop → 500.
 */
;(function () {
  const STORAGE_KEY = "ulti.ai.session"
  const CONTEXT_KEY = "ulti.ai.context"
  const DEFAULT_MODEL_KEY = "ulti.ai.default_model"
  const LAST_CHAT_PATH_KEY = "ulti.ai.last_chat_path"
  const SIGNIN_URL = "/ai/api/v1/auths/signin"
  const CONFIG_URL = "/api/v1/ai/config"
  const BASE_SYSTEM_PROMPT = [
    "Tu es UltiAI, l'assistant intégré à la suite Ultimail (mail, drive, contacts, agenda).",
    "Réponds en français sauf demande contraire. Utilise les tools disponibles pour agir sur les données utilisateur.",
    "Après chaque appel d'outil, réponds toujours en langage naturel : résume le résultat, cite les sources, propose la suite.",
    "Ne termine jamais un tour utilisateur avec uniquement un appel d'outil sans texte explicatif.",
    "Respecte strictement le paramètre limit des tools.",
  ].join(" ")

  function readPageUrl() {
    try {
      return new URL(window.location.href)
    } catch {
      return null
    }
  }

  function isTemporaryEmbed() {
    const url = readPageUrl()
    return url?.searchParams.get("temporary-chat") === "true"
  }

  function modelFromUrl() {
    const url = readPageUrl()
    if (!url) return ""
    const raw = url.searchParams.get("model") || url.searchParams.get("models") || ""
    return raw.split(",")[0]?.trim() || ""
  }

  function applySelectedModels(modelIds) {
    const ids = modelIds.map((id) => String(id || "").trim()).filter(Boolean)
    if (!ids.length) return
    try {
      sessionStorage.setItem("selectedModels", JSON.stringify(ids))
      localStorage.setItem(DEFAULT_MODEL_KEY, ids[0])
    } catch {
      // storage unavailable
    }
  }

  function bootstrapSelectedModels(modelHint) {
    const resolved = modelFromUrl() || String(modelHint || "").trim() || localStorage.getItem(DEFAULT_MODEL_KEY) || ""
    if (resolved) applySelectedModels([resolved])
    return resolved
  }

  function restoreLastChatIfHome() {
    if (isTemporaryEmbed()) return
    const url = readPageUrl()
    if (!url) return
    const path = url.pathname.replace(/\/$/, "") || "/"
    if (path !== "/ai") return
    if (url.searchParams.get("model") || url.searchParams.get("models")) return
    try {
      const last = localStorage.getItem(LAST_CHAT_PATH_KEY)
      if (!last || !/\/c\/[^/]+/.test(last)) return
      const target = last.startsWith("/") ? last : `/ai${last}`
      if (target === url.pathname + url.search) return
      window.location.replace(target)
    } catch {
      // ignore
    }
  }

  function watchChatRoute() {
    const save = () => {
      if (isTemporaryEmbed()) return
      try {
        const path = window.location.pathname
        if (/\/c\/[^/]+/.test(path)) {
          localStorage.setItem(LAST_CHAT_PATH_KEY, path + window.location.search)
        }
      } catch {
        // ignore
      }
    }
    window.addEventListener("popstate", save)
    const timer = window.setInterval(save, 2000)
    window.addEventListener("beforeunload", () => window.clearInterval(timer))
    save()
  }

  function ensureEmbedSignin() {
    try {
      if (localStorage.getItem("token")) return
      const xhr = new XMLHttpRequest()
      xhr.open("POST", SIGNIN_URL, false)
      xhr.withCredentials = true
      xhr.setRequestHeader("Content-Type", "application/json")
      xhr.send(JSON.stringify({ email: "", password: "" }))
      if (xhr.status !== 200) return
      const data = JSON.parse(xhr.responseText)
      if (data && data.token) {
        localStorage.setItem("token", data.token)
      }
    } catch {
      // Ultimail session not ready yet — parent may post ULTI_SESSION later
    }
  }

  async function fetchEmbedConfig() {
    try {
      const response = await fetch(CONFIG_URL, { credentials: "include" })
      if (!response.ok) return null
      return await response.json()
    } catch {
      return null
    }
  }

  async function syncUserModelPreference(modelId) {
    const model = String(modelId || "").trim()
    if (!model) return false
    const token = localStorage.getItem("token")
    if (!token) return false
    try {
      const settingsRes = await fetch("/ai/api/v1/users/user/settings", {
        headers: { Authorization: `Bearer ${token}` },
        credentials: "include",
      })
      if (!settingsRes.ok) return false
      const settings = await settingsRes.json()
      const ui = settings?.ui || {}
      const current = ui.models || ui.model_ids
      if (Array.isArray(current) && current.length > 0 && String(current[0] || "").trim()) {
        return true
      }

      const modelsRes = await fetch("/ai/api/models", {
        headers: { Authorization: `Bearer ${token}` },
        credentials: "include",
      })
      if (modelsRes.ok) {
        const modelsPayload = await modelsRes.json()
        const items = Array.isArray(modelsPayload?.data)
          ? modelsPayload.data
          : Array.isArray(modelsPayload)
            ? modelsPayload
            : []
        const known = items.some((entry) => entry && entry.id === model)
        if (!known) return false
      }

      const updateRes = await fetch("/ai/api/v1/users/user/settings/update", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
        credentials: "include",
        body: JSON.stringify({ ui: { models: [model], model_ids: [model] } }),
      })
      if (!updateRes.ok) return false
      applySelectedModels([model])
      return true
    } catch {
      return false
    }
  }

  function scheduleModelSync(modelId) {
    const model = String(modelId || "").trim()
    if (!model) return
    let attempts = 0
    const tick = async () => {
      attempts += 1
      const done = await syncUserModelPreference(model)
      if (done || attempts >= 12) return
      window.setTimeout(tick, 1000)
    }
    window.setTimeout(tick, 500)
  }

  function readContextPrompt() {
    try {
      const raw = sessionStorage.getItem(CONTEXT_KEY)
      if (!raw) return BASE_SYSTEM_PROMPT
      const parsed = JSON.parse(raw)
      const parts = [BASE_SYSTEM_PROMPT, parsed.systemPrompt].filter(Boolean)
      return parts.join("\n\n")
    } catch {
      return BASE_SYSTEM_PROMPT
    }
  }

  function injectSystemPrompt(body) {
    if (!body || !Array.isArray(body.messages)) return body
    const prompt = readContextPrompt()
    if (!prompt) return body
    const messages = body.messages.slice()
    const systemIndex = messages.findIndex((m) => m && m.role === "system")
    if (systemIndex >= 0) {
      messages[systemIndex] = { ...messages[systemIndex], content: prompt }
    } else {
      messages.unshift({ role: "system", content: prompt })
    }
    return { ...body, messages }
  }

  function patchFetch() {
    if (window.__ultiFetchPatched) return
    window.__ultiFetchPatched = true
    const originalFetch = window.fetch.bind(window)
    window.fetch = async function patchedFetch(input, init) {
      const url = typeof input === "string" ? input : input instanceof Request ? input.url : ""
      const method = (init && init.method) || (input instanceof Request ? input.method : "GET")
      if (
        method.toUpperCase() === "POST" &&
        /\/api\/(v1\/)?chat\/completions(?:\?|$)/.test(url) &&
        init &&
        typeof init.body === "string"
      ) {
        try {
          const body = JSON.parse(init.body)
          const patched = injectSystemPrompt(body)
          if (patched !== body) {
            init = { ...init, body: JSON.stringify(patched) }
          }
        } catch {
          // ignore malformed bodies
        }
      }
      return originalFetch(input, init)
    }
  }

  function brandDocument() {
    const titleEl = document.querySelector("title")
    if (titleEl) {
      const t = titleEl.textContent || ""
      if (t.includes("Open WebUI")) {
        titleEl.textContent = t.replace(/UltiAI \(Open WebUI\)/g, "UltiAI").replace(/Open WebUI/g, "UltiAI")
      } else if (!t.trim()) {
        titleEl.textContent = "UltiAI"
      }
    }
  }

  function watchDocumentTitle() {
    brandDocument()
    const titleEl = document.querySelector("title")
    if (!titleEl) return
    new MutationObserver(() => brandDocument()).observe(titleEl, {
      childList: true,
      characterData: true,
      subtree: true,
    })
  }

  restoreLastChatIfHome()
  bootstrapSelectedModels("")
  ensureEmbedSignin()
  patchFetch()
  watchDocumentTitle()
  watchChatRoute()

  void (async () => {
    const config = await fetchEmbedConfig()
    const model = bootstrapSelectedModels(config?.default_model)
    if (!localStorage.getItem("token")) ensureEmbedSignin()
    if (model) scheduleModelSync(model)
  })()

  window.addEventListener("message", (event) => {
    if (event.source !== window.parent) return
    const data = event.data
    if (!data || typeof data !== "object") return

    if (data.type === "ULTI_SESSION") {
      try {
        sessionStorage.setItem(
          STORAGE_KEY,
          JSON.stringify({
            token_secret: data.token_secret,
            session_id: data.session_id,
            mcp_url: data.mcp_url,
            enabled_tools: data.enabled_tools,
            default_model: data.default_model,
            updated_at: Date.now(),
          })
        )
      } catch {
        // sessionStorage unavailable
      }
      if (data.default_model && typeof data.default_model === "string") {
        const model = data.default_model.trim()
        if (model) {
          applySelectedModels([model])
          scheduleModelSync(model)
        }
      }
      if (!localStorage.getItem("token")) {
        ensureEmbedSignin()
      }
      return
    }

    if (data.type === "ULTI_CONTEXT_UPDATE") {
      try {
        sessionStorage.setItem(
          CONTEXT_KEY,
          JSON.stringify({
            systemPrompt: data.systemPrompt,
            context: data.context,
            updated_at: Date.now(),
          })
        )
      } catch {
        // sessionStorage unavailable
      }
    }
  })
})()
