import axios from 'axios'
import { Env } from '../lib/env'
import { Logger } from '../lib/logger'
import {
  normalizeMidtransStatus,
  type MidtransStatusResponse,
  type PaymentStatusResponse,
} from '../features/payments/lib/midtrans'

// Normalize base URL to ensure a single "/api" segment and no trailing slash
function computeApiBase(): string | undefined {
  const raw = (Env.API_BASE_URL || '').trim()
  const normalized = raw.replace(/\/+$/g, '')
  let base = normalized ? (/\/api$/i.test(normalized) ? normalized : `${normalized}/api`) : undefined
  if (!base) {
    // Dev fallback: if running locally and backend on default port 8000, use it
    try {
      const { hostname } = window.location
      const isLocal = hostname === 'localhost' || hostname === '127.0.0.1'
      if (isLocal) {
        base = 'http://localhost:8000/api'
        Logger.warn('api.base.fallback', { base })
      }
    } catch {
      // noop: window not available
    }
  }
  return base
}

const apiBase = computeApiBase()

export const api = axios.create({ baseURL: apiBase })

// Axios interceptors for logging
api.interceptors.request.use((config) => {
  const method = (config.method || 'GET').toUpperCase()
  const url = `${config.baseURL || ''}${config.url || ''}`
  Logger.info('api.request', { method, url })
  if (Env.LOG_LEVEL === 'debug') Logger.debug('api.request.data', Logger.mask(config.data))
  return config
})

api.interceptors.response.use(
  (response) => {
    const url = response.config?.url || ''
    Logger.info('api.response', { url, status: response.status })
    if (Env.LOG_LEVEL === 'debug') Logger.debug('api.response.data', response.data)
    return response
  },
  (error) => {
    const baseURL = error.config?.baseURL || ''
    const url = error.config?.url || ''
    const status = error.response?.status
    const fullUrl = `${baseURL}${url}`
    Logger.error('api.error', { baseURL, url, fullUrl, status, message: error.message })
    throw error
  }
)

export async function getPaymentStatus(orderId: string): Promise<PaymentStatusResponse> {
  if (apiBase) {
    const { data } = await api.get(`/payments/${orderId}/status`)
    // If backend returns Midtrans status response (pass-through), normalize it.
    if (data && typeof data === 'object' && 'transaction_status' in data) {
      const normalized = normalizeMidtransStatus(data as MidtransStatusResponse)
      if (normalized.orderId && normalized.orderId !== orderId) {
        Logger.error('status.mismatch', { requested: orderId, returned: normalized.orderId })
        return { orderId, status: normalized.status || 'pending' }
      }
      return normalized
    }
    // Otherwise, assume backend already returns app-level shape.
    const app = data as PaymentStatusResponse
    if (app.orderId && app.orderId !== orderId) {
      Logger.error('status.mismatch', { requested: orderId, returned: app.orderId })
      return { orderId, status: app.status || 'pending' }
    }
    return app
  }
  // Fallback stub when API base not set
  return { orderId, status: 'pending' }
}

export async function postCharge(payload: Record<string, any>): Promise<any> {
  if (!apiBase) throw new Error('API base URL not configured (set VITE_API_BASE_URL or use local fallback)')
  Logger.info('charge.start', { payment_type: payload?.payment_type })
  if (Env.LOG_LEVEL === 'debug') Logger.debug('charge.payload', Logger.mask(payload))
  const { data } = await api.post('/payments/charge', payload)
  Logger.info('charge.done', { order_id: data?.order_id, status_code: data?.status_code })
  return data
}

export type RuntimeConfigResponse = {
  paymentToggles: {
    bank_transfer: boolean
    credit_card: boolean
    gopay: boolean
    cstore: boolean
    cpay?: boolean
  }
  midtransEnv?: 'production' | 'sandbox'
  clientKey?: string
}

export async function getRuntimeConfig(): Promise<RuntimeConfigResponse> {
  if (apiBase) {
    const { data } = await api.get('/config')
    Logger.info('config.runtime.loaded')
    if (Env.LOG_LEVEL === 'debug') Logger.debug('config.runtime.data', data)
    return data as RuntimeConfigResponse
  }
  // Fallback when API base not set: use build-time Env toggles
  Logger.warn('config.runtime.fallback', { reason: 'API base not set' })
  return {
    paymentToggles: {
      bank_transfer: Env.ENABLE_BANK_TRANSFER,
      credit_card: Env.ENABLE_CREDIT_CARD,
      gopay: Env.ENABLE_GOPAY,
      cstore: Env.ENABLE_CSTORE,
      cpay: Env.ENABLE_CPAY,
    },
    midtransEnv: Env.MIDTRANS_ENV,
    clientKey: Env.MIDTRANS_CLIENT_KEY,
  }
}

export type PaymentLinkPayload = {
  order_id: string
  nominal: number
  customer?: { name?: string; phone?: string; email?: string }
  expire_at?: number
  allowed_methods?: string[]
}

export async function getPaymentLinkPayload(token: string): Promise<PaymentLinkPayload> {
  if (apiBase) {
    const { data } = await api.get(`/payment-links/${encodeURIComponent(token)}`)
    Logger.info('paymentlink.resolve', { tokenLen: token.length })
    return data as PaymentLinkPayload
  }
  try {
    const json = JSON.parse(atob(token))
    return {
      order_id: json.order_id || token,
      nominal: Number(json.nominal) || 150000,
      customer: json.customer || {},
      expire_at: json.expire_at || Date.now() + 24 * 60 * 60 * 1000
,
      allowed_methods: json.allowed_methods || undefined,
    }
  } catch {
    return {
      order_id: token,
      nominal: 150000,
      expire_at: Date.now() + 24 * 60 * 60 * 1000
,
    }
  }
}