const BASE = import.meta.env.VITE_API_BASE_URL ?? '/api'

export interface DeploymentStatus {
  mode: 'PUBLIC' | 'PRIVATE'
  tenantRegisterEnabled: boolean
  services: Record<string, { enabled: boolean; baseUrl: string | null }>
}

export async function getDeploymentStatus(): Promise<DeploymentStatus> {
  const res = await fetch(`${BASE}/private/deployment/status`)
  const json = await res.json()
  return json.data as DeploymentStatus
}

async function streamOperation(
  path: string,
  onLine: (line: string) => void,
  signal?: AbortSignal,
): Promise<void> {
  const token = localStorage.getItem('token') ?? ''
  const res = await fetch(`${BASE}${path}`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${token}` },
    signal,
  })
  if (!res.ok) {
    const text = await res.text()
    throw new Error(text || `HTTP ${res.status}`)
  }
  const reader = res.body!.getReader()
  const decoder = new TextDecoder()
  let buf = ''
  try {
    while (true) {
      const { done, value } = await reader.read()
      if (done) break
      buf += decoder.decode(value, { stream: true })
      const lines = buf.split('\n')
      buf = lines.pop() ?? ''
      for (const line of lines) {
        onLine(line)
      }
    }
    if (buf) onLine(buf)
  } catch (e: any) {
    // Connection drop during RESTART_SELF is expected - don't throw
    if (e?.name === 'TypeError' || e?.message?.includes('network') || e?.message?.includes('fetch')) {
      onLine('>>> 连接已中断（服务正在重启）')
      return
    }
    throw e
  }
}

export async function getRunningServices(): Promise<string[]> {
  const token = localStorage.getItem('token') ?? ''
  const res = await fetch(`${BASE}/system/services`, {
    headers: { Authorization: `Bearer ${token}` },
  })
  if (!res.ok) throw new Error(`HTTP ${res.status}`)
  const json = await res.json()
  return json.data as string[]
}

export async function fetchServiceLogs(service: string, lines: number): Promise<string> {
  const token = localStorage.getItem('token') ?? ''
  const res = await fetch(
    `${BASE}/system/logs/${encodeURIComponent(service)}?lines=${lines}`,
    { headers: { Authorization: `Bearer ${token}` } },
  )
  if (!res.ok) throw new Error(`HTTP ${res.status}`)
  return res.text()
}

export async function getSystemVersion(): Promise<{ currentVersion: string }> {
  const token = localStorage.getItem('token') ?? ''
  const res = await fetch(`${BASE}/system/version`, {
    headers: { Authorization: `Bearer ${token}` },
  })
  if (!res.ok) throw new Error(`HTTP ${res.status}`)
  const json = await res.json()
  return json.data as { currentVersion: string }
}

export function streamSystemUpdate(onLine: (line: string) => void, signal?: AbortSignal) {
  return streamOperation('/system/update', onLine, signal)
}

export function streamSelectiveUpdate(services: string[], onLine: (line: string) => void, signal?: AbortSignal) {
  const qs = services.map(s => `services=${encodeURIComponent(s)}`).join('&')
  return streamOperation(`/system/update-selective${qs ? '?' + qs : ''}`, onLine, signal)
}

export function streamSystemReset(onLine: (line: string) => void, signal?: AbortSignal) {
  return streamOperation('/system/reset', onLine, signal)
}

export interface UpdateCheckResult {
  currentVersion: string
  latestVersion: string
  hasUpdate: boolean
  releasedAt: string
  changelog: string
  services: Record<string, { current: string; latest: string; changed: boolean }>
}

export async function checkForUpdates(): Promise<UpdateCheckResult> {
  const json = await authFetch('/system/check-update')
  return json as UpdateCheckResult
}

// ── Database Management (PRIVATE mode only) ──────────────────────────────

export interface TableInfo {
  name: string
  comment: string
}

export interface ColumnInfo {
  name: string
  type: string
  size: number
  nullable: boolean
  comment: string
}

export interface TableDataPage {
  columns: string[]
  rows: Record<string, any>[]
  total: number
  totalPages: number
  page: number
  size: number
}

async function authFetch(path: string): Promise<any> {
  const token = localStorage.getItem('token') ?? ''
  const res = await fetch(`${BASE}${path}`, {
    headers: { Authorization: `Bearer ${token}` },
  })
  if (!res.ok) {
    const json = await res.json().catch(() => null)
    throw new Error(json?.message ?? `HTTP ${res.status}`)
  }
  return res.json()
}

export async function listDatabaseTables(): Promise<TableInfo[]> {
  const json = await authFetch('/system/database/tables')
  return json.data as TableInfo[]
}

export async function getTableColumns(tableName: string): Promise<ColumnInfo[]> {
  const json = await authFetch(`/system/database/tables/${encodeURIComponent(tableName)}/columns`)
  return json.data as ColumnInfo[]
}

export async function getTableData(
  tableName: string,
  params: { page?: number; size?: number; keyword?: string; sortColumn?: string; sortDirection?: string },
): Promise<TableDataPage> {
  const query = new URLSearchParams()
  if (params.page != null) query.set('page', String(params.page))
  if (params.size != null) query.set('size', String(params.size))
  if (params.keyword) query.set('keyword', params.keyword)
  if (params.sortColumn) query.set('sortColumn', params.sortColumn)
  if (params.sortDirection) query.set('sortDirection', params.sortDirection)
  const qs = query.toString()
  const json = await authFetch(`/system/database/tables/${encodeURIComponent(tableName)}/data${qs ? '?' + qs : ''}`)
  return json.data as TableDataPage
}
