/**
 * Metabase API utility
 *
 * Handles authentication and requests to Metabase API
 */

const config = useRuntimeConfig()
const METABASE_URL = config.metabaseUrl || 'http://metabase:3000'
const METABASE_API_KEY = config.metabaseApiKey || ''
const METABASE_EMAIL = config.metabaseEmail || 'claudeCode0@nucleoriofrio.com'
const METABASE_PASSWORD = config.metabasePassword || 'vK^NyZdZDH#p'

let sessionToken: string | null = null
let tokenExpiry: number = 0

/**
 * Get a valid Metabase session token
 * Reuses existing token if still valid, otherwise requests a new one
 */
export async function getMetabaseToken(): Promise<string> {
  // Check if we have a valid token
  if (sessionToken && Date.now() < tokenExpiry) {
    return sessionToken
  }

  // Request a new token
  try {
    const response = await $fetch<{ id: string }>(`${METABASE_URL}/api/session`, {
      method: 'POST',
      body: {
        username: METABASE_EMAIL,
        password: METABASE_PASSWORD
      }
    })

    sessionToken = response.id

    // Tokens expire after 14 days by default, but we'll refresh after 13 days to be safe
    tokenExpiry = Date.now() + (13 * 24 * 60 * 60 * 1000)

    console.log('[Metabase] New session token obtained')
    return sessionToken
  } catch (error) {
    console.error('[Metabase] Failed to obtain session token:', error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to authenticate with Metabase'
    })
  }
}

/**
 * Make an authenticated request to Metabase API
 * Supports both API Key and Session Token authentication
 */
export async function metabaseFetch<T = any>(
  endpoint: string,
  options: RequestInit = {}
): Promise<T> {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...options.headers as Record<string, string>
  }

  // Prefer API Key if available
  if (METABASE_API_KEY) {
    headers['X-API-KEY'] = METABASE_API_KEY
  } else {
    const token = await getMetabaseToken()
    headers['X-Metabase-Session'] = token
  }

  try {
    const response = await $fetch<T>(`${METABASE_URL}${endpoint}`, {
      ...options,
      headers
    })

    return response
  } catch (error: any) {
    console.error(`[Metabase] Request failed for ${endpoint}:`, error)

    // If using session token and it's invalid, clear it and retry once
    if (error.statusCode === 401 && !METABASE_API_KEY) {
      console.log('[Metabase] Token invalid, clearing and retrying...')
      sessionToken = null
      tokenExpiry = 0

      // Retry once with fresh token
      const newToken = await getMetabaseToken()
      return await $fetch<T>(`${METABASE_URL}${endpoint}`, {
        ...options,
        headers: {
          ...options.headers,
          'X-Metabase-Session': newToken,
          'Content-Type': 'application/json'
        }
      })
    }

    throw createError({
      statusCode: error.statusCode || 500,
      statusMessage: error.message || 'Metabase request failed'
    })
  }
}

/**
 * Get database metadata
 */
export async function getMetabaseDatabases() {
  return metabaseFetch('/api/database')
}

/**
 * Get tables from a specific database
 */
export async function getMetabaseTables(databaseId: number) {
  return metabaseFetch(`/api/database/${databaseId}/metadata`)
}

/**
 * Execute a query against a table
 */
export async function queryMetabaseTable(databaseId: number, tableId: number, query: any = {}) {
  return metabaseFetch('/api/dataset', {
    method: 'POST',
    body: {
      database: databaseId,
      type: 'query',
      query: {
        'source-table': tableId,
        ...query
      }
    }
  })
}

/**
 * Get all cards/questions
 */
export async function getMetabaseCards(filter?: string) {
  const endpoint = filter ? `/api/card?f=${filter}` : '/api/card'
  return metabaseFetch(endpoint)
}

/**
 * Get a specific card by ID
 */
export async function getMetabaseCard(cardId: number) {
  return metabaseFetch(`/api/card/${cardId}`)
}

/**
 * Execute a card query with optional parameters
 */
export async function executeCardQuery(cardId: number, parameters?: any[]) {
  const body = parameters ? { parameters } : {}
  return metabaseFetch(`/api/card/${cardId}/query`, {
    method: 'POST',
    body
  })
}

/**
 * Execute a card query with cache (GET)
 */
export async function executeCardQueryCached(cardId: number) {
  return metabaseFetch(`/api/card/${cardId}/query`)
}
