import adminClient from "./client"
import type { ApiResponse } from "../../types"
import type { UpstreamActionLog } from "../../api/upstreamActions"
import { pageResult } from "./response"

export interface AdminInstanceUser {
  id: number
  username: string | null
  nickname: string | null
  email: string | null
  phone: string | null
  balance: number
  label?: string | null
}

export interface AdminInstance {
  id: number
  user_id: number
  order_id: number
  product_id: number
  product_name: string
  product_group_name: string | null
  api_type?: string | null
  status: string
  suspend_type: string | null
  hostname: string | null
  alias: string | null
  main_ip: string | null
  ssh_port: number | null
  os_image?: string | null
  cpu?: number | null
  memory?: number | null
  system_disk_size?: number | null
  data_disk_size?: number | null
  in_bw?: number | null
  out_bw?: number | null
  ip_num?: number | null
  nat_acl_limit?: number | null
  traffic_quota?: number | null
  traffic_type?: number | null
  internet?: number
  is_locked?: number
  cycle: string
  unit_price: number
  next_renew_amount: number
  auto_renew: number
  expires_at: string | null
  created_at: string | null
  updated_at?: string | null
  terminated_at: string | null
  upstream_id: number | null
  upstream_task_id?: number | null
  upstream_invoice_id?: number | null
  cloud_server_id: number | null
  cloud_server_name: string | null
  cloud_server_base_url: string | null
  upstream_console_url: string | null
  provision_attempts: number
  last_provision_at: string | null
  provision_log: string | null
  provision_plugin?: AdminProvisionPlugin | null
  plugin_manage_actions?: AdminPluginManageAction[]
  plugin_links?: AdminPluginLink[]
  user: AdminInstanceUser
}

export interface AdminProvisionPlugin {
  id: string
  name: string
  version: string
}

export interface AdminPluginManageAction {
  key: string
  label: string
  confirm?: boolean
  style?: string
  audience?: string
  description?: string
}

export interface AdminPluginLink {
  label: string
  url: string
}

export interface AdminInstanceDetail extends AdminInstance {
  actions?: UpstreamActionLog[]
}

export interface AdminInstanceListQuery {
  keyword?: string
  status?: string
  user_id?: number
  product_id?: number
  group_id?: number
  cloud_server_id?: number
  has_upstream?: boolean
  auto_renew?: boolean
  expired?: boolean
  due_days?: number
  order_by?: "id" | "created_at" | "updated_at" | "expires_at" | "user_id"
  sort?: "asc" | "desc"
  limit?: number
  offset?: number
}

export interface AdminInstanceListResult {
  items: AdminInstance[]
  total: number
  limit: number
  offset: number
  summary: Record<string, number>
}

export interface AdminInstanceBillingPayload {
  cycle?: string
  unit_price?: number
  next_renew_amount?: number
  expires_at?: string | null
  auto_renew?: boolean
}

export type AdminInstancePowerAction = "power-on" | "shutdown" | "hard-shutdown" | "reboot"
export type AdminInstanceBatchAction = AdminInstancePowerAction | "suspend" | "unsuspend" | "delete" | "provision"

export interface AdminInstanceBatchPayload {
  ids: number[]
  type?: "traffic" | "due" | "manual"
  free_gpu?: number
  reason?: string
}

export interface AdminInstanceBatchResultItem {
  id: number
  success: boolean
  data?: Record<string, unknown>
  error?: string
}

export interface AdminInstanceBatchResult {
  success: number
  failed: number
  results: AdminInstanceBatchResultItem[]
}

const BASE = "/v1/admin/instances"

function toParams(query: AdminInstanceListQuery = {}) {
  const params = new URLSearchParams()
  Object.entries(query).forEach(([key, value]) => {
    if (value !== undefined && value !== null && value !== "") params.set(key, String(value))
  })
  return params
}

export async function listAdminInstances(query: AdminInstanceListQuery = {}) {
  const params = toParams(query)
  const { data } = await adminClient.get<ApiResponse<AdminInstanceListResult | AdminInstance[]>>(
    params.toString() ? `${BASE}?${params.toString()}` : BASE,
  )
  const paged = pageResult<AdminInstance>(data.data)
  const payload = data.data && !Array.isArray(data.data) ? data.data : null
  return {
    ...data,
    data: {
      items: paged.items,
      total: paged.total,
      limit: paged.limit ?? query.limit ?? paged.items.length,
      offset: paged.offset ?? query.offset ?? 0,
      summary: payload && "summary" in payload ? payload.summary : {},
    },
  }
}

export async function getAdminInstance(instanceId: number) {
  const { data } = await adminClient.get<ApiResponse<AdminInstanceDetail>>(`${BASE}/${instanceId}`)
  return data
}

export async function operateAdminInstancePower(instanceId: number, action: AdminInstancePowerAction) {
  const { data } = await adminClient.post<ApiResponse<{ taskid: number | null; instance_id: number }>>(
    `${BASE}/${instanceId}/power/${action}`,
  )
  return data
}

export async function suspendAdminInstance(
  instanceId: number,
  payload: { type?: "traffic" | "due" | "manual"; free_gpu?: number; reason?: string } = {},
) {
  const { data } = await adminClient.post<ApiResponse<{ taskid: number | null; instance_id: number }>>(
    `${BASE}/${instanceId}/suspend`,
    { type: "manual", free_gpu: 0, ...payload },
  )
  return data
}

export async function unsuspendAdminInstance(instanceId: number) {
  const { data } = await adminClient.post<ApiResponse<{ taskid: number | null; instance_id: number }>>(
    `${BASE}/${instanceId}/unsuspend`,
  )
  return data
}

export async function deleteAdminInstance(instanceId: number) {
  const { data } = await adminClient.delete<ApiResponse<{ taskid: number | null; instance_id: number }>>(
    `${BASE}/${instanceId}`,
  )
  return data
}

export async function provisionAdminInstance(instanceId: number) {
  const { data } = await adminClient.post<ApiResponse<{ instance_id: number }>>(
    `${BASE}/${instanceId}/provision`,
  )
  return data
}

export async function updateAdminInstanceAutoRenew(instanceId: number, autoRenew: boolean) {
  const { data } = await adminClient.patch<ApiResponse<{ id: number; auto_renew: number }>>(
    `${BASE}/${instanceId}/auto-renew`,
    { auto_renew: autoRenew },
  )
  return data
}

export async function updateAdminInstanceBilling(instanceId: number, payload: AdminInstanceBillingPayload) {
  const { data } = await adminClient.patch<ApiResponse<AdminInstance>>(
    `${BASE}/${instanceId}/billing`,
    payload,
  )
  return data
}

export async function batchOperateAdminInstances(action: AdminInstanceBatchAction, payload: AdminInstanceBatchPayload) {
  const { data } = await adminClient.post<ApiResponse<AdminInstanceBatchResult>>(
    `${BASE}/batch/${action}`,
    payload,
  )
  return data
}

export async function runAdminPluginAction(instanceId: number, action: string, payload?: Record<string, unknown>) {
  const { data } = await adminClient.post<ApiResponse<{ message?: string; payload?: Record<string, unknown> }>>(
    `${BASE}/${instanceId}/plugin-actions/${action}`,
    payload ? { payload } : undefined,
  )
  return data
}
