import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios'
import { AUTH_COOKIES } from '../utils/commonVariables'
import * as Sentry from '@sentry/nextjs'
import {
    getCookie,
    getEncryptedCookie,
    hasMeta
} from '../utils/commonFunctions'
import {
    encryptWithHMAC,
    decryptWithHMAC
} from '../utils/encryptionFunctions'

interface ApiError {
    status: number
    message: string
}

// Create an Axios instance
const apiClient: AxiosInstance = axios.create({
    baseURL: process.env.NEXT_PUBLIC_API_URL,
    timeout: 10000,
    headers: {
        'Content-Type': 'application/json'
    }
})

// ✅ Flag to check if encryption is enabled
const isEncryptionEnabled =
    process.env.NEXT_PUBLIC_API_ENCRYPTION_ENABLED === 'true'

//Request interceptor
apiClient.interceptors.request.use(
    (config) => {

        if (config.data && !(config.data instanceof FormData)) {
            if (isEncryptionEnabled) {
                const encryptedData = encryptWithHMAC(config.data)
                config.data = encryptedData
            }
        }

        // 🗂️ For FormData, let browser handle Content-Type with boundary
        if (config.data instanceof FormData) {
            delete config.headers['Content-Type']
        }

        // const authToken = getCookie(AUTH_COOKIES.USER_TOKEN)
        const authToken = getEncryptedCookie(AUTH_COOKIES.USER_TOKEN)
        if (authToken) {
            config.headers['Authorization'] = `Bearer ${authToken}`
        }
        config.headers['usertype'] = 'guest'

        // 🗂️ For FormData, let browser handle Content-Type with proper boundary
        if (config.data instanceof FormData) {
            delete config.headers['Content-Type']
        }
        return config
    },
    (error) => {
        /**
         * Sentry capture: Request-level error (e.g., config or interceptor failure)
         */
        Sentry.captureException(error) // Capture request errors
        return Promise.reject(error)
    }
)

// Response interceptor
apiClient.interceptors.response.use(
    <T>(response: AxiosResponse<T>) => {
        const { data, config, ...rest } = response

        // 🔓 Decrypt response if encryption enabled
        const decryptedData = isEncryptionEnabled ? decryptWithHMAC(data) : data

        // 🛠 Parse request payload (decrypt if encryption enabled)
        // ✅ Skip parsing if data is FormData
        let requestData = config?.data
        
        if (!(config?.data instanceof FormData)) {
            const rawConfigData = JSON.parse(config?.data ?? '{}')
            requestData =
                isEncryptionEnabled && Object.keys(rawConfigData).length
                    ? decryptWithHMAC(rawConfigData)
                    : rawConfigData
        }

        /**
         * Sentry capture: Log successful responses with API-level error (e.g., `status === 0`)
         * These are *logical* failures indicated by the API, not HTTP failures.
         */
        if (hasMeta(decryptedData) && decryptedData.meta.status === 0) {
            Sentry.captureException(response, {
                tags: {
                    api_url: config?.url || 'unknown'
                },
                extra: {
                    requestData: requestData instanceof FormData ? 'FormData' : requestData,
                    responseData: decryptedData
                }
            })
        }

        return {
            ...rest,
            config: { ...config, data: requestData },
            data: decryptedData
        }
    },
    (error: AxiosError<ApiError>) => {
        const { config, response, request } = error

        // 🛠 Parse request payload
        // ✅ Skip parsing if data is FormData
        let requestData = config?.data
        
        if (!(config?.data instanceof FormData)) {
            const rawConfigData = JSON.parse(config?.data ?? '{}')
            requestData =
                isEncryptionEnabled && Object.keys(rawConfigData).length
                    ? decryptWithHMAC(rawConfigData)
                    : rawConfigData
        }

        // 🔓 Decrypt response payload if encryption enabled
        const responseData =
            isEncryptionEnabled && response?.data
                ? decryptWithHMAC(response.data)
                : response?.data


        if (response) {
            /**
             * Sentry capture: API responded with an error (HTTP status >= 400)
             */
            Sentry.captureException(error, {
                tags: {
                    status_code: response.status.toString(),
                    api_url: config?.url || 'unknown'
                },
                extra: {
                    requestData: requestData instanceof FormData ? 'FormData' : requestData,
                    responseData
                }
            })
            // Handle HTTP errors based on status code
            switch (response.status) {
                case 400:
                    console.log('Bad Request:', responseData?.message)
                    break
                case 401:
                    console.log('Unauthorized - Redirecting to login')
                    // deleteCookie(AUTH_COOKIES.USER_TOKEN)
                    // window.location.href = `${import.meta.env.NEXT_PUBLIC_API_URL}login`; // Redirect user
                    break
                case 403:
                    console.log('Forbidden:', responseData?.message)
                    break
                case 404:
                    console.log('Not Found:', responseData?.message)
                    break
                case 500:
                    console.log('Internal Server Error:', responseData?.message)
                    break
                default:
                    console.log('Something went wrong:', responseData?.message)
            }
        } else if (request) {
            /**
             * Sentry capture: Request was made but no response was received
             * Typically network errors, timeouts, or server down
             */
            Sentry.captureException(error, {
                tags: {
                    api_url: config?.url || 'unknown'
                },
                extra: {
                    requestData: requestData instanceof FormData ? 'FormData' : requestData
                }
            })
            console.log('Network Error: No response from server')
        } else {
            /**
             * Sentry capture: Something else went wrong during request setup
             */
            Sentry.captureException(error, {
                tags: {
                    api_url: config?.url || 'unknown'
                },
                extra: {
                    requestData: requestData instanceof FormData ? 'FormData' : requestData
                }
            })
            console.log('Error:', error.message)
        }

        // ❌ Reject with decrypted response data if available
        return Promise.reject(responseData || error)
    }
)

export default apiClient