# Authentication Utilities Guide

## 🎯 Overview

All authentication-related code has been **centralized** in `src/lib/auth.ts` to avoid hardcoding, ensure consistency, and prevent common errors like JSON parsing failures.

---

## ✅ Problem Solved

### Before (Hardcoded)
```typescript
// ❌ Scattered throughout components
const userData = localStorage.getItem('adminUser')
if (userData) {
  setUser(JSON.parse(userData))  // Can crash if userData is "undefined"
}

// ❌ Hardcoded storage keys
localStorage.setItem('adminToken', token)
localStorage.setItem('adminUser', JSON.stringify(user))

// ❌ Duplicate role mapping logic
const roleMap = { 'ADMINISTRATOR': 'System Administrator', ... }
```

**Issues:**
- ❌ JSON parsing crashes on invalid data
- ❌ Hardcoded storage keys (typo-prone)
- ❌ Duplicate code across components
- ❌ No type safety
- ❌ Difficult to maintain

### After (Centralized)
```typescript
// ✅ Safe, typed, centralized
import { getAdminUser, setAdminAuth, getRoleDisplayName } from '@/lib/auth'

const user = getAdminUser()  // Returns null if invalid, never crashes
setAdminAuth({ token, user })  // Consistent storage
const roleName = getRoleDisplayName(user?.role)  // Consistent formatting
```

**Benefits:**
- ✅ Safe JSON parsing (never crashes)
- ✅ Type-safe with TypeScript
- ✅ Single source of truth
- ✅ Easy to maintain
- ✅ Consistent behavior

---

## 📚 Available Functions

### 1. **getAdminUser()**
Get the currently logged-in admin user.

```typescript
import { getAdminUser } from '@/lib/auth'

const user = getAdminUser()
// Returns: AdminUser | null

if (user) {
  console.log(user.firstName, user.lastName)
  console.log(user.role)
  console.log(user.email)
}
```

**Features:**
- ✅ Safe JSON parsing (returns null on error)
- ✅ Handles "undefined" string from localStorage
- ✅ Type-safe return value
- ✅ SSR-safe (checks for window)

---

### 2. **getAdminToken()**
Get the JWT authentication token.

```typescript
import { getAdminToken } from '@/lib/auth'

const token = getAdminToken()
// Returns: string | null

if (token) {
  // Use token in API calls
  fetch('/api/endpoint', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  })
}
```

**Features:**
- ✅ Handles "undefined" string
- ✅ Returns null if invalid
- ✅ SSR-safe

---

### 3. **setAdminAuth(data)**
Store authentication data after login.

```typescript
import { setAdminAuth } from '@/lib/auth'

// After successful login
const response = await fetch('/api/auth/login', { ... })
const result = await response.json()

setAdminAuth({
  token: result.data.token,
  user: result.data.user
})
```

**Features:**
- ✅ Stores both token and user
- ✅ Consistent storage keys
- ✅ Error handling
- ✅ Type-safe parameters

---

### 4. **updateAdminUser(user)**
Update user data (after profile changes).

```typescript
import { updateAdminUser } from '@/lib/auth'

// After updating profile
updateAdminUser({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john.doe@example.com'
})
```

**Features:**
- ✅ Merges with existing data
- ✅ Preserves unchanged fields
- ✅ Type-safe

---

### 5. **clearAdminAuth()**
Logout and clear all auth data.

```typescript
import { clearAdminAuth } from '@/lib/auth'

const handleLogout = () => {
  clearAdminAuth()
  router.push('/admin')
}
```

**Features:**
- ✅ Removes token and user
- ✅ Error handling
- ✅ Clean logout

---

### 6. **isAuthenticated()**
Check if user is logged in.

```typescript
import { isAuthenticated } from '@/lib/auth'

useEffect(() => {
  if (!isAuthenticated()) {
    router.push('/admin')
  }
}, [])
```

**Features:**
- ✅ Checks both token and user
- ✅ Boolean return
- ✅ Fast check

---

### 7. **hasRole(role)**
Check if user has specific role(s).

```typescript
import { hasRole } from '@/lib/auth'

// Single role
if (hasRole('ADMINISTRATOR')) {
  // Show admin features
}

// Multiple roles
if (hasRole(['ADMINISTRATOR', 'COMMUNICATIONS_MANAGER'])) {
  // Show manager features
}
```

**Features:**
- ✅ Supports single or array of roles
- ✅ Type-safe
- ✅ Boolean return

---

### 8. **hasPermission(permission)**
Check if user has specific permission(s).

```typescript
import { hasPermission } from '@/lib/auth'

if (hasPermission('CREATE_NEWS_ARTICLE')) {
  // Show create button
}

if (hasPermission(['EDIT_USER', 'DELETE_USER'])) {
  // Show user management
}
```

**Features:**
- ✅ Checks user permissions array
- ✅ Supports single or array
- ✅ Boolean return

---

### 9. **getUserDisplayName()**
Get formatted user display name.

```typescript
import { getUserDisplayName } from '@/lib/auth'

const displayName = getUserDisplayName()
// Returns: "John Doe" or "John" or "user@example.com" or "User"
```

**Features:**
- ✅ Intelligent fallback
- ✅ Always returns string
- ✅ User-friendly

---

### 10. **getRoleDisplayName(role?)**
Get human-readable role name.

```typescript
import { getRoleDisplayName } from '@/lib/auth'

const roleName = getRoleDisplayName()
// Uses current user's role

const roleName2 = getRoleDisplayName('ADMINISTRATOR')
// Returns: "System Administrator"
```

**Features:**
- ✅ Maps technical to display names
- ✅ Handles all role types
- ✅ Fallback for unknown roles

---

### 11. **getUserInitials()**
Get user initials for avatars.

```typescript
import { getUserInitials } from '@/lib/auth'

const initials = getUserInitials()
// Returns: "JD" for John Doe, or "J" or "?" as fallback

<div className="avatar">
  {initials}
</div>
```

**Features:**
- ✅ First + Last name initials
- ✅ Intelligent fallback
- ✅ Always returns string

---

## 🎯 Usage Examples

### Example 1: Login Page

```typescript
// src/app/admin/page.tsx
import { setAdminAuth, isAuthenticated } from '@/lib/auth'
import { API_BASE_URL } from '@/config/api'

export default function AdminLogin() {
  // Check if already logged in
  useEffect(() => {
    if (isAuthenticated()) {
      router.push('/admin/dashboard')
    }
  }, [])

  const handleLogin = async (email: string, password: string) => {
    const response = await fetch(`${API_BASE_URL}/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password })
    })

    const result = await response.json()

    if (result.success) {
      // Store auth data
      setAdminAuth({
        token: result.data.token,
        user: result.data.user
      })

      router.push('/admin/dashboard')
    }
  }
}
```

---

### Example 2: Header Component

```typescript
// src/components/admin/AdminHeader.tsx
import { getAdminUser, clearAdminAuth, getRoleDisplayName } from '@/lib/auth'

export default function AdminHeader() {
  const [user, setUser] = useState<AdminUser | null>(null)

  useEffect(() => {
    const userData = getAdminUser()
    setUser(userData)
  }, [])

  const handleLogout = () => {
    clearAdminAuth()
    router.push('/admin')
  }

  return (
    <header>
      <div>
        <p>{user?.firstName} {user?.lastName}</p>
        <p>{getRoleDisplayName(user?.role)}</p>
      </div>
      <button onClick={handleLogout}>Logout</button>
    </header>
  )
}
```

---

### Example 3: Protected Route

```typescript
// src/app/admin/dashboard/page.tsx
import { isAuthenticated, hasRole } from '@/lib/auth'

export default function Dashboard() {
  useEffect(() => {
    if (!isAuthenticated()) {
      router.push('/admin')
      return
    }

    if (!hasRole(['ADMINISTRATOR', 'COMMUNICATIONS_MANAGER'])) {
      router.push('/admin/unauthorized')
    }
  }, [])

  return <div>Dashboard</div>
}
```

---

### Example 4: Conditional Rendering

```typescript
// src/components/admin/Sidebar.tsx
import { hasRole, hasPermission } from '@/lib/auth'

export default function Sidebar() {
  return (
    <nav>
      <Link href="/admin/dashboard">Dashboard</Link>
      
      {hasRole(['ADMINISTRATOR', 'COMMUNICATIONS_MANAGER']) && (
        <Link href="/admin/users">Users</Link>
      )}
      
      {hasPermission('CREATE_NEWS_ARTICLE') && (
        <Link href="/admin/news/new">Create Article</Link>
      )}
      
      {hasRole('ADMINISTRATOR') && (
        <Link href="/admin/settings">Settings</Link>
      )}
    </nav>
  )
}
```

---

## 🔧 TypeScript Types

```typescript
interface AdminUser {
  id: string
  firstName: string
  lastName: string
  email: string
  cellphone?: string
  role: string
  emailVerified?: boolean
  cellphoneVerified?: boolean
  isActive?: boolean
  department?: string
  permissions?: string[]
  createdAt?: string
  updatedAt?: string
  lastLoginAt?: string
}

interface AuthTokens {
  token: string
  user: AdminUser
}
```

---

## 🛡️ Security Features

### Safe JSON Parsing
```typescript
// Handles all edge cases:
- null
- undefined
- "undefined" (string)
- "null" (string)
- Invalid JSON
- Empty string

// Never crashes, always returns null on error
```

### SSR Safety
```typescript
// All functions check for window
if (typeof window === 'undefined') return null

// Safe to use in Next.js server components
```

### Error Handling
```typescript
try {
  localStorage.setItem(...)
} catch (error) {
  console.error('Failed to save auth data:', error)
}

// Graceful degradation
```

---

## 📋 Migration Checklist

If you have old code, migrate it:

### ❌ Old Way
```typescript
const token = localStorage.getItem('adminToken')
const userData = localStorage.getItem('adminUser')
const user = JSON.parse(userData)  // Can crash!
```

### ✅ New Way
```typescript
import { getAdminToken, getAdminUser } from '@/lib/auth'

const token = getAdminToken()
const user = getAdminUser()  // Safe, never crashes
```

---

### ❌ Old Way
```typescript
localStorage.setItem('adminToken', token)
localStorage.setItem('adminUser', JSON.stringify(user))
```

### ✅ New Way
```typescript
import { setAdminAuth } from '@/lib/auth'

setAdminAuth({ token, user })
```

---

### ❌ Old Way
```typescript
localStorage.removeItem('adminToken')
localStorage.removeItem('adminUser')
```

### ✅ New Way
```typescript
import { clearAdminAuth } from '@/lib/auth'

clearAdminAuth()
```

---

## 🎯 Best Practices

1. **Always use auth utilities** - Never access localStorage directly
2. **Check authentication** - Use `isAuthenticated()` in protected routes
3. **Type safety** - Import `AdminUser` type for type checking
4. **Error handling** - Functions handle errors gracefully
5. **Consistent naming** - Use provided functions for role names
6. **SSR awareness** - Functions are SSR-safe

---

## 🐛 Troubleshooting

### Issue: "undefined is not valid JSON"
**Solution:** You're using old code. Update to use `getAdminUser()` instead of `JSON.parse(localStorage.getItem(...))`

### Issue: User data not persisting
**Solution:** Use `setAdminAuth()` instead of direct localStorage calls

### Issue: Role checks not working
**Solution:** Ensure user data includes `role` field and use `hasRole()` function

### Issue: SSR errors
**Solution:** All functions are SSR-safe. Ensure you're importing from `@/lib/auth`

---

## 📚 Related Files

- **Auth Utilities**: `src/lib/auth.ts`
- **API Config**: `src/config/api.ts`
- **Login Page**: `src/app/admin/page.tsx`
- **Header Component**: `src/components/admin/AdminHeader.tsx`
- **Sidebar Component**: `src/components/admin/AdminSidebar.tsx`

---

## ✅ Summary

**All authentication code is now centralized in `src/lib/auth.ts`!**

**Benefits:**
- ✅ No more hardcoding
- ✅ Safe JSON parsing
- ✅ Type-safe
- ✅ Consistent behavior
- ✅ Easy to maintain
- ✅ SSR-safe
- ✅ Error handling

**Use these functions everywhere you need authentication!** 🚀
