const API_BASE = import.meta.env.VITE_API_URL || ''

class ApiClient {
  constructor() {
    this.token = localStorage.getItem('rmm_token')
  }

  setToken(token) {
    this.token = token
    if (token) {
      localStorage.setItem('rmm_token', token)
    } else {
      localStorage.removeItem('rmm_token')
    }
  }

  getToken() {
    return this.token
  }

  async request(path, options = {}) {
    const headers = {
      'Content-Type': 'application/json',
      ...options.headers,
    }

    if (this.token) {
      headers['Authorization'] = `Bearer ${this.token}`
    }

    const res = await fetch(`${API_BASE}${path}`, {
      ...options,
      headers,
    })

    if (res.status === 401) {
      this.setToken(null)
      window.location.href = '/login'
      throw new Error('Unauthorized')
    }

    if (!res.ok) {
      const err = await res.json().catch(() => ({ error: res.statusText }))
      throw new Error(err.error || 'Request failed')
    }

    return res.json()
  }

  get(path) {
    return this.request(path)
  }

  post(path, body) {
    const opts = { method: 'POST' }
    if (body !== undefined) opts.body = JSON.stringify(body)
    return this.request(path, opts)
  }

  put(path, body) {
    return this.request(path, { method: 'PUT', body: JSON.stringify(body) })
  }

  del(path) {
    return this.request(path, { method: 'DELETE' })
  }

  // Auth
  async login(username, password) {
    const data = await this.post('/api/v1/auth/login', { username, password })
    if (data.token) this.setToken(data.token)
    return data
  }

  async validateTOTP(totpToken, code) {
    const data = await this.post('/api/v1/auth/2fa/validate', { totp_token: totpToken, code })
    if (data.token) this.setToken(data.token)
    return data
  }

  async setupTOTP() {
    return this.post('/api/v1/auth/2fa/setup')
  }

  async confirmTOTP(code) {
    return this.post('/api/v1/auth/2fa/confirm', { code })
  }

  async disableTOTP(password, code) {
    return this.post('/api/v1/auth/2fa/disable', { password, code })
  }

  logout() {
    this.setToken(null)
  }

  me() {
    return this.get('/api/v1/auth/me')
  }

  // Agents
  getAgents() {
    return this.get('/api/v1/agents')
  }

  getAgent(id) {
    return this.get(`/api/v1/agents/${id}`)
  }

  getAgentEvents(id, limit = 50) {
    return this.get(`/api/v1/agents/${id}/events?limit=${limit}`)
  }

  deleteAgent(id) {
    return this.del(`/api/v1/agents/${id}`)
  }

  preRegisterAgent(name, customerId) {
    const body = { name }
    if (customerId) body.customer_id = customerId
    return this.post('/api/v1/agents', body)
  }

  assignCustomer(agentId, customerId) {
    return this.put(`/api/v1/agents/${agentId}/customer`, { customer_id: customerId })
  }

  unassignCustomer(agentId) {
    return this.del(`/api/v1/agents/${agentId}/customer`)
  }

  // Customers
  getCustomers() {
    return this.get('/api/v1/customers')
  }

  createCustomer(number, name) {
    return this.post('/api/v1/customers', { number, name })
  }

  updateCustomer(id, number, name) {
    return this.put(`/api/v1/customers/${id}`, { number, name })
  }

  deleteCustomer(id) {
    return this.del(`/api/v1/customers/${id}`)
  }

  getCustomerAgents(id) {
    return this.get(`/api/v1/customers/${id}/agents`)
  }

  // Metrics
  getMetrics(agentId, metric, params = '') {
    return this.get(`/api/v1/agents/${agentId}/metrics?metric=${metric}${params}`)
  }

  getMetricsSummary(agentId, metric, bucket = '5 minutes') {
    return this.get(`/api/v1/agents/${agentId}/metrics/summary?metric=${metric}&bucket=${encodeURIComponent(bucket)}`)
  }

  // Backups
  getBackups(agentId) {
    return this.get(`/api/v1/agents/${agentId}/backups`)
  }

  async downloadBackup(agentId, backupId) {
    const headers = {}
    if (this.token) headers['Authorization'] = `Bearer ${this.token}`
    const res = await fetch(`${API_BASE}/api/v1/agents/${agentId}/backups/${backupId}?format=xml`, { headers })
    if (!res.ok) throw new Error('Download fehlgeschlagen')
    const blob = await res.blob()
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `config_${agentId.substring(0, 8)}_${backupId}.xml`
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  }

  triggerBackup(agentId) {
    return this.post(`/api/v1/agents/${agentId}/backup`)
  }

  // Tunnel
  openTunnel(agentId, targetHost, targetPort) {
    return this.post(`/api/v1/agents/${agentId}/tunnel`, { target_host: targetHost, target_port: targetPort })
  }

  getTunnels(agentId) {
    return this.get(`/api/v1/agents/${agentId}/tunnels`)
  }

  closeTunnel(agentId, tunnelId) {
    return this.del(`/api/v1/agents/${agentId}/tunnel/${tunnelId}`)
  }

  // WireGuard
  getWgPeers(agentId) {
    return this.get(`/api/v1/agents/${agentId}/wireguard/peers`)
  }

  addWgPeer(agentId, data) {
    return this.post(`/api/v1/agents/${agentId}/wireguard/peers`, data)
  }

  deleteWgPeer(agentId, uuid) {
    return this.del(`/api/v1/agents/${agentId}/wireguard/peers/${uuid}`)
  }

  // Updates
  checkUpdates(agentId) {
    return this.post(`/api/v1/agents/${agentId}/update-check`)
  }

  runUpdate(agentId, reboot = false) {
    return this.post(`/api/v1/agents/${agentId}/update`, { reboot })
  }

  // Exec
  execCommand(agentId, command, timeout = 30) {
    return this.post(`/api/v1/agents/${agentId}/exec`, { command, timeout })
  }

  proxmoxAction(agentId, type, vmid, action) {
    return this.post(`/api/v1/agents/${agentId}/proxmox/action`, { type, vmid, action })
  }

  // Users
  getUsers() {
    return this.get('/api/v1/users')
  }

  createUser(data) {
    return this.post('/api/v1/users', data)
  }

  deleteUser(id) {
    return this.del(`/api/v1/users/${id}`)
  }

  changePassword(userId, password) {
    return this.put(`/api/v1/users/${userId}/password`, { password })
  }

  // API-Keys
  getAPIKeys() {
    return this.get('/api/v1/apikeys')
  }

  getCustomerAPIKeys(customerId) {
    return this.get(`/api/v1/customers/${customerId}/apikeys`)
  }

  createAPIKey(name, permissions = 'read', customerId = null) {
    return this.post('/api/v1/apikeys', { name, permissions, customer_id: customerId })
  }

  deleteAPIKey(id) {
    return this.del(`/api/v1/apikeys/${id}`)
  }

  // System Settings
  getSettings() {
    return this.get('/api/v1/settings')
  }

  updateSettings(data) {
    return this.put('/api/v1/settings', data)
  }

  // Audit Log
  getAuditLogs(params = {}) {
    const q = new URLSearchParams()
    if (params.limit) q.set('limit', params.limit)
    if (params.offset) q.set('offset', params.offset)
    if (params.action) q.set('action', params.action)
    if (params.agent_id) q.set('agent_id', params.agent_id)
    return this.get(`/api/v1/audit?${q.toString()}`)
  }

  // Firmware
  getFirmwareInfo() {
    return this.get('/api/v1/firmware')
  }

  async uploadFirmware(version, platform, file) {
    const headers = {}
    if (this.token) headers['Authorization'] = `Bearer ${this.token}`
    const res = await fetch(`${API_BASE}/api/v1/firmware/upload?version=${encodeURIComponent(version)}&platform=${encodeURIComponent(platform)}`, {
      method: 'POST',
      headers,
      body: file,
    })
    if (res.status === 401) {
      this.setToken(null)
      window.location.href = '/login'
      throw new Error('Unauthorized')
    }
    if (!res.ok) {
      const err = await res.json().catch(() => ({ error: res.statusText }))
      throw new Error(err.error || 'Upload fehlgeschlagen')
    }
    return res.json()
  }

  requestAgentUpdate(agentId) {
    return this.post(`/api/v1/agents/${agentId}/request-update`)
  }

  cancelAgentUpdate(agentId) {
    return this.del(`/api/v1/agents/${agentId}/request-update`)
  }

  requestUpdateAll() {
    return this.post('/api/v1/agents/request-update-all')
  }

  // Tasks
  getTasks(params = {}) {
    const q = new URLSearchParams()
    if (params.limit) q.set('limit', params.limit)
    if (params.offset) q.set('offset', params.offset)
    if (params.agent_id) q.set('agent_id', params.agent_id)
    if (params.status) q.set('status', params.status)
    if (params.action) q.set('action', params.action)
    return this.get(`/api/v1/tasks?${q.toString()}`)
  }

  createTask(data) {
    return this.post('/api/v1/tasks', data)
  }

  cancelTask(id) {
    return this.post(`/api/v1/tasks/${id}/cancel`)
  }

  deleteTask(id) {
    return this.del(`/api/v1/tasks/${id}`)
  }

  runTaskNow(id) {
    return this.post(`/api/v1/tasks/${id}/run`)
  }

  updateTask(id, data) {
    return this.put(`/api/v1/tasks/${id}`, data)
  }

  toggleTask(id) {
    return this.put(`/api/v1/tasks/${id}/toggle`)
  }

  // Installer
  getInstallerInfo() {
    return this.get('/api/v1/installer')
  }

  async uploadInstaller(platform, file) {
    const headers = {}
    if (this.token) headers['Authorization'] = `Bearer ${this.token}`
    const formData = new FormData()
    formData.append('file', file)
    const res = await fetch(`${API_BASE}/api/v1/installer/upload?platform=${encodeURIComponent(platform)}`, {
      method: 'POST',
      headers,
      body: formData,
    })
    if (res.status === 401) {
      this.setToken(null)
      window.location.href = '/login'
      throw new Error('Unauthorized')
    }
    if (!res.ok) {
      const err = await res.json().catch(() => ({ error: res.statusText }))
      throw new Error(err.error || 'Upload fehlgeschlagen')
    }
    return res.json()
  }
}

export const api = new ApiClient()
export default api
