import { SCHEMA_VERSION } from '../db/schema.js'
import { useSaveFilePrompt } from '../composables/useSaveFilePrompt.js'

/**
 * Builds a JSON export envelope wrapping entity data.
 * @param {object} data — e.g. { exercises: [...] }
 * @param {{ name: string, uuid: string }} exportedBy — current user info
 * @returns {object} The complete envelope
 */
export function buildEnvelope(data, exportedBy) {
  return {
    metadata: {
      appName: __APP_NAME__,
      appVersion: __APP_VERSION__,
      schemaVersion: SCHEMA_VERSION,
      exportDate: new Date().toISOString(),
      exportedBy: {
        name: exportedBy.name,
        uuid: exportedBy.uuid,
      },
    },
    data,
  }
}

/**
 * Parses and validates a JSON envelope string.
 * Returns { valid, envelope, error } where error is an i18n key.
 */
export function parseEnvelope(jsonString) {
  let parsed
  try {
    parsed = JSON.parse(jsonString)
  } catch {
    return { valid: false, envelope: null, error: 'import.errors.invalidJson' }
  }

  if (!parsed || typeof parsed !== 'object') {
    return { valid: false, envelope: null, error: 'import.errors.invalidFormat' }
  }

  const { metadata, data } = parsed

  if (!metadata || typeof metadata !== 'object') {
    return { valid: false, envelope: null, error: 'import.errors.missingMetadata' }
  }

  if (metadata.appName !== __APP_NAME__) {
    return { valid: false, envelope: null, error: 'import.errors.wrongApp' }
  }

  if (typeof metadata.schemaVersion !== 'number') {
    return { valid: false, envelope: null, error: 'import.errors.missingSchema' }
  }

  if (metadata.schemaVersion > SCHEMA_VERSION) {
    return { valid: false, envelope: null, error: 'import.errors.newerSchema' }
  }

  if (!data || typeof data !== 'object') {
    return { valid: false, envelope: null, error: 'import.errors.missingData' }
  }

  if (!metadata.exportedBy || !metadata.exportedBy.uuid || !metadata.exportedBy.name) {
    return { valid: false, envelope: null, error: 'import.errors.missingExporter' }
  }

  return { valid: true, envelope: parsed, error: null }
}

/**
 * Prompts for a filename (prefilled with `defaultFilename`), then triggers a
 * browser file download. No-op if the user cancels.
 * @param {string} defaultFilename
 * @param {string} jsonString
 */
export async function downloadJson(defaultFilename, jsonString) {
  const { promptFilename } = useSaveFilePrompt()
  const filename = await promptFilename(defaultFilename)
  if (!filename) return

  const blob = new Blob([jsonString], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.click()
  URL.revokeObjectURL(url)
}

/**
 * Opens a file picker and returns file contents as string.
 * Returns null if user cancels.
 */
export function pickJsonFile() {
  return new Promise((resolve) => {
    const input = document.createElement('input')
    input.type = 'file'
    input.accept = '.json'
    input.onchange = async (e) => {
      const file = e.target.files[0]
      if (!file) {
        resolve(null)
        return
      }
      const text = await file.text()
      resolve(text)
    }
    // Handle cancel (focus returns without change)
    input.addEventListener('cancel', () => resolve(null))
    input.click()
  })
}
