import { defineStore, getActivePinia } from 'pinia'
import type { MiniUserProfile } from '@/types/auth'

export const MINI_AUTH_STORAGE_KEY = 'miniAuth'
export const MINI_PROFILE_PREFILL_STORAGE_KEY = 'miniProfilePrefill'

export interface MiniAuthState {
  token: string
  profile: MiniUserProfile | null
}

export interface MiniAuthUiState {
  loginPromptVisible: boolean
  needPhoneAuthorize: boolean
  authPromptMessage: string
}

export interface MiniProfilePrefillState {
  nickName: string
  avatarUrl: string | null
}

type MiniAuthStoreState = MiniAuthState & MiniAuthUiState

function createInitialState(): MiniAuthState {
  return {
    token: '',
    profile: null,
  }
}

function createInitialUiState(): MiniAuthUiState {
  return {
    loginPromptVisible: false,
    needPhoneAuthorize: false,
    authPromptMessage: '',
  }
}

function isValidProfile(value: unknown): value is MiniUserProfile {
  if (!value || typeof value !== 'object') {
    return false
  }
  return typeof (value as MiniUserProfile).mpUserId === 'number'
}

export function getPersistedAuthState(): MiniAuthState {
  const state = uni.getStorageSync(MINI_AUTH_STORAGE_KEY) as Partial<MiniAuthState> | undefined
  return {
    token: typeof state?.token === 'string' ? state.token : '',
    profile: isValidProfile(state?.profile) ? state.profile : null,
  }
}

export function getPersistedToken(): string {
  return getPersistedAuthState().token
}

function writePersistedAuthState(state: MiniAuthState) {
  uni.setStorageSync(MINI_AUTH_STORAGE_KEY, state)
}

function patchActiveStore(state: Partial<MiniAuthStoreState>) {
  const pinia = getActivePinia()
  if (!pinia) {
    return
  }
  const store = useMiniAuthStore(pinia)
  store.$patch(state)
}

export function clearMiniAuthSession() {
  const state = createInitialState()
  uni.removeStorageSync(MINI_AUTH_STORAGE_KEY)
  patchActiveStore({
    ...state,
    ...createInitialUiState(),
  })
}

export function updateMiniAuthProfile(profile: MiniUserProfile) {
  const state = {
    ...getPersistedAuthState(),
    profile,
  }
  writePersistedAuthState(state)
  patchActiveStore(state)
}

export function showMiniLoginPrompt(message = '') {
  patchActiveStore({
    loginPromptVisible: true,
    authPromptMessage: message,
  })
}

export function hideMiniLoginPrompt() {
  patchActiveStore({
    loginPromptVisible: false,
    authPromptMessage: '',
    needPhoneAuthorize: false,
  })
}

export function setMiniPhoneAuthorizeRequired(required: boolean) {
  patchActiveStore({
    needPhoneAuthorize: required,
  })
}

function isValidProfilePrefill(value: unknown): value is MiniProfilePrefillState {
  if (!value || typeof value !== 'object') {
    return false
  }
  return typeof (value as MiniProfilePrefillState).nickName === 'string'
}

export function setMiniProfilePrefill(prefill: MiniProfilePrefillState) {
  uni.setStorageSync(MINI_PROFILE_PREFILL_STORAGE_KEY, prefill)
}

export function getMiniProfilePrefill(): MiniProfilePrefillState | null {
  const value = uni.getStorageSync(MINI_PROFILE_PREFILL_STORAGE_KEY) as Partial<MiniProfilePrefillState> | undefined
  if (!isValidProfilePrefill(value)) {
    return null
  }
  return {
    nickName: value.nickName.trim(),
    avatarUrl: typeof value.avatarUrl === 'string' && value.avatarUrl.trim()
      ? value.avatarUrl.trim()
      : null,
  }
}

export function clearMiniProfilePrefill() {
  uni.removeStorageSync(MINI_PROFILE_PREFILL_STORAGE_KEY)
}

export const useMiniAuthStore = defineStore('miniAuth', {
  state: (): MiniAuthStoreState => ({
    ...createInitialState(),
    ...createInitialUiState(),
  }),
  getters: {
    isLoggedIn: state => Boolean(state.token),
  },
  actions: {
    setSession(payload: MiniAuthState) {
      this.token = payload.token
      this.profile = payload.profile
      this.loginPromptVisible = false
      this.needPhoneAuthorize = false
      this.authPromptMessage = ''
      writePersistedAuthState({
        token: payload.token,
        profile: payload.profile,
      })
    },
    setProfile(profile: MiniUserProfile) {
      this.profile = profile
      writePersistedAuthState({
        token: this.token,
        profile,
      })
    },
    clearSession() {
      this.token = ''
      this.profile = null
      this.loginPromptVisible = false
      this.needPhoneAuthorize = false
      this.authPromptMessage = ''
      uni.removeStorageSync(MINI_AUTH_STORAGE_KEY)
    },
    restoreSession() {
      const state = getPersistedAuthState()
      this.token = state.token
      this.profile = state.profile
      return state
    },
    showLoginPrompt(message = '') {
      this.loginPromptVisible = true
      this.authPromptMessage = message
    },
    hideLoginPrompt() {
      this.loginPromptVisible = false
      this.needPhoneAuthorize = false
      this.authPromptMessage = ''
    },
    setNeedPhoneAuthorize(required: boolean) {
      this.needPhoneAuthorize = required
    },
  },
})
