'use client'

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'

// Query keys
export const twoFactorKeys = {
  all: ['twoFactor'] as const,
  status: () => [...twoFactorKeys.all, 'status'] as const,
}

// Types
export interface TwoFactorStatus {
  enabled: boolean
  enabledAt: string | null
  backupCodesRemaining: number
}

export interface TwoFactorSetupResponse {
  qrCode: string
  secret: string
  otpauthUri: string
}

export interface TwoFactorVerifyResponse {
  enabled: boolean
  backupCodes: string[]
  message: string
}

export interface TwoFactorDisableResponse {
  disabled: boolean
  message: string
}

export interface BackupCodesResponse {
  backupCodes: string[]
  message: string
}

// API functions
async function get2FAStatus(): Promise<TwoFactorStatus> {
  const res = await fetch('/api/v1/auth/2fa/status')
  if (!res.ok) {
    const error = await res.json()
    throw new Error(error.error || 'Failed to get 2FA status')
  }
  return res.json()
}

async function setup2FA(): Promise<TwoFactorSetupResponse> {
  const res = await fetch('/api/v1/auth/2fa/setup', { method: 'POST' })
  if (!res.ok) {
    const error = await res.json()
    throw new Error(error.error || 'Failed to set up 2FA')
  }
  return res.json()
}

async function verify2FA(token: string): Promise<TwoFactorVerifyResponse> {
  const res = await fetch('/api/v1/auth/2fa/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token }),
  })
  if (!res.ok) {
    const error = await res.json()
    throw new Error(error.error || 'Failed to verify 2FA')
  }
  return res.json()
}

async function disable2FA(data: {
  password: string
  token?: string
  backupCode?: string
}): Promise<TwoFactorDisableResponse> {
  const res = await fetch('/api/v1/auth/2fa/disable', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  })
  if (!res.ok) {
    const error = await res.json()
    throw new Error(error.error || 'Failed to disable 2FA')
  }
  return res.json()
}

async function regenerateBackupCodes(password: string): Promise<BackupCodesResponse> {
  const res = await fetch('/api/v1/auth/2fa/backup-codes', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ password }),
  })
  if (!res.ok) {
    const error = await res.json()
    throw new Error(error.error || 'Failed to regenerate backup codes')
  }
  return res.json()
}

// Hooks
export function useTwoFactorStatus() {
  return useQuery({
    queryKey: twoFactorKeys.status(),
    queryFn: get2FAStatus,
  })
}

export function useSetup2FA() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: setup2FA,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: twoFactorKeys.status() })
    },
  })
}

export function useVerify2FA() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: verify2FA,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: twoFactorKeys.status() })
    },
  })
}

export function useDisable2FA() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: disable2FA,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: twoFactorKeys.status() })
    },
  })
}

export function useRegenerateBackupCodes() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: regenerateBackupCodes,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: twoFactorKeys.status() })
    },
  })
}
