/**
 * 资产管理 API 服务
 * 对应文档：asset-detail-refactor-api-changes.md
 */

import { BaseService } from '../BaseService'
import {
  assertAssetActionAllowed,
  markAssetActionCalled,
  type AssetRateLimitedAction
} from '@/utils/business/apiRateLimit'
import type {
  BaseResponse,
  AssetResolveParams,
  AssetResolveResponse,
  AssetRealtimeStatusResponse,
  AssetRefreshResponse,
  AssetPackageListResponse,
  AssetPackageParams,
  AssetCurrentPackageResponse,
  DeviceStopResponse,
  AssetStartResponse,
  AssetWalletTransactionListResponse,
  AssetWalletTransactionParams,
  AssetWalletResponse,
  AssetOrdersParams,
  AssetOrdersResponse,
  UpdateAssetRealnameStatusRequest,
  DtoUpdateAssetRealnameStatusResponse,
  AssetOperationLogsResponse,
  AssetOperationLogsParams,
  AssetPackageUsageRecord,
  UpdateAssetPackageUsedDataRequest,
  UpdateAssetPackageExpiresAtRequest
} from '@/types/api'

const runRateLimitedAssetAction = async <T>(
  action: Exclude<AssetRateLimitedAction, 'refresh'>,
  identifier: string,
  request: () => Promise<T>
): Promise<T> => {
  assertAssetActionAllowed(action, identifier)
  markAssetActionCalled(action, identifier)
  return request()
}

export class AssetService extends BaseService {
  /**
   * 通过任意标识符查询设备或卡的完整详情
   * 支持虚拟号、ICCID、IMEI、SN、MSISDN
   * GET /api/admin/assets/resolve/:identifier
   * @param identifier 资产标识符（虚拟号、ICCID、IMEI、SN、MSISDN）
   * @param params 查询参数
   */
  static resolveAsset(
    identifier: string,
    params?: AssetResolveParams,
    config?: Record<string, any>
  ): Promise<BaseResponse<AssetResolveResponse>> {
    return this.getOne<AssetResolveResponse>(
      `/api/admin/assets/resolve/${identifier}`,
      params,
      config
    )
  }

  /**
   * 读取资产实时状态（直接读 DB/Redis，不调网关）
   * GET /api/admin/assets/:identifier/realtime-status
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   */
  static getRealtimeStatus(identifier: string): Promise<BaseResponse<AssetRealtimeStatusResponse>> {
    return this.getOne<AssetRealtimeStatusResponse>(
      `/api/admin/assets/${identifier}/realtime-status`,
      undefined,
      {
        requestOptions: {
          show404Error: false // 404时不显示错误提示
        }
      }
    )
  }

  /**
   * 主动调网关拉取最新数据后返回
   * POST /api/admin/assets/:identifier/refresh
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   */
  static refreshAsset(identifier: string): Promise<BaseResponse<AssetRefreshResponse>> {
    return this.post<BaseResponse<AssetRefreshResponse>>(
      `/api/admin/assets/${identifier}/refresh`,
      {},
      { timeout: 60000 }
    )
  }

  /**
   * 查询该资产所有套餐记录，含虚流量换算字段（分页）
   * GET /api/admin/assets/:identifier/packages?page=1&page_size=50
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   * @param params 查询参数（可选分页参数）
   */
  static getAssetPackages(
    identifier: string,
    params?: AssetPackageParams
  ): Promise<BaseResponse<AssetPackageListResponse>> {
    return this.get<BaseResponse<AssetPackageListResponse>>(
      `/api/admin/assets/${identifier}/packages`,
      params,
      {
        requestOptions: {
          show404Error: false // 404时不显示错误提示
        }
      }
    )
  }

  /**
   * 查询当前生效中的主套餐
   * GET /api/admin/assets/:identifier/current-package
   * 无生效套餐时返回 404
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   */
  static getCurrentPackage(identifier: string): Promise<BaseResponse<AssetCurrentPackageResponse>> {
    return this.getOne<AssetCurrentPackageResponse>(
      `/api/admin/assets/${identifier}/current-package`,
      undefined,
      {
        requestOptions: {
          show404Error: false // 404时不显示错误提示
        }
      }
    )
  }

  /**
   * 修改套餐真实已用量
   * PATCH /api/admin/assets/:identifier/packages/:package_usage_id/used-data
   */
  static updateAssetPackageUsedData(
    identifier: string,
    packageUsageId: number,
    data: UpdateAssetPackageUsedDataRequest
  ): Promise<BaseResponse<AssetPackageUsageRecord>> {
    return this.patch<BaseResponse<AssetPackageUsageRecord>>(
      `/api/admin/assets/${identifier}/packages/${packageUsageId}/used-data`,
      data as Record<string, any>
    )
  }

  /**
   * 修改套餐过期时间
   * PATCH /api/admin/assets/:identifier/packages/:package_usage_id/expires-at
   */
  static updateAssetPackageExpiresAt(
    identifier: string,
    packageUsageId: number,
    data: UpdateAssetPackageExpiresAtRequest
  ): Promise<BaseResponse<AssetPackageUsageRecord>> {
    return this.patch<BaseResponse<AssetPackageUsageRecord>>(
      `/api/admin/assets/${identifier}/packages/${packageUsageId}/expires-at`,
      data as Record<string, any>
    )
  }

  // ========== 资产停复机操作（统一接口）==========

  /**
   * 停机资产（卡或设备）
   * POST /api/admin/assets/:identifier/stop
   * 停机成功后设置 1 小时停机保护期（保护期内禁止复机）
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   */
  static stopAsset(identifier: string): Promise<BaseResponse<DeviceStopResponse | void>> {
    return runRateLimitedAssetAction('stop', identifier, () =>
      this.post<BaseResponse<DeviceStopResponse | void>>(`/api/admin/assets/${identifier}/stop`, {})
    )
  }

  /**
   * 复机资产（卡或设备）
   * POST /api/admin/assets/:identifier/start
   * 前端按资产标识限制 5 分钟内只能调用一次
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   */
  static startAsset(
    identifier: string,
    config?: Record<string, any>
  ): Promise<BaseResponse<AssetStartResponse>> {
    return runRateLimitedAssetAction('start', identifier, () =>
      this.post<BaseResponse<AssetStartResponse>>(
        `/api/admin/assets/${identifier}/start`,
        {},
        config
      )
    )
  }

  // ========== 资产停用 ==========

  /**
   * 手动停用资产（卡或设备）
   * PATCH /api/admin/assets/:identifier/deactivate
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   */
  static deactivateAsset(identifier: string): Promise<BaseResponse> {
    return this.patch<BaseResponse>(`/api/admin/assets/${identifier}/deactivate`, {})
  }

  // ========== 钱包查询 ==========

  /**
   * 查询指定卡或设备的钱包余额概况
   * GET /api/admin/assets/:identifier/wallet
   * 企业账号禁止调用
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   */
  static getAssetWallet(identifier: string): Promise<BaseResponse<AssetWalletResponse>> {
    return this.getOne<AssetWalletResponse>(`/api/admin/assets/${identifier}/wallet`, undefined, {
      requestOptions: {
        show404Error: false // 404时不显示错误提示
      }
    })
  }

  /**
   * 分页查询指定资产的钱包收支流水
   * GET /api/admin/assets/:identifier/wallet/transactions
   * 企业账号禁止调用
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   * @param params 查询参数
   */
  static getWalletTransactions(
    identifier: string,
    params?: AssetWalletTransactionParams
  ): Promise<BaseResponse<AssetWalletTransactionListResponse>> {
    return this.get<BaseResponse<AssetWalletTransactionListResponse>>(
      `/api/admin/assets/${identifier}/wallet/transactions`,
      params
    )
  }

  // ========== 轮询状态更新 ==========

  /**
   * 更新资产轮询状态
   * PATCH /api/admin/assets/:identifier/polling-status
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   * @param data 轮询状态数据
   */
  static updatePollingStatus(
    identifier: string,
    data: { enable_polling: boolean }
  ): Promise<BaseResponse> {
    return this.patch<BaseResponse>(`/api/admin/assets/${identifier}/polling-status`, data)
  }

  // ========== 资产历史订单 ==========

  /**
   * 查询资产历史订单
   * GET /api/admin/assets/:identifier/orders
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   * @param params 查询参数
   */
  static getAssetOrders(
    identifier: string,
    params?: AssetOrdersParams
  ): Promise<BaseResponse<AssetOrdersResponse>> {
    return this.get<BaseResponse<AssetOrdersResponse>>(
      `/api/admin/assets/${identifier}/orders`,
      params
    )
  }

  /**
   * 更新资产实名认证策略
   * PATCH /api/admin/assets/:identifier/realname-mode
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   * @param realname_policy 实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)
   */
  static updateRealnamePolicy(identifier: string, realname_policy: string): Promise<BaseResponse> {
    return this.patch<BaseResponse>(`/api/admin/assets/${identifier}/realname-mode`, {
      realname_policy
    })
  }

  /**
   * 手动更新资产实名状态
   * PATCH /api/admin/assets/:identifier/realname-status
   * @param identifier 资产标识符（ICCID 或 VirtualNo）
   * @param data 实名状态数据
   */
  static updateRealnameStatus(
    identifier: string,
    data: UpdateAssetRealnameStatusRequest
  ): Promise<BaseResponse<DtoUpdateAssetRealnameStatusResponse>> {
    return this.patch<BaseResponse<DtoUpdateAssetRealnameStatusResponse>>(
      `/api/admin/assets/${identifier}/realname-status`,
      data
    )
  }

  // ========== 资产操作审计日志 ==========

  /**
   * 查询资产操作审计日志
   * GET /api/admin/assets/:identifier/operation-logs
   * @param identifier 资产标识符
   * @param params 查询参数
   */
  static getOperationLogs(
    identifier: string,
    params?: AssetOperationLogsParams
  ): Promise<BaseResponse<AssetOperationLogsResponse>> {
    return this.get<BaseResponse<AssetOperationLogsResponse>>(
      `/api/admin/assets/${identifier}/operation-logs`,
      params
    )
  }
}
