import apiClient from './client'

export interface PhysicalDisk {
  id: string
  device_path: string
  vendor?: string
  model?: string
  serial_number?: string
  size_bytes: number
  sector_size?: number
  is_ssd: boolean
  health_status: string
  is_used: boolean
  attached_to_pool?: string // Pool name if disk is used in a ZFS pool
  created_at: string
  updated_at: string
}

export interface VolumeGroup {
  id: string
  name: string
  size_bytes: number
  free_bytes: number
  physical_volumes: string[]
  created_at: string
  updated_at: string
}

export interface Repository {
  id: string
  name: string
  description?: string
  volume_group: string
  logical_volume: string
  size_bytes: number
  used_bytes: number
  filesystem_type?: string
  mount_point?: string
  is_active: boolean
  warning_threshold_percent: number
  critical_threshold_percent: number
  created_at: string
  updated_at: string
}

export const storageApi = {
  listDisks: async (): Promise<PhysicalDisk[]> => {
    const response = await apiClient.get<{ disks: PhysicalDisk[] | null }>('/storage/disks')
    return response.data.disks || []
  },

  syncDisks: async (): Promise<{ task_id: string }> => {
    const response = await apiClient.post<{ task_id: string }>('/storage/disks/sync')
    return response.data
  },

  listVolumeGroups: async (): Promise<VolumeGroup[]> => {
    const response = await apiClient.get<{ volume_groups: VolumeGroup[] | null }>('/storage/volume-groups')
    return response.data.volume_groups || []
  },

  listRepositories: async (): Promise<Repository[]> => {
    const response = await apiClient.get<{ repositories: Repository[] | null }>('/storage/repositories')
    return response.data.repositories || []
  },

  getRepository: async (id: string): Promise<Repository> => {
    const response = await apiClient.get<Repository>(`/storage/repositories/${id}`)
    return response.data
  },

  createRepository: async (data: {
    name: string
    description?: string
    volume_group: string
    size_gb: number
    filesystem_type?: string
  }): Promise<{ task_id: string }> => {
    const response = await apiClient.post<{ task_id: string }>('/storage/repositories', data)
    return response.data
  },

  deleteRepository: async (id: string): Promise<void> => {
    await apiClient.delete(`/storage/repositories/${id}`)
  },
}

export interface ZFSPool {
  id: string
  name: string
  description?: string
  raid_level: string // stripe, mirror, raidz, raidz2, raidz3
  disks: string[] // device paths
  spare_disks?: string[] // spare disk paths
  size_bytes: number
  used_bytes: number
  compression: string // off, lz4, zstd, gzip
  deduplication: boolean
  auto_expand: boolean
  scrub_interval: number // days
  is_active: boolean
  health_status: string // online, degraded, faulted, offline
  compress_ratio?: number // compression ratio (e.g., 1.45)
  created_at: string
  updated_at: string
  created_by: string
}

export const zfsApi = {
  listPools: async (): Promise<ZFSPool[]> => {
    const response = await apiClient.get<{ pools: ZFSPool[] | null }>('/storage/zfs/pools')
    return response.data.pools || []
  },

  getPool: async (id: string): Promise<ZFSPool> => {
    const response = await apiClient.get<ZFSPool>(`/storage/zfs/pools/${id}`)
    return response.data
  },

  createPool: async (data: {
    name: string
    description?: string
    raid_level: string
    disks: string[]
    compression?: string
    deduplication?: boolean
    auto_expand?: boolean
  }): Promise<ZFSPool> => {
    const response = await apiClient.post<ZFSPool>('/storage/zfs/pools', data)
    return response.data
  },

  deletePool: async (id: string): Promise<void> => {
    await apiClient.delete(`/storage/zfs/pools/${id}`)
  },

  addSpareDisk: async (id: string, disks: string[]): Promise<void> => {
    await apiClient.post(`/storage/zfs/pools/${id}/spare`, { disks })
  },

  listDatasets: async (poolId: string): Promise<ZFSDataset[]> => {
    const response = await apiClient.get<{ datasets: ZFSDataset[] | null }>(`/storage/zfs/pools/${poolId}/datasets`)
    return response.data.datasets || []
  },

  createDataset: async (poolId: string, data: {
    name: string
    type: 'filesystem' | 'volume'
    compression?: string
    quota?: number
    reservation?: number
    mount_point?: string
  }): Promise<ZFSDataset> => {
    const response = await apiClient.post<ZFSDataset>(`/storage/zfs/pools/${poolId}/datasets`, data)
    return response.data
  },

  deleteDataset: async (poolId: string, datasetName: string): Promise<void> => {
    await apiClient.delete(`/storage/zfs/pools/${poolId}/datasets/${encodeURIComponent(datasetName)}`)
  },

  getARCStats: async (): Promise<ARCStats> => {
    const response = await apiClient.get<ARCStats>('/storage/zfs/arc/stats')
    return response.data
  },
}

// Snapshot interfaces and API
export interface Snapshot {
  id: string
  name: string // Full snapshot name (e.g., "pool/dataset@snapshot-name")
  dataset: string // Dataset name (e.g., "pool/dataset")
  snapshot_name: string // Snapshot name only (e.g., "snapshot-name")
  created: string
  referenced: number // Size in bytes
  used: number // Used space in bytes
  is_latest: boolean // Whether this is the latest snapshot for the dataset
}

export interface CreateSnapshotRequest {
  dataset: string
  name: string
  recursive?: boolean
}

export interface CloneSnapshotRequest {
  clone_name: string
}

export const snapshotApi = {
  listSnapshots: async (dataset?: string): Promise<Snapshot[]> => {
    const params = dataset ? `?dataset=${encodeURIComponent(dataset)}` : ''
    const response = await apiClient.get<{ snapshots: Snapshot[] }>(`/storage/zfs/snapshots${params}`)
    return response.data.snapshots || []
  },

  createSnapshot: async (data: CreateSnapshotRequest): Promise<void> => {
    await apiClient.post('/storage/zfs/snapshots', data)
  },

  deleteSnapshot: async (snapshotName: string, recursive?: boolean): Promise<void> => {
    const params = recursive ? '?recursive=true' : ''
    await apiClient.delete(`/storage/zfs/snapshots/${encodeURIComponent(snapshotName)}${params}`)
  },

  rollbackSnapshot: async (snapshotName: string, force?: boolean): Promise<void> => {
    await apiClient.post(`/storage/zfs/snapshots/${encodeURIComponent(snapshotName)}/rollback`, { force: force || false })
  },

  cloneSnapshot: async (snapshotName: string, data: CloneSnapshotRequest): Promise<void> => {
    await apiClient.post(`/storage/zfs/snapshots/${encodeURIComponent(snapshotName)}/clone`, data)
  },
}

// Snapshot Schedule interfaces and API
export interface SnapshotSchedule {
  id: string
  name: string
  dataset: string
  snapshot_name_template: string
  schedule_type: 'hourly' | 'daily' | 'weekly' | 'monthly' | 'cron'
  schedule_config: {
    time?: string // For daily, weekly, monthly (HH:MM format)
    day?: number // For weekly (0-6, Sunday=0), monthly (1-31)
    cron?: string // For cron type
  }
  recursive: boolean
  enabled: boolean
  retention_count?: number
  retention_days?: number
  last_run_at?: string
  next_run_at?: string
  created_by?: string
  created_at: string
  updated_at: string
}

export interface CreateSnapshotScheduleRequest {
  name: string
  dataset: string
  snapshot_name_template: string
  schedule_type: 'hourly' | 'daily' | 'weekly' | 'monthly' | 'cron'
  schedule_config: {
    time?: string
    day?: number
    cron?: string
  }
  recursive?: boolean
  retention_count?: number
  retention_days?: number
}

export const snapshotScheduleApi = {
  listSchedules: async (): Promise<SnapshotSchedule[]> => {
    const response = await apiClient.get<{ schedules: SnapshotSchedule[] }>('/storage/zfs/snapshot-schedules')
    return response.data.schedules || []
  },

  getSchedule: async (id: string): Promise<SnapshotSchedule> => {
    const response = await apiClient.get<SnapshotSchedule>(`/storage/zfs/snapshot-schedules/${id}`)
    return response.data
  },

  createSchedule: async (data: CreateSnapshotScheduleRequest): Promise<SnapshotSchedule> => {
    const response = await apiClient.post<SnapshotSchedule>('/storage/zfs/snapshot-schedules', data)
    return response.data
  },

  updateSchedule: async (id: string, data: CreateSnapshotScheduleRequest): Promise<SnapshotSchedule> => {
    const response = await apiClient.put<SnapshotSchedule>(`/storage/zfs/snapshot-schedules/${id}`, data)
    return response.data
  },

  deleteSchedule: async (id: string): Promise<void> => {
    await apiClient.delete(`/storage/zfs/snapshot-schedules/${id}`)
  },

  toggleSchedule: async (id: string, enabled: boolean): Promise<void> => {
    await apiClient.post(`/storage/zfs/snapshot-schedules/${id}/toggle`, { enabled })
  },
}

export interface ZFSDataset {
  id: string
  name: string
  pool: string
  type: string // filesystem, volume, snapshot
  mount_point: string
  used_bytes: number
  available_bytes: number
  referenced_bytes: number
  compression: string
  deduplication: string
  quota: number // -1 for unlimited
  reservation: number
  created_at: string
}

export interface ARCStats {
  hit_ratio: number
  cache_usage: number
  cache_size: number
  cache_max: number
  hits: number
  misses: number
  demand_hits: number
  prefetch_hits: number
  mru_hits: number
  mfu_hits: number
  collected_at: string
}

// Replication Task interfaces and API
export interface ReplicationTask {
  id: string
  name: string
  direction: 'outbound' | 'inbound'
  source_dataset?: string
  target_host?: string
  target_port?: number
  target_user?: string
  target_dataset?: string
  target_ssh_key_path?: string
  source_host?: string
  source_port?: number
  source_user?: string
  local_dataset?: string
  schedule_type?: string
  schedule_config?: {
    time?: string
    day?: number
    cron?: string
  }
  compression: string
  encryption: boolean
  recursive: boolean
  incremental: boolean
  auto_snapshot: boolean
  enabled: boolean
  status: 'idle' | 'running' | 'failed' | 'paused'
  last_run_at?: string
  last_run_status?: 'success' | 'failed' | 'partial'
  last_run_error?: string
  next_run_at?: string
  last_snapshot_sent?: string
  last_snapshot_received?: string
  total_runs: number
  successful_runs: number
  failed_runs: number
  bytes_sent: number
  bytes_received: number
  created_by?: string
  created_at: string
  updated_at: string
}

export interface CreateReplicationTaskRequest {
  name: string
  direction: 'outbound' | 'inbound'
  source_dataset?: string
  target_host?: string
  target_port?: number
  target_user?: string
  target_dataset?: string
  target_ssh_key_path?: string
  source_host?: string
  source_port?: number
  source_user?: string
  local_dataset?: string
  schedule_type?: string
  schedule_config?: {
    time?: string
    day?: number
    cron?: string
  }
  compression?: string
  encryption?: boolean
  recursive?: boolean
  incremental?: boolean
  auto_snapshot?: boolean
  enabled?: boolean
}

export const replicationApi = {
  listTasks: async (direction?: 'outbound' | 'inbound'): Promise<ReplicationTask[]> => {
    const params = direction ? `?direction=${direction}` : ''
    const response = await apiClient.get<{ tasks: ReplicationTask[] }>(`/storage/zfs/replication-tasks${params}`)
    return response.data.tasks || []
  },

  getTask: async (id: string): Promise<ReplicationTask> => {
    const response = await apiClient.get<ReplicationTask>(`/storage/zfs/replication-tasks/${id}`)
    return response.data
  },

  createTask: async (data: CreateReplicationTaskRequest): Promise<ReplicationTask> => {
    const response = await apiClient.post<ReplicationTask>('/storage/zfs/replication-tasks', data)
    return response.data
  },

  updateTask: async (id: string, data: CreateReplicationTaskRequest): Promise<ReplicationTask> => {
    const response = await apiClient.put<ReplicationTask>(`/storage/zfs/replication-tasks/${id}`, data)
    return response.data
  },

  deleteTask: async (id: string): Promise<void> => {
    await apiClient.delete(`/storage/zfs/replication-tasks/${id}`)
  },
}
