import { getAccessToken, clearTokens, setTokens } from '../lib/api'
import { getActiveBusinessId } from '../lib/businessContext'
import { API_BASE_URL } from '../lib/config'
import { ensureJpegUploadFile, ensureUploadFile } from '../utils/imageUpload'

export interface MediaItem {
  id: string
  publicUrl: string
  fileName: string
  originalFileName: string
  mimeType: string
  width: number | null
  height: number | null
}

function isDataUrl(value: string) {
  return value.startsWith('data:')
}

function businessPath(suffix = '') {
  const businessId = getActiveBusinessId()
  if (!businessId) {
    throw new Error('No active business selected. Please sign in again.')
  }
  return `/businesses/${businessId}/media${suffix}`
}

async function refreshAccessToken() {
  const refreshToken = localStorage.getItem('meshkee_business_refresh_token')
  if (!refreshToken) return false

  const response = await fetch(`${API_BASE_URL}/auth/refresh`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refreshToken }),
  })

  if (!response.ok) {
    clearTokens()
    return false
  }

  const data = await response.json()
  setTokens(data.accessToken, data.refreshToken)
  return true
}

function parseUploadError(payload: unknown, status: number) {
  if (payload && typeof payload === 'object') {
    const message = (payload as { message?: string | string[] }).message
    if (Array.isArray(message)) {
      return message.join(', ')
    }
    if (typeof message === 'string' && message) {
      return message
    }
  }

  return `Upload failed with status ${status}`
}

export async function uploadMediaFiles(
  files: File[],
  signal?: AbortSignal,
): Promise<MediaItem[]> {
  if (!files.length) return []

  const send = async () => {
    const formData = new FormData()
    files.forEach((file) => formData.append('files', file))

    const headers = new Headers()
    const accessToken = getAccessToken()
    if (accessToken) {
      headers.set('Authorization', `Bearer ${accessToken}`)
    }

    return fetch(`${API_BASE_URL}${businessPath()}`, {
      method: 'POST',
      headers,
      body: formData,
      signal,
    })
  }

  let response = await send()

  if (response.status === 401) {
    const refreshed = await refreshAccessToken()
    if (refreshed) {
      response = await send()
    }
  }

  const payload = await response.json().catch(() => null)
  if (!response.ok) {
    throw new Error(parseUploadError(payload, response.status))
  }

  return (payload.items as Array<Record<string, unknown>>).map((item) => ({
    id: String(item.id),
    publicUrl: String(item.publicUrl),
    fileName: String(item.fileName),
    originalFileName: String(item.originalFileName),
    mimeType: String(item.mimeType),
    width: typeof item.width === 'number' ? item.width : null,
    height: typeof item.height === 'number' ? item.height : null,
  }))
}

export async function resolveDataUrlToMediaId(
  value: string | null,
  filename: string,
  existingMediaId?: string | null,
): Promise<string | null> {
  if (!value) return null
  if (!isDataUrl(value)) {
    return existingMediaId ?? null
  }

  const file = filename.toLowerCase().endsWith('.png')
    ? await ensureUploadFile(value, filename)
    : await ensureJpegUploadFile(value, filename)
  const uploaded = await uploadMediaFiles([file])
  return uploaded[0]?.id ?? null
}

export async function resolveHtmlEmbeddedDataUrls(html: string): Promise<string> {
  if (!html.includes('data:')) return html

  const parser = new DOMParser()
  const doc = parser.parseFromString(html, 'text/html')
  const images = Array.from(doc.querySelectorAll('img'))

  for (let index = 0; index < images.length; index += 1) {
    const src = images[index].getAttribute('src')
    if (!src || !isDataUrl(src)) continue

    const file = await ensureJpegUploadFile(src, `inline-image-${index + 1}.jpg`)
    const uploaded = await uploadMediaFiles([file])
    if (uploaded[0]) {
      images[index].setAttribute('src', uploaded[0].publicUrl)
    }
  }

  return doc.body.innerHTML
}

export async function resolveDataUrlsToMediaIds(
  values: string[],
  existingMediaIds: string[],
): Promise<string[]> {
  const resolved: string[] = []

  for (let index = 0; index < values.length; index += 1) {
    const value = values[index]
    if (isDataUrl(value)) {
      const file = await ensureJpegUploadFile(value, `product-image-${index + 1}.jpg`)
      const uploaded = await uploadMediaFiles([file])
      if (uploaded[0]) resolved.push(uploaded[0].id)
    } else if (existingMediaIds[index]) {
      resolved.push(existingMediaIds[index])
    }
  }

  return resolved
}
