/* eslint-disable react-refresh/only-export-components */
import React, { createContext, useContext, useEffect, useState } from 'react'
import { AppwriteException } from 'appwrite'
import { auth } from '@/lib/appwrite'
import type { Models } from 'appwrite'

function mapLoginError(err: unknown): Error {
  if (err instanceof AppwriteException) {
    const type = (err.type || '').toLowerCase()
    const msg = (err.message || '').toLowerCase()
    if (type.includes('user_blocked') || msg.includes('blocked')) {
      return new Error('Dieser Account ist gesperrt. Bitte Support kontaktieren.')
    }
    if (err.code === 401) {
      return new Error(
        'Anmeldung fehlgeschlagen. Häufige Ursachen: falsches Passwort; User wurde nur in der Console angelegt ohne Passwort; E-Mail/Passwort-Login ist im Appwrite-Projekt deaktiviert; oder die VITE_APPWRITE_PROJECT_ID passt nicht zu dem Projekt, in dem der User liegt.'
      )
    }
    if (err.message) {
      return new Error(err.message)
    }
  }
  if (err instanceof Error) {
    return err
  }
  return new Error('Login fehlgeschlagen.')
}

interface AuthContextType {
  user: Models.User<Models.Preferences> | null
  loading: boolean
  login: (email: string, password: string) => Promise<void>
  register: (email: string, password: string, name?: string) => Promise<void>
  logout: () => Promise<void>
  refreshUser: () => Promise<void>
}

const AuthContext = createContext<AuthContextType | undefined>(undefined)

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<Models.User<Models.Preferences> | null>(null)
  const [loading, setLoading] = useState(true)

  const refreshUser = async () => {
    try {
      const currentUser = await auth.getCurrentUser()
      setUser(currentUser)
    } catch {
      setUser(null)
    }
  }

  useEffect(() => {
    const init = async () => {
      await refreshUser()
      setLoading(false)
    }
    init()
  }, [])

  const login = async (email: string, password: string) => {
    try {
      await auth.login(email, password)
      await refreshUser()
    } catch (e) {
      throw mapLoginError(e)
    }
  }

  const register = async (email: string, password: string, name?: string) => {
    try {
      await auth.register(email, password, name)
      await refreshUser()
    } catch (e) {
      throw mapLoginError(e)
    }
  }

  const logout = async () => {
    await auth.logout()
    setUser(null)
  }

  return (
    <AuthContext.Provider
      value={{
        user,
        loading,
        login,
        register,
        logout,
        refreshUser,
      }}
    >
      {children}
    </AuthContext.Provider>
  )
}

export function useAuth() {
  const context = useContext(AuthContext)
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider')
  }
  return context
}
