import axios, { type AxiosProgressEvent } from 'axios'
import { isJwtExpired } from '@/utils/jwt'

const updateClient = axios.create({
  baseURL: import.meta.env.VITE_UPDATE_API_BASE_URL ?? '',
  timeout: 30000,
})

type UploadProgressHandler = (percent: number) => void

function uploadProgressConfig(onProgress?: UploadProgressHandler) {
  if (!onProgress) return {}
  return {
    onUploadProgress: (event: AxiosProgressEvent) => {
      const total = event.total ?? 0
      if (!total) return
      onProgress(Math.min(100, Math.round((event.loaded * 100) / total)))
    },
  }
}

if (import.meta.env.DEV) {
  updateClient.interceptors.request.use((config) => {
    console.debug('[tenant-platform][UPDATE] request', {
      method: config.method?.toUpperCase(),
      url: config.baseURL ? `${config.baseURL}${config.url ?? ''}` : config.url,
      params: config.params,
    })
    return config
  })
  updateClient.interceptors.response.use((res) => {
    console.debug('[tenant-platform][UPDATE] response', {
      status: res.status,
      url: res.config.url,
    })
    return res
  })
}

updateClient.interceptors.request.use((config) => {
  const url = config.url ?? ''
  const skipAuth = (
    url.startsWith('/api/v1/updates/app/check') ||
    url.startsWith('/api/v1/updates/app/inspect') ||
    url.startsWith('/api/v1/updates/public/') ||
    url.startsWith('/api/v1/rn/release-set/check') ||
    url.startsWith('/api/v1/rn/files/')
  )
  if (!skipAuth) {
    const token = localStorage.getItem('token')
    if (token && !isJwtExpired(token)) {
      config.headers.Authorization = `Bearer ${token}`
    } else if (token && isJwtExpired(token)) {
      localStorage.removeItem('token')
      if (typeof window !== 'undefined' && window.location.pathname !== '/login') {
        window.location.href = `/login?reason=${encodeURIComponent('登录已失效，请重新登录')}`
      }
      return Promise.reject(new Error('登录已失效，请重新登录'))
    }
  }
  return config
})

updateClient.interceptors.response.use(
  (response) => response,
  (error) => {
    const status = error?.response?.status
    if (status === 401) {
      localStorage.removeItem('token')
      if (typeof window !== 'undefined' && window.location.pathname !== '/login') {
        window.location.href = `/login?reason=${encodeURIComponent('登录已失效，请重新登录')}`
      }
      return Promise.reject(error)
    }
    if (status === 403) {
      return Promise.reject(error)
    }
    return Promise.reject(error)
  },
)

export type StoreType = 'HUAWEI' | 'MI' | 'OPPO' | 'VIVO' | 'HONOR' | 'APP_STORE' | 'GOOGLE_PLAY' | 'HARMONY_APP' | 'REVIEW_WEBHOOK'
export type StoreReviewState = 'PENDING' | 'SUBMITTING' | 'UNDER_REVIEW' | 'APPROVED' | 'REJECTED'
export type PublishMode = 'MANUAL' | 'NOW' | 'SCHEDULED' | 'AUTO_REVIEW'
export type GrayMode = 'PERCENT' | 'MEMBERS'

export interface PublishConfig {
  id: string
  appKey: string
  configJson?: string
  updatedAt: string
  allowAnonymousUpdateCheck?: boolean
}

export interface OperationLog {
  id: string
  appKey: string
  resourceType: string
  resourceId: string
  action: string
  operator?: string
  reason?: string
  detailJson?: string
  createdAt: string
}

export interface GrayMember {
  userId: string
  name: string
  source: 'SYNC' | 'MANUAL'
  active: boolean
  tags: string[]
}

export interface GrayTag {
  tagName: string
  memberCount: number
}

export interface StoreConfig {
  id: string
  appKey: string
  storeType: StoreType
  configJson?: string
  enabled: boolean
  updatedAt: string
}

export interface AppVersion {
  id: string
  appKey: string
  platform: 'ANDROID' | 'IOS' | 'HARMONY'
  versionName: string
  versionCode: number
  packageName?: string
  downloadUrl?: string
  changeLog?: string
  forceUpdate: boolean
  publishStatus: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
  grayEnabled: boolean
  grayPercent: number
  appStoreUrl?: string
  marketUrl?: string
  scheduledPublishAt?: string
  autoPublishAfterReview: boolean
  webhookUrl?: string
  storeSubmitTargets?: string
  storeReviewStatus?: string
  storeSubmitMode?: PublishMode
  storeSubmitScheduledAt?: string
  grayMode?: GrayMode
  grayMemberIds?: string
  createdAt: string
}

export interface StoreRemoteStateDto {
  storeType: StoreType
  reviewState: 'ONLINE' | 'UNDER_REVIEW' | 'UNDER_REVIEW_XIAOMI' | 'REJECTED' | 'NOT_FOUND' | 'UNKNOWN' | 'QUERY_FAILED'
  onlineVersionName?: string
  onlineVersionCode?: string
  reviewVersionName?: string
  reviewVersionCode?: string
  currentSubmissionLive: boolean
  nonCurrentRelease: boolean
  canSubmit: boolean
  blockReason?: string
}

export interface PreflightSubmitResultDto {
  versionId: string
  versionName: string
  versionCode: number
  stores: StoreRemoteStateDto[]
}

export interface AppPackageInspectResult {
  platform: 'ANDROID' | 'IOS' | 'HARMONY'
  packageName?: string
  versionName?: string
  versionCode?: number
  fileName?: string
  detected: boolean
}

export interface RnBundle {
  id: string
  appKey: string
  packageName: string
  moduleId: string
  type: 'common' | 'app' | 'buz'
  platform: 'ANDROID' | 'IOS'
  version: string
  appVersionRange: string
  builtAgainstNativeBaselineId: string
  buildId: string
  bundleFormat: string
  commonVersionRange?: string
  minNativeApiLevel: number
  bundleSha256: string
  archiveSha256: string
  keyId: string
  signature: string
  note?: string
  publishStatus: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
  publishMode?: PublishMode
  scheduledPublishAt?: string
  grayEnabled: boolean
  grayPercent: number
  grayMode?: GrayMode
  grayMemberIds?: string
  createdAt: string
}

export interface UnifiedAppUploadItem {
  fileKey: string
  platform: 'ANDROID' | 'IOS' | 'HARMONY'
  versionName: string
  versionCode: number
  changeLog?: string
  forceUpdate: boolean
  packageName?: string
  appStoreUrl?: string
  marketUrl?: string
  publishImmediately: boolean
}

export interface UnifiedReleaseManifest {
  appVersions: UnifiedAppUploadItem[]
}

export interface DownloadPageHistoryItem {
  versionName: string
  versionCode: number
  downloadUrl?: string
  available: boolean
  changeLog?: string
  publishedAt: string
  current: boolean
}

export interface DownloadPageAppInfo {
  versionName: string
  versionCode: number
  downloadUrl?: string
  available?: boolean
  changeLog?: string
  storeUrl?: string
  storeLinks?: Record<string, string>
  publishedAt: string
  history?: DownloadPageHistoryItem[]
}

export interface DownloadPageInfo {
  android: DownloadPageAppInfo | null
  ios: DownloadPageAppInfo | null
  harmony: DownloadPageAppInfo | null
}

export function fetchDownloadPageInfo(appKey: string) {
  return updateClient.get<{ data: DownloadPageInfo }>('/api/v1/updates/public/download-info', {
    params: { appKey },
  })
}

export const updateAdminApi = {
  listAppVersions(appKey: string, platform: 'ANDROID' | 'IOS' | 'HARMONY') {
    return updateClient.get<{ data: AppVersion[] }>('/api/v1/updates/app/list', {
      params: { appKey, platform },
    })
  },

  publishAppVersion(id: string, body?: { publishImmediately?: boolean; scheduledPublishAt?: string; forceUpdate?: boolean }) {
    return updateClient.post(`/api/v1/updates/app/${id}/publish`, body ?? {})
  },

  unpublishAppVersion(id: string, reason: string) {
    return updateClient.post(`/api/v1/updates/app/${id}/unpublish`, { reason })
  },

  patchChangeLog(id: string, changeLog: string) {
    return updateClient.patch<{ data: AppVersion }>(`/api/v1/updates/app/${id}/changelog`, { changeLog })
  },

  grayAppVersion(id: string, body: {
    enabled: boolean
    grayMode: GrayMode
    percent?: number
    groupNames?: string[]
    extraMemberIds?: string[]
  }) {
    return updateClient.post(`/api/v1/updates/app/${id}/gray`, body)
  },

  uploadAppVersion(formData: FormData, onProgress?: UploadProgressHandler) {
    return updateClient.post<{ data: AppVersion }>('/api/v1/updates/app/upload', formData, uploadProgressConfig(onProgress))
  },

  inspectAppPackage(apkUrl: string) {
    return updateClient.get<{ data: AppPackageInspectResult }>('/api/v1/updates/app/inspect', {
      params: { apkUrl },
    })
  },

  listRnBundles(appKey: string, moduleId?: string, platform?: string) {
    return updateClient.get<{ data: RnBundle[] }>('/api/v1/rn/list', {
      params: { appKey, ...(moduleId && { moduleId }), ...(platform && { platform }) },
    })
  },

  publishRnBundle(id: string, body?: { publishImmediately?: boolean; scheduledPublishAt?: string }) {
    return updateClient.post(`/api/v1/rn/${id}/publish`, body ?? {})
  },

  unpublishRnBundle(id: string, reason: string) {
    return updateClient.post(`/api/v1/rn/${id}/unpublish`, { reason })
  },

  grayRnBundle(id: string, body: {
    enabled: boolean
    grayMode: GrayMode
    percent?: number
    groupNames?: string[]
    extraMemberIds?: string[]
  }) {
    return updateClient.post(`/api/v1/rn/${id}/gray`, body)
  },

  uploadRnBundle(formData: FormData, onProgress?: UploadProgressHandler) {
    return updateClient.post<{ data: RnBundle }>('/api/v1/rn/upload', formData, uploadProgressConfig(onProgress))
  },

  uploadUnifiedRelease(formData: FormData, onProgress?: UploadProgressHandler) {
    return updateClient.post('/api/v1/updates/unified/upload', formData, uploadProgressConfig(onProgress))
  },

  // ── Store config ────────────────────────────────────────────────────────

  getStoreConfigs(appKey: string) {
    return updateClient.get<{ data: StoreConfig[] }>('/api/v1/updates/store/configs', { params: { appKey } })
  },

  saveStoreConfig(appKey: string, storeType: StoreType, configJson: string, enabled: boolean) {
    return updateClient.put<{ data: StoreConfig }>(
      `/api/v1/updates/store/configs/${storeType}`,
      { configJson, enabled },
      { params: { appKey } },
    )
  },

  deleteStoreConfig(appKey: string, storeType: StoreType) {
    return updateClient.delete(`/api/v1/updates/store/configs/${storeType}`, { params: { appKey } })
  },

  executeSubmitToStores(
    versionId: string,
    storeTypes: StoreType[],
    submitMode: PublishMode = 'MANUAL',
    scheduledPublishAt?: string,
    autoPublishAfterReview = false,
  ) {
    return updateClient.post<{ data: AppVersion }>(
      `/api/v1/updates/store/app/${versionId}/execute-submit`,
      { storeTypes, submitMode, scheduledPublishAt, autoPublishAfterReview },
    )
  },

  updateStoreReview(versionId: string, storeType: StoreType, state: StoreReviewState, reason?: string) {
    return updateClient.post<{ data: AppVersion }>(
      `/api/v1/updates/store/app/${versionId}/review`,
      { storeType, state, ...(reason ? { reason } : {}) },
    )
  },

  cancelStoreReview(versionId: string, storeTypes?: StoreType[]) {
    return updateClient.post<{ data: null }>(
      `/api/v1/updates/store/app/${versionId}/cancel-review`,
      storeTypes ? { storeTypes } : {},
    )
  },

  preflightStoreSubmission(versionId: string) {
    return updateClient.post<{ data: PreflightSubmitResultDto }>(
      `/api/v1/updates/store/app/${versionId}/preflight-submit`,
      {},
    )
  },

  refreshStoreReviewStatus(versionId: string) {
    return updateClient.post<{ data: PreflightSubmitResultDto }>(
      `/api/v1/updates/store/app/${versionId}/refresh-review-status`,
      {},
    )
  },

  deleteAppVersion(versionId: string) {
    return updateClient.delete<{ data: null }>(`/api/v1/updates/app/${versionId}`)
  },

  updatePublishSchedule(
    versionId: string,
    publishType: 'IMMEDIATE' | 'SCHEDULED',
    scheduledAt?: string,
  ) {
    return updateClient.put<{ data: AppVersion }>(
      `/api/v1/updates/store/app/${versionId}/publish-schedule`,
      { publishType, scheduledAt },
    )
  },

  getPublishConfig(appKey: string) {
    return updateClient.get<{ data: PublishConfig }>('/api/v1/updates/publish/config', { params: { appKey } })
  },

  savePublishConfig(appKey: string, config: Record<string, unknown>) {
    return updateClient.put<{ data: PublishConfig }>('/api/v1/updates/publish/config', config, { params: { appKey } })
  },

  listOperationLogs(appKey: string, limit = 100) {
    return updateClient.get<{ data: OperationLog[] }>('/api/v1/updates/ops/logs', {
      params: { appKey, limit },
    })
  },

  listGrayMembers(appKey: string) {
    return updateClient.get<{ data: GrayMember[] }>('/api/v1/updates/gray/members', {
      params: { appKey },
    })
  },

  addGrayMembers(appKey: string, userIds: string[], name?: string) {
    return updateClient.post('/api/v1/updates/gray/members', { appKey, userIds, name })
  },

  deleteGrayMember(appKey: string, userId: string) {
    return updateClient.delete(`/api/v1/updates/gray/members/${userId}`, { params: { appKey } })
  },

  syncGrayMembers(appKey: string, members: { userId: string; name?: string }[]) {
    return updateClient.post<{ data: { added: number; updated: number; removed: number } }>(
      '/api/v1/updates/gray/members/sync', { appKey, members })
  },

  importGrayMembersFromIm(appKey: string) {
    return updateClient.post<{ data: { added: number; updated: number; removed: number } }>(
      '/api/v1/updates/gray/members/import-im', null, { params: { appKey } })
  },

  listGrayTags(appKey: string) {
    return updateClient.get<{ data: GrayTag[] }>('/api/v1/updates/gray/tags', { params: { appKey } })
  },

  createGrayTag(appKey: string, tagName: string, userIds: string[]) {
    return updateClient.post('/api/v1/updates/gray/tags', { appKey, tagName, userIds })
  },

  deleteGrayTag(appKey: string, tagName: string) {
    return updateClient.delete(`/api/v1/updates/gray/tags/${tagName}`, { params: { appKey } })
  },

  addMembersToTag(appKey: string, tagName: string, userIds: string[]) {
    return updateClient.post(`/api/v1/updates/gray/tags/${tagName}/members`, { appKey, userIds })
  },

  removeMembersFromTag(appKey: string, tagName: string, userIds: string[]) {
    return updateClient.delete(`/api/v1/updates/gray/tags/${tagName}/members`, { data: { appKey, userIds } })
  },

  // ── Statistics ─────────────────────────────────────────────────────────

  getVersionDistribution(appKey: string, platform: string, days?: number) {
    return updateClient.get<{ data: { versionCode: number; versionName: string; deviceCount: number }[] }>(
      '/api/v1/updates/stats/version-distribution',
      { params: { appKey, platform, days: days ?? 30 } },
    )
  },

  getDeviceDistribution(appKey: string, platform: string, days?: number) {
    return updateClient.get<{
      data: {
        models: { model: string; deviceCount: number }[]
        osVersions: { osVersion: string; deviceCount: number }[]
        vendors: { vendor: string; deviceCount: number }[]
      }
    }>('/api/v1/updates/stats/device-distribution', { params: { appKey, platform, days: days ?? 30 } })
  },

  getDailyTrend(appKey: string, platform: string, days?: number) {
    return updateClient.get<{ data: { day: string; deviceCount: number }[] }>(
      '/api/v1/updates/stats/daily-trend',
      { params: { appKey, platform, days: days ?? 7 } },
    )
  },
}
