import axios, { AxiosResponse, AxiosError } from 'axios'
import toast from 'react-hot-toast'
import type {
  SystemInfo,
  SystemStatus,
  Recipe,
  RecipeCreate,
  RecipeUpdate,
  RecipeList,
  ProcessStatus,
  ProcessStartRequest,
  ProcessActionResponse,
  HardwareStatus,
  SafetyStatus,
  User,
  UserCreate,
  UserUpdate,
  ApiResponse,
  ApiError,
} from '../types'

// Create axios instance with default configuration
const apiClient = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000',
  timeout: 30000, // 30 seconds timeout for industrial environment
  headers: {
    'Content-Type': 'application/json',
  },
})

// Request interceptor to add auth token if available
apiClient.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('auth_token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// Response interceptor for error handling
apiClient.interceptors.response.use(
  (response: AxiosResponse) => {
    return response
  },
  (error: AxiosError) => {
    const apiError: ApiError = {
      message: 'An error occurred',
      status: error.response?.status,
    }

    if (error.response?.data && typeof error.response.data === 'object') {
      const errorData = error.response.data as any
      apiError.message = errorData.message || errorData.detail || apiError.message
      apiError.code = errorData.code
    } else if (error.message) {
      apiError.message = error.message
    }

    // Handle specific error codes
    if (error.response?.status === 401) {
      // Unauthorized - redirect to login
      localStorage.removeItem('auth_token')
      window.location.href = '/login'
      return Promise.reject(apiError)
    }

    if (error.response?.status === 503) {
      // Service unavailable
      toast.error('System temporarily unavailable. Please try again.')
    } else if (error.response?.status >= 500) {
      // Server errors
      toast.error('Server error occurred. Please contact support.')
    }

    return Promise.reject(apiError)
  }
)

// Helper function to handle API responses
const handleResponse = <T>(response: AxiosResponse<T>): T => {
  return response.data
}

// API service class
class ApiService {
  // System endpoints
  async getSystemInfo(): Promise<SystemInfo> {
    const response = await apiClient.get('/api/v1/info')
    return handleResponse(response)
  }

  async getSystemStatus(): Promise<SystemStatus> {
    const response = await apiClient.get('/api/v1/system/status')
    return handleResponse(response)
  }

  async getHealthCheck(): Promise<{ status: string }> {
    const response = await apiClient.get('/health')
    return handleResponse(response)
  }

  // Recipe endpoints
  async getRecipes(params?: {
    skip?: number
    limit?: number
    active_only?: boolean
    search?: string
  }): Promise<RecipeList> {
    const response = await apiClient.get('/api/v1/recipes', { params })
    return handleResponse(response)
  }

  async getRecipe(id: number): Promise<Recipe> {
    const response = await apiClient.get(`/api/v1/recipes/${id}`)
    return handleResponse(response)
  }

  async createRecipe(recipe: RecipeCreate): Promise<Recipe> {
    const response = await apiClient.post('/api/v1/recipes', recipe)
    return handleResponse(response)
  }

  async updateRecipe(id: number, recipe: RecipeUpdate): Promise<Recipe> {
    const response = await apiClient.put(`/api/v1/recipes/${id}`, recipe)
    return handleResponse(response)
  }

  async deleteRecipe(id: number): Promise<void> {
    await apiClient.delete(`/api/v1/recipes/${id}`)
  }

  // Process control endpoints
  async getProcessStatus(): Promise<ProcessStatus> {
    const response = await apiClient.get('/api/v1/process/status')
    return handleResponse(response)
  }

  async startProcess(request: ProcessStartRequest): Promise<ProcessActionResponse> {
    const response = await apiClient.post('/api/v1/process/start', request)
    return handleResponse(response)
  }

  async pauseProcess(): Promise<ProcessActionResponse> {
    const response = await apiClient.post('/api/v1/process/pause')
    return handleResponse(response)
  }

  async resumeProcess(): Promise<ProcessActionResponse> {
    const response = await apiClient.post('/api/v1/process/resume')
    return handleResponse(response)
  }

  async stopProcess(): Promise<ProcessActionResponse> {
    const response = await apiClient.post('/api/v1/process/stop')
    return handleResponse(response)
  }

  async emergencyStop(): Promise<ProcessActionResponse> {
    const response = await apiClient.post('/api/v1/process/emergency-stop')
    return handleResponse(response)
  }

  // Hardware endpoints
  async getHardwareStatus(): Promise<HardwareStatus> {
    const response = await apiClient.get('/api/v1/hardware/status')
    return handleResponse(response)
  }

  async getTemperatures(): Promise<any[]> {
    const response = await apiClient.get('/api/v1/hardware/temperatures')
    return handleResponse(response)
  }

  async getMotorStatus(): Promise<any[]> {
    const response = await apiClient.get('/api/v1/hardware/motors')
    return handleResponse(response)
  }

  async setMotorSpeed(motorId: string, speed: number): Promise<void> {
    await apiClient.post(`/api/v1/hardware/motors/${motorId}/speed`, { speed })
  }

  // Safety endpoints
  async getSafetyStatus(): Promise<SafetyStatus> {
    const response = await apiClient.get('/api/v1/safety/status')
    return handleResponse(response)
  }

  async acknowledgeAlarm(alarmId: string): Promise<void> {
    await apiClient.post(`/api/v1/safety/alarms/${alarmId}/acknowledge`)
  }

  async clearAlarms(): Promise<void> {
    await apiClient.post('/api/v1/safety/alarms/clear')
  }

  // User management endpoints
  async getUsers(params?: {
    skip?: number
    limit?: number
    active_only?: boolean
  }): Promise<{ users: User[]; total: number }> {
    const response = await apiClient.get('/api/v1/users', { params })
    return handleResponse(response)
  }

  async getUser(id: string): Promise<User> {
    const response = await apiClient.get(`/api/v1/users/${id}`)
    return handleResponse(response)
  }

  async createUser(user: UserCreate): Promise<User> {
    const response = await apiClient.post('/api/v1/users', user)
    return handleResponse(response)
  }

  async updateUser(id: string, user: UserUpdate): Promise<User> {
    const response = await apiClient.put(`/api/v1/users/${id}`, user)
    return handleResponse(response)
  }

  async deleteUser(id: string): Promise<void> {
    await apiClient.delete(`/api/v1/users/${id}`)
  }

  // Authentication endpoints
  async login(username: string, password: string): Promise<{ access_token: string; token_type: string; user: User }> {
    const response = await apiClient.post('/api/v1/auth/login', {
      username,
      password,
    })
    const data = handleResponse(response)
    
    // Store token
    localStorage.setItem('auth_token', data.access_token)
    
    return data
  }

  async logout(): Promise<void> {
    localStorage.removeItem('auth_token')
    await apiClient.post('/api/v1/auth/logout')
  }

  async refreshToken(): Promise<{ access_token: string }> {
    const response = await apiClient.post('/api/v1/auth/refresh')
    const data = handleResponse(response)
    localStorage.setItem('auth_token', data.access_token)
    return data
  }

  // Data export endpoints
  async exportProcessData(sessionId: string, format: 'csv' | 'json' = 'csv'): Promise<Blob> {
    const response = await apiClient.get(`/api/v1/data/export/${sessionId}`, {
      params: { format },
      responseType: 'blob',
    })
    return response.data
  }

  async getProcessMetrics(days: number = 30): Promise<any> {
    const response = await apiClient.get('/api/v1/data/metrics', {
      params: { days },
    })
    return handleResponse(response)
  }
}

// Create and export API service instance
export const api = new ApiService()

// Export the axios instance for direct use if needed
export { apiClient }
