/**
 * API Service
 *
 * Axios-based API client for the ERP backend
 */

import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios';
import * as SecureStore from 'expo-secure-store';
import { ApiResponse, ApiError } from '@/types';

// API Configuration
const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'http://localhost:4000/api/v1';
const STORAGE_KEY_TOKEN = 'auth_token';
const STORAGE_KEY_REFRESH = 'refresh_token';
const STORAGE_KEY_TENANT = 'tenant_id';

// Create axios instance
const api: AxiosInstance = axios.create({
  baseURL: API_BASE_URL,
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json',
  },
});

// Request interceptor - add auth token
api.interceptors.request.use(
  async (config: InternalAxiosRequestConfig) => {
    try {
      const token = await SecureStore.getItemAsync(STORAGE_KEY_TOKEN);
      const tenantId = await SecureStore.getItemAsync(STORAGE_KEY_TENANT);

      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      if (tenantId) {
        config.headers['X-Tenant-ID'] = tenantId;
      }
    } catch (error) {
      console.warn('Error reading auth token:', error);
    }

    return config;
  },
  (error) => Promise.reject(error)
);

// Response interceptor - handle errors and token refresh
api.interceptors.response.use(
  (response) => response,
  async (error: AxiosError<ApiError>) => {
    const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };

    // Handle 401 - try to refresh token
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;

      try {
        const refreshToken = await SecureStore.getItemAsync(STORAGE_KEY_REFRESH);

        if (refreshToken) {
          const response = await axios.post(`${API_BASE_URL}/auth/refresh`, {
            refreshToken,
          });

          const { token, refreshToken: newRefreshToken } = response.data;

          await SecureStore.setItemAsync(STORAGE_KEY_TOKEN, token);
          await SecureStore.setItemAsync(STORAGE_KEY_REFRESH, newRefreshToken);

          originalRequest.headers.Authorization = `Bearer ${token}`;
          return api(originalRequest);
        }
      } catch (refreshError) {
        // Refresh failed - clear tokens
        await SecureStore.deleteItemAsync(STORAGE_KEY_TOKEN);
        await SecureStore.deleteItemAsync(STORAGE_KEY_REFRESH);
        await SecureStore.deleteItemAsync(STORAGE_KEY_TENANT);
      }
    }

    // Transform error to consistent format
    const apiError: ApiError = {
      message: error.response?.data?.message || error.message || 'An error occurred',
      code: error.response?.data?.code,
      statusCode: error.response?.status || 500,
      errors: error.response?.data?.errors,
    };

    return Promise.reject(apiError);
  }
);

// Auth API
export const authApi = {
  login: async (email: string, password: string, tenantId?: string) => {
    const response = await api.post('/auth/login', { email, password, tenantId });
    return response.data;
  },

  logout: async () => {
    try {
      await api.post('/auth/logout');
    } finally {
      await SecureStore.deleteItemAsync(STORAGE_KEY_TOKEN);
      await SecureStore.deleteItemAsync(STORAGE_KEY_REFRESH);
      await SecureStore.deleteItemAsync(STORAGE_KEY_TENANT);
    }
  },

  getProfile: async () => {
    const response = await api.get('/auth/profile');
    return response.data;
  },

  refreshToken: async (refreshToken: string) => {
    const response = await api.post('/auth/refresh', { refreshToken });
    return response.data;
  },
};

// Partners API
export const partnersApi = {
  list: async (params?: { page?: number; limit?: number; search?: string; isCustomer?: boolean; isSupplier?: boolean }) => {
    const response = await api.get('/partners', { params });
    return response.data;
  },

  getById: async (id: string) => {
    const response = await api.get(`/partners/${id}`);
    return response.data;
  },

  create: async (data: Partial<any>) => {
    const response = await api.post('/partners', data);
    return response.data;
  },

  update: async (id: string, data: Partial<any>) => {
    const response = await api.put(`/partners/${id}`, data);
    return response.data;
  },

  delete: async (id: string) => {
    const response = await api.delete(`/partners/${id}`);
    return response.data;
  },
};

// Products API
export const productsApi = {
  list: async (params?: { page?: number; limit?: number; search?: string; isActive?: boolean }) => {
    const response = await api.get('/inventory/products', { params });
    return response.data;
  },

  getById: async (id: string) => {
    const response = await api.get(`/inventory/products/${id}`);
    return response.data;
  },
};

// Invoices API
export const invoicesApi = {
  list: async (params?: { page?: number; limit?: number; state?: string; invoiceType?: string }) => {
    const response = await api.get('/financial/invoices', { params });
    return response.data;
  },

  getById: async (id: string) => {
    const response = await api.get(`/financial/invoices/${id}`);
    return response.data;
  },
};

// Storage helpers
export const storage = {
  setToken: (token: string) => SecureStore.setItemAsync(STORAGE_KEY_TOKEN, token),
  getToken: () => SecureStore.getItemAsync(STORAGE_KEY_TOKEN),
  setRefreshToken: (token: string) => SecureStore.setItemAsync(STORAGE_KEY_REFRESH, token),
  getRefreshToken: () => SecureStore.getItemAsync(STORAGE_KEY_REFRESH),
  setTenantId: (id: string) => SecureStore.setItemAsync(STORAGE_KEY_TENANT, id),
  getTenantId: () => SecureStore.getItemAsync(STORAGE_KEY_TENANT),
  clearAll: async () => {
    await SecureStore.deleteItemAsync(STORAGE_KEY_TOKEN);
    await SecureStore.deleteItemAsync(STORAGE_KEY_REFRESH);
    await SecureStore.deleteItemAsync(STORAGE_KEY_TENANT);
  },
};

export default api;
