import adminClient from "./client"
import type { ApiResponse } from "../../types"
import { listResult } from "./response"

export type BillingCycle =
  | "hourly"
  | "daily"
  | "monthly"
  | "quarterly"
  | "semi_annually"
  | "annually"
  | "biennially"
  | "triennially"
  | "one_time"

export type ProductType = "server" | "hosting" | "domain" | "ssl" | "license" | "other"
export type ProductStatus = "draft" | "active" | "hidden" | "deprecated"
export type StockPolicy = "unlimited" | "tracked"
export type ProductApiType = "none" | "dcim_cloud_image" | "dcim_cloud_rid" | "zjmf_finance" | "plugin"

export type DiskUnit = "GB" | "MB"

export type ConfigFieldType = "fixed" | "user_select" | "input" | "slider"
export type ConfigFieldValidationType = "none" | "hostname" | "password"

export interface ConfigFieldOption {
  def: string   // "101|Debian 12 64位" 或 "101"（无显示名则原样显示）
}

export interface ConfigField {
  def: string                        // "os|操作系统" 或 "备注"
  type: ConfigFieldType
  value?: string | number | null     // type=fixed 时的固定值
  options?: ConfigFieldOption[]      // type=user_select 时的选项列表
  validation?: ConfigFieldValidationType  // type=input 时的验证规则
  hostname_prefix?: string           // validation=hostname 时的前缀
  hostname_length?: string           // validation=hostname 时的位数范围，如 "3-5"
  slider_min?: number                // type=slider 最小值（含，免费基础值）
  slider_max?: number                // type=slider 最大值（含）
  slider_step?: number               // type=slider 步长，默认 1
  slider_unit_price?: number         // type=slider 每单位价格（超出 min 部分计费）
  slider_unit?: string               // type=slider 单位显示，如 "GB"
}

export interface ProductPricingItem {
  cycle: BillingCycle
  price: number
  original_price?: number | null
  setup_fee?: number
  is_enabled?: boolean
  sort_order?: number
}

export interface ProductPricing extends Required<Omit<ProductPricingItem, "original_price">> {
  id: number
  original_price: number | null
}

export interface Product {
  id: number
  group_id: number
  sku: string
  name: string
  type: ProductType
  status: ProductStatus
  vcpu: number | null
  cpu_model: string | null
  cpu_base_mhz: number | null
  cpu_turbo_mhz: number | null
  memory: string | null
  disk: string | null
  bandwidth: string | null
  features: string | null
  badges: string | null
  base_setup_fee: number
  base_price: number
  stock_policy: StockPolicy
  stock: number
  min_quantity: number
  max_quantity: number
  auto_provision: boolean
  trial_enabled: boolean
  trial_days: number
  sort_order: number
  is_featured: boolean
  requires_real_name: boolean
  cloud_server_id: number | null
  api_type: ProductApiType
  api_identifier: string | null
  provision_interface_id: number | null
  provision_config: ConfigField[] | null
  provision_plugin?: ProvisionPluginManifest | null
  provision_interface?: ProvisionInterface | null
  product_page?: ProvisionProductPage | null
  pricings: ProductPricing[]
  created_at: string
  updated_at: string
}

export interface ProvisionProductPageTab {
  key: string
  label: string
  html: string
}

export interface ProvisionProductPage {
  layout?: string
  summary_html?: string
  empty_state_html?: string
  tabs?: ProvisionProductPageTab[]
  purchase_fields?: ProvisionPurchaseField[]
}

export interface ProvisionPurchaseField {
  key: string
  label: string
  type?: string
  required?: boolean
  default?: string | number | boolean | null
  placeholder?: string
  help?: string
  options?: { label: string; value: string }[]
}

export interface ProvisionManageAction {
  key: string
  label: string
  confirm?: boolean
  style?: "default" | "primary" | "danger" | string
  description?: string
}

export interface ProvisionTestLink {
  label: string
  url: string
  method?: string
}

export interface ProvisionConfigFieldOption {
  label: string
  value: string | number | boolean
}

export interface ProvisionConfigField {
  key: string
  label: string
  type?: string
  required?: boolean
  secret?: boolean
  default?: string | number | boolean | null
  placeholder?: string
  help?: string
  options?: ProvisionConfigFieldOption[]
  validation?: Record<string, unknown>
}

export interface ProvisionPluginManifest {
  id: string
  name: string
  version: string
  status?: string
  provider?: string
  description?: string
  capabilities?: string[]
  manage_actions?: ProvisionManageAction[]
  test_links?: ProvisionTestLink[]
  product_page?: ProvisionProductPage
  upstream_param_fields?: ProvisionConfigField[]
  config_fields?: ProvisionConfigField[]
  docs?: string
  requirements?: Record<string, unknown>
  author?: {
    name?: string
    url?: string
  }
}

export interface ProductCreatePayload {
  group_id: number
  sku: string
  name: string
  type?: ProductType
  status?: ProductStatus
  vcpu?: number | null
  cpu_model?: string | null
  cpu_base_mhz?: number | null
  cpu_turbo_mhz?: number | null
  memory?: string | null
  disk?: string | null
  bandwidth?: string | null
  features?: string | null
  badges?: string | null
  base_setup_fee?: number
  base_price?: number
  stock_policy?: StockPolicy
  stock?: number
  min_quantity?: number
  max_quantity?: number
  auto_provision?: boolean
  trial_enabled?: boolean
  trial_days?: number
  sort_order?: number
  is_featured?: boolean
  requires_real_name?: boolean
  cloud_server_id?: number | null
  api_type?: ProductApiType
  api_identifier?: string | null
  provision_interface_id?: number | null
  provision_config?: ConfigField[] | null
  pricings?: ProductPricingItem[]
}

export type ProductUpdatePayload = Partial<ProductCreatePayload>

export interface CloudResourceItem {
  id: string
  label: string
  extra: string | null
}

export interface ProvisionInterface {
  id: number
  name: string
  plugin_id: string
  plugin_name?: string | null
  config: Record<string, unknown>
  enabled: boolean
  sort_order: number
  remark?: string | null
  last_test_ok?: boolean | null
  last_test_message?: string | null
  created_at: string
  updated_at: string
}

export interface ProvisionInterfacePayload {
  name: string
  plugin_id: string
  config: Record<string, unknown>
  enabled?: boolean
  sort_order?: number
  remark?: string | null
}

export interface ZjmfFinanceProductItem {
  id: string
  name: string
  type: string | null
  description: string | null
  group_id: string | null
  group_name: string | null
}

export interface ZjmfFinanceProductGroup {
  id: string | null
  name: string
  products: ZjmfFinanceProductItem[]
}

export interface ZjmfFinanceProductList {
  count: number
  currency: string | null
  groups: ZjmfFinanceProductGroup[]
  products: ZjmfFinanceProductItem[]
}

export interface ZjmfFinancePricingCycle {
  cycle: BillingCycle
  label: string
  price: number | null
  setup_fee: number | null
  currency: string | null
}

export interface ZjmfFinanceCustomField {
  id: string | null
  fieldname: string | null
  fieldtype: string | null
  required: boolean
  description: string | null
  fieldoptions: string | null
}

export interface ZjmfFinanceConfigOption {
  id: string | null
  option_name: string | null
  option_type: string | null
  sub_count: number
  subs: {
    id: string | null
    option_name: string | null
    qty_minimum: number | string | null
    qty_maximum: number | string | null
  }[]
}

export interface ZjmfFinanceConfigGroup {
  id: string | null
  name: string | null
  description: string | null
  options: ZjmfFinanceConfigOption[]
}

export interface ZjmfFinanceProductConfig {
  product: {
    id: string | null
    name: string | null
    type: string | null
    description: string | null
    pay_method: string | null
    stock_control: number | string | null
    qty: number | string | null
    hidden: number | string | null
    retired: number | string | null
  }
  currency: string | null
  cycles: ZjmfFinancePricingCycle[]
  customfields: ZjmfFinanceCustomField[]
  customfield_count: number
  config_groups: ZjmfFinanceConfigGroup[]
  config_group_count: number
  config_option_count: number
  sub_option_count: number
}

export type ProductReadinessLevel = "error" | "warning"
export type ProductReadinessStatus = "pass" | "warning" | "error"

export interface ProductReadinessIssue {
  level: ProductReadinessLevel
  scope: string
  message: string
  suggestion: string | null
}

export interface ProductReadinessProduct {
  product_id: number
  sku: string
  name: string
  status: ProductReadinessStatus
  error_count: number
  warning_count: number
  issues: ProductReadinessIssue[]
}

export interface ProductGroupReadiness {
  group: {
    id: number
    name: string
    slug: string
    area: number | null
    node: number | null
    os_count: number
  }
  status: ProductReadinessStatus
  summary: {
    product_count: number
    active_server_count: number
    error_count: number
    warning_count: number
  }
  issues: ProductReadinessIssue[]
  products: ProductReadinessProduct[]
}

const BASE = "/v1/admin/products"

function arrayValue<T>(value: unknown): T[] {
  return Array.isArray(value) ? value as T[] : []
}

function numberValue(value: unknown): number {
  const n = Number(value ?? 0)
  return Number.isFinite(n) ? n : 0
}

function booleanValue(value: unknown): boolean {
  if (typeof value === "boolean") return value
  if (typeof value === "number") return value !== 0
  const text = String(value ?? "").trim().toLowerCase()
  return text === "1" || text === "true" || text === "yes" || text === "on"
}

function normalizeProvisionPlugin(plugin: ProvisionPluginManifest): ProvisionPluginManifest {
  return {
    ...plugin,
    capabilities: arrayValue<string>(plugin.capabilities),
    manage_actions: arrayValue<ProvisionManageAction>(plugin.manage_actions),
    test_links: arrayValue<ProvisionTestLink>(plugin.test_links),
    upstream_param_fields: arrayValue<ProvisionConfigField>(plugin.upstream_param_fields),
    config_fields: arrayValue<ProvisionConfigField>(plugin.config_fields),
    product_page: plugin.product_page
      ? {
          ...plugin.product_page,
          tabs: arrayValue<ProvisionProductPageTab>(plugin.product_page.tabs),
          purchase_fields: arrayValue<ProvisionPurchaseField>(plugin.product_page.purchase_fields),
        }
      : undefined,
  }
}

function normalizeProvisionInterface(item: ProvisionInterface): ProvisionInterface {
  return {
    ...item,
    config: item.config && typeof item.config === "object" && !Array.isArray(item.config) ? item.config : {},
  }
}

function normalizeProduct(product: Product): Product {
  return {
    ...product,
    auto_provision: booleanValue(product.auto_provision),
    trial_enabled: booleanValue(product.trial_enabled),
    is_featured: booleanValue(product.is_featured),
    requires_real_name: booleanValue(product.requires_real_name),
    pricings: arrayValue<ProductPricing>(product.pricings),
    provision_config: product.provision_config === null ? null : arrayValue<ConfigField>(product.provision_config),
    provision_plugin: product.provision_plugin ? normalizeProvisionPlugin(product.provision_plugin) : product.provision_plugin,
    provision_interface: product.provision_interface ? normalizeProvisionInterface(product.provision_interface) : product.provision_interface,
    product_page: product.product_page
      ? {
          ...product.product_page,
          tabs: arrayValue<ProvisionProductPageTab>(product.product_page.tabs),
          purchase_fields: arrayValue<ProvisionPurchaseField>(product.product_page.purchase_fields),
        }
      : product.product_page,
  }
}

const readinessMessageMap: Record<string, string> = {
  "group has no area/node binding": "产品组未绑定区域或节点",
  "group has no active products": "产品组下没有已上架的产品",
  "product sku/name is incomplete": "产品名称或 SKU 不完整",
  "product has no enabled pricing": "产品没有启用的价格周期",
  "plugin product has no api_identifier": "插件开通产品未选择开通插件",
  "plugin runtime is not enabled": "插件运行时未启用",
  "provision plugin is missing": "绑定的开通插件不存在或不支持开通能力",
  "provision plugin is disabled": "绑定的开通插件未启用",
  "product has no cloud_server_id": "产品未绑定上游接口",
  "bound cloud server is unavailable": "绑定的上游接口不存在或已禁用",
  "product requires a ZJMF finance server": "产品开通方式是 ZJMF 财务，但绑定的上游不是 ZJMF 财务类型",
  "product requires a DCIM cloud server": "产品开通方式是 DCIM 云服务器，但绑定的上游不是 DCIM 类型",
  "image product has no api_identifier": "镜像开通产品未填写镜像 ID 或上游标识",
  "unknown api_type uses plugin fallback at provisioning time": "未知开通方式，实际开通时会尝试走插件兜底",
}

function normalizeReadinessMessage(message: unknown): string {
  const text = String(message ?? "检测项缺少说明")
  return readinessMessageMap[text] ?? text
}

function normalizeReadinessIssue(issue: Partial<ProductReadinessIssue> | null | undefined): ProductReadinessIssue {
  const level = issue?.level === "error" || issue?.level === "warning" ? issue.level : "warning"
  return {
    level,
    scope: String(issue?.scope ?? ""),
    message: normalizeReadinessMessage(issue?.message),
    suggestion: issue?.suggestion === undefined || issue.suggestion === null ? null : String(issue.suggestion),
  }
}

function normalizeReadinessStatus(status: unknown): ProductReadinessStatus {
  if (status === "error" || status === "warning" || status === "pass") return status
  if (status === "ready") return "pass"
  return "warning"
}

function normalizeProductGroupReadiness(value: ProductGroupReadiness): ProductGroupReadiness {
  const legacy = value as ProductGroupReadiness & {
    group_issues?: unknown
    products_active?: unknown
    products_total?: unknown
  }
  const group = value.group ?? {}
  const summary = value.summary ?? {}
  const issuesSource = arrayValue<Partial<ProductReadinessIssue>>(value.issues).length > 0
    ? value.issues
    : legacy.group_issues
  const issues = arrayValue<Partial<ProductReadinessIssue>>(issuesSource).map(normalizeReadinessIssue)
  const products = arrayValue<Partial<ProductReadinessProduct>>(value.products).map((product) => ({
    product_id: numberValue(product.product_id),
    sku: String(product.sku ?? ""),
    name: String(product.name ?? "未命名产品"),
    status: normalizeReadinessStatus(product.status),
    error_count: numberValue(product.error_count),
    warning_count: numberValue(product.warning_count),
    issues: arrayValue<Partial<ProductReadinessIssue>>(product.issues).map(normalizeReadinessIssue),
  }))
  const issueErrorCount = issues.filter((issue) => issue.level === "error").length
  const issueWarningCount = issues.filter((issue) => issue.level === "warning").length
  const productErrorCount = products.reduce((sum, product) => sum + product.error_count, 0)
  const productWarningCount = products.reduce((sum, product) => sum + product.warning_count, 0)
  const errorCount = Math.max(numberValue(summary.error_count), issueErrorCount + productErrorCount)
  const warningCount = Math.max(numberValue(summary.warning_count), issueWarningCount + productWarningCount)
  const reportedStatus = normalizeReadinessStatus(value.status)
  const status: ProductReadinessStatus = errorCount > 0 ? "error" : warningCount > 0 ? "warning" : reportedStatus
  return {
    ...value,
    group: {
      id: numberValue(group.id),
      name: String(group.name ?? "未命名分组"),
      slug: String(group.slug ?? ""),
      area: group.area === null || group.area === undefined ? null : numberValue(group.area),
      node: group.node === null || group.node === undefined ? null : numberValue(group.node),
      os_count: numberValue(group.os_count),
    },
    status,
    summary: {
      product_count: numberValue(summary.product_count) || numberValue(legacy.products_total) || products.length,
      active_server_count: numberValue(summary.active_server_count) || numberValue(legacy.products_active),
      error_count: errorCount,
      warning_count: warningCount,
    },
    issues,
    products,
  }
}

function normalizeZjmfFinanceProductList(value: ZjmfFinanceProductList | null): ZjmfFinanceProductList {
  const data = (value ?? {}) as Partial<ZjmfFinanceProductList>
  return {
    count: numberValue(data.count),
    currency: data.currency ?? null,
    groups: arrayValue<ZjmfFinanceProductGroup>(data.groups).map((group) => ({
      ...group,
      products: arrayValue<ZjmfFinanceProductItem>(group.products),
    })),
    products: arrayValue<ZjmfFinanceProductItem>(data.products),
  }
}

function normalizeZjmfFinanceProductConfig(value: ZjmfFinanceProductConfig | null): ZjmfFinanceProductConfig | null {
  if (!value) return null
  const data = value as Partial<ZjmfFinanceProductConfig>
  return {
    product: {
      id: data.product?.id ?? null,
      name: data.product?.name ?? null,
      type: data.product?.type ?? null,
      description: data.product?.description ?? null,
      pay_method: data.product?.pay_method ?? null,
      stock_control: data.product?.stock_control ?? null,
      qty: data.product?.qty ?? null,
      hidden: data.product?.hidden ?? null,
      retired: data.product?.retired ?? null,
    },
    currency: data.currency ?? null,
    cycles: arrayValue<ZjmfFinancePricingCycle>(data.cycles),
    customfields: arrayValue<ZjmfFinanceCustomField>(data.customfields),
    customfield_count: numberValue(data.customfield_count),
    config_groups: arrayValue<ZjmfFinanceConfigGroup>(data.config_groups).map((group) => ({
      ...group,
      options: arrayValue<ZjmfFinanceConfigOption>(group.options).map((option) => ({
        ...option,
        subs: arrayValue<ZjmfFinanceConfigOption["subs"][number]>(option.subs),
      })),
    })),
    config_group_count: numberValue(data.config_group_count),
    config_option_count: numberValue(data.config_option_count),
    sub_option_count: numberValue(data.sub_option_count),
  }
}

export async function listProducts(groupId?: number) {
  const url = groupId ? `${BASE}?group_id=${groupId}` : BASE
  const { data } = await adminClient.get<ApiResponse<Product[] | { items: Product[]; total: number }>>(url)
  return { ...data, data: listResult<Product>(data.data).map(normalizeProduct) }
}

export async function getProduct(id: number) {
  const { data } = await adminClient.get<ApiResponse<Product>>(`${BASE}/${id}`)
  return { ...data, data: data.data ? normalizeProduct(data.data) : null }
}

export async function createProduct(payload: ProductCreatePayload) {
  const { data } = await adminClient.post<ApiResponse<Product>>(BASE, payload)
  return { ...data, data: data.data ? normalizeProduct(data.data) : null }
}

export async function updateProduct(id: number, payload: ProductUpdatePayload) {
  const { data } = await adminClient.put<ApiResponse<Product>>(`${BASE}/${id}`, payload)
  return { ...data, data: data.data ? normalizeProduct(data.data) : null }
}

export async function deleteProduct(id: number) {
  const { data } = await adminClient.delete<ApiResponse<null>>(`${BASE}/${id}`)
  return data
}

export async function checkProductGroupReadiness(groupId: number) {
  const { data } = await adminClient.get<ApiResponse<ProductGroupReadiness>>(
    `${BASE}/groups/${groupId}/readiness`,
  )
  return { ...data, data: data.data ? normalizeProductGroupReadiness(data.data) : null }
}

export async function listProvisionPlugins() {
  const { data } = await adminClient.get<ApiResponse<ProvisionPluginManifest[] | { items: ProvisionPluginManifest[] }>>(
    `${BASE}/provision-plugins`,
  )
  return { ...data, data: listResult<ProvisionPluginManifest>(data.data).map(normalizeProvisionPlugin) }
}

export async function testProvisionPlugin(pluginId: string, config: Record<string, unknown> = {}) {
  const { data } = await adminClient.post<ApiResponse<Record<string, unknown>>>(
    `${BASE}/provision-plugins/${pluginId}/test`,
    config,
  )
  return data
}

export async function listProvisionInterfaces(pluginId?: string) {
  const { data } = await adminClient.get<ApiResponse<ProvisionInterface[] | { items: ProvisionInterface[] }>>(
    `${BASE}/provision-interfaces`,
    { params: pluginId ? { plugin_id: pluginId } : undefined },
  )
  return { ...data, data: listResult<ProvisionInterface>(data.data).map(normalizeProvisionInterface) }
}

export async function createProvisionInterface(payload: ProvisionInterfacePayload) {
  const { data } = await adminClient.post<ApiResponse<ProvisionInterface>>(
    `${BASE}/provision-interfaces`,
    payload,
  )
  return { ...data, data: data.data ? normalizeProvisionInterface(data.data) : null }
}

export async function updateProvisionInterface(id: number, payload: Partial<ProvisionInterfacePayload>) {
  const { data } = await adminClient.put<ApiResponse<ProvisionInterface>>(
    `${BASE}/provision-interfaces/${id}`,
    payload,
  )
  return { ...data, data: data.data ? normalizeProvisionInterface(data.data) : null }
}

export async function deleteProvisionInterface(id: number) {
  const { data } = await adminClient.delete<ApiResponse<null>>(`${BASE}/provision-interfaces/${id}`)
  return data
}

export async function testProvisionInterface(id: number) {
  const { data } = await adminClient.post<ApiResponse<Record<string, unknown>>>(
    `${BASE}/provision-interfaces/${id}/test`,
  )
  return data
}

export async function listCloudResources(
  kind: "image" | "area",
  cloudServerId: number,
) {
  const { data } = await adminClient.get<ApiResponse<CloudResourceItem[] | { items: CloudResourceItem[] }>>(
    `${BASE}/cloud-resources/${kind}?cloud_server_id=${cloudServerId}`,
  )
  return { ...data, data: listResult<CloudResourceItem>(data.data) }
}

export async function listZjmfFinanceProducts(cloudServerId: number) {
  const { data } = await adminClient.get<ApiResponse<ZjmfFinanceProductList>>(
    `${BASE}/zjmf-finance/products?cloud_server_id=${cloudServerId}`,
  )
  return { ...data, data: normalizeZjmfFinanceProductList(data.data) }
}

export async function getZjmfFinanceProductConfig(cloudServerId: number, pid: string | number) {
  const { data } = await adminClient.get<ApiResponse<ZjmfFinanceProductConfig>>(
    `${BASE}/zjmf-finance/product-config?cloud_server_id=${cloudServerId}&pid=${pid}`,
  )
  return { ...data, data: normalizeZjmfFinanceProductConfig(data.data) }
}
