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

export const MINI_AUTH_STORAGE_KEY = 'miniAuth'

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

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

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,
  })
}

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
    },
  },
})
