import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import Swal from 'sweetalert2'
import { useAuthStore } from '@/stores/auth'
import { getApiErrorMessage } from '@/core/utils/getApiErrorMessage'
import { resolvePostLoginRoute } from '@/modules/auth'
import { leaveImpersonation, takeImpersonation } from '../services/impersonate.service'
import type { UserListItem } from '../types/user.types'

const IMPERSONATE_PERMISSION = 'menyamar pengguna'
const DEVELOPER_ROLE = 'DEVELOPER'

function userCanImpersonate(): boolean {
  const authStore = useAuthStore()
  const roles = authStore.user?.roles ?? []

  if (roles.some((role) => role.name === DEVELOPER_ROLE)) {
    return true
  }

  const activeRole = authStore.activeRole
  const roleWithPermissions = roles.find((role) => role.id === activeRole?.id)

  return (
    roleWithPermissions?.permissions?.some(
      (permission) => permission.name === IMPERSONATE_PERMISSION,
    ) ?? false
  )
}

function isImpersonateTargetVisible(target: UserListItem, currentUserId?: string): boolean {
  if (!currentUserId || target.id === currentUserId) {
    return false
  }

  return !target.roles?.some((role) => role.name === DEVELOPER_ROLE)
}

function targetCanBeImpersonated(target: UserListItem, currentUserId?: string): boolean {
  if (!isImpersonateTargetVisible(target, currentUserId)) {
    return false
  }

  return target.status === 'active'
}

export function useImpersonate() {
  const authStore = useAuthStore()
  const router = useRouter()
  const loading = ref(false)

  const impersonating = computed(() => authStore.isImpersonating)
  const canImpersonate = computed(() => userCanImpersonate())

  function showImpersonateButton(target: UserListItem): boolean {
    return canImpersonate.value && isImpersonateTargetVisible(target, authStore.user?.id)
  }

  function canImpersonateUser(target: UserListItem): boolean {
    return canImpersonate.value && targetCanBeImpersonated(target, authStore.user?.id)
  }

  function impersonateButtonTitle(target: UserListItem): string {
    if (impersonating.value) {
      return 'Anda sedang menyamar pengguna'
    }

    if (target.status !== 'active') {
      return 'Hanya pengguna aktif boleh disamar'
    }

    return 'Menyamar sebagai pengguna'
  }

  async function refreshImpersonationStatus() {
    await authStore.refreshImpersonationStatus()
  }

  async function impersonateUser(target: UserListItem) {
    if (!canImpersonateUser(target) || loading.value || impersonating.value) {
      return
    }

    const result = await Swal.fire({
      title: 'Menyamar pengguna?',
      text: `Anda akan log masuk sebagai "${target.name}".`,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonText: 'Ya, menyamar',
      cancelButtonText: 'Batal',
      reverseButtons: true,
    })

    if (!result.isConfirmed) {
      return
    }

    loading.value = true

    try {
      const response = await takeImpersonation(target.id)
      authStore.applySession(response)
      authStore.isImpersonating = true

      await Swal.fire({
        toast: true,
        position: 'top-end',
        icon: 'success',
        title: response.message,
        showConfirmButton: false,
        showCloseButton: true,
        timer: 2000,
      })

      await router.push(resolvePostLoginRoute(response.redirect_path))
    } catch (error) {
      await Swal.fire({
        icon: 'error',
        title: 'Gagal menyamar',
        text: getApiErrorMessage(error, 'Tidak dapat menyamar sebagai pengguna ini.'),
      })
    } finally {
      loading.value = false
    }
  }

  async function stopImpersonation() {
    if (!impersonating.value || loading.value) {
      return
    }

    loading.value = true

    try {
      const response = await leaveImpersonation()
      authStore.applySession(response)
      authStore.isImpersonating = false

      await Swal.fire({
        toast: true,
        position: 'top-end',
        icon: 'success',
        title: response.message,
        showConfirmButton: false,
        showCloseButton: true,
        timer: 2000,
      })

      await router.push(resolvePostLoginRoute(response.redirect_path))
    } catch (error) {
      await Swal.fire({
        icon: 'error',
        title: 'Gagal tamatkan penyamaran',
        text: getApiErrorMessage(error, 'Tidak dapat kembali ke akaun asal.'),
      })
    } finally {
      loading.value = false
    }
  }

  return {
    canImpersonate,
    showImpersonateButton,
    canImpersonateUser,
    impersonateButtonTitle,
    impersonating,
    loading,
    refreshImpersonationStatus,
    impersonateUser,
    stopImpersonation,
  }
}
