'use client'

import React, { createContext, useContext, useState, useCallback, useEffect } from 'react'
import { mutate } from 'swr'
import type { PortalUser, UserRole } from './types'

export const SESSION_TOKEN_KEY = 'adm_token'
export const SESSION_USER_KEY = 'adm_user'

interface AuthContextType {
  user: PortalUser | null
  isAuthenticated: boolean
  isLoading: boolean
  login: (email: string, password: string) => Promise<{ success: boolean; error?: string }>
  logout: () => Promise<void>
  activeTenantId: string | null
  setActiveTenantId: (id: string | null) => void
}

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

function mapApiUser(u: any): PortalUser {
  return {
    id: String(u.id),
    tenantId: u.tenant_id ? String(u.tenant_id) : null,
    tenantName: u.tenant_name ?? null,
    name: u.name,
    email: u.email,
    role: u.role as UserRole,
    status: (u.status ?? 'active') as 'active' | 'inactive' | 'pending' | 'blocked',
    mfaEnabled: !!u.mfa_enabled,
    lastLogin: u.last_login ?? null,
    createdAt: u.created_at ?? new Date().toISOString(),
    permissions: [],
  }
}

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<PortalUser | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [activeTenantId, setActiveTenantId] = useState<string | null>(null)

  // Carrega sessão ao montar usando Bearer token armazenado no sessionStorage
  useEffect(() => {
    const storedUser = sessionStorage.getItem(SESSION_USER_KEY)
    const storedToken = sessionStorage.getItem(SESSION_TOKEN_KEY)

    if (storedUser && storedToken) {
      try {
        const parsed = JSON.parse(storedUser)
        const mapped = mapApiUser(parsed)
        setUser(mapped)
        if (mapped.tenantId) setActiveTenantId(mapped.tenantId)
        setIsLoading(false)
        // Valida token com servidor em background
        fetch('/api/auth/session', {
          credentials: 'include',
          headers: { Authorization: `Bearer ${storedToken}` },
        })
          .then((r) => r.ok ? r.json() : null)
          .then((data) => {
            if (data?.user) {
              const refreshed = mapApiUser(data.user)
              setUser(refreshed)
              sessionStorage.setItem(SESSION_USER_KEY, JSON.stringify(data.user))
              if (refreshed.tenantId) setActiveTenantId(refreshed.tenantId)
              // Revalida todos os SWR agora que o token está confirmado no sessionStorage
              mutate(() => true, undefined, { revalidate: true })
            } else {
              sessionStorage.removeItem(SESSION_USER_KEY)
              sessionStorage.removeItem(SESSION_TOKEN_KEY)
              setUser(null)
            }
          })
          .catch(() => {})
          .finally(() => setIsLoading(false))
        return
      } catch {}
    }
    // Sem token local, tenta via cookie como fallback
    fetch('/api/auth/session', { credentials: 'include' })
      .then((r) => r.ok ? r.json() : null)
      .then((data) => {
        if (data?.user) {
          const mapped = mapApiUser(data.user)
          setUser(mapped)
          sessionStorage.setItem(SESSION_USER_KEY, JSON.stringify(data.user))
          if (mapped.tenantId) setActiveTenantId(mapped.tenantId)
          mutate(() => true, undefined, { revalidate: true })
        }
      })
      .catch(() => {})
      .finally(() => setIsLoading(false))
  }, [])

  const login = useCallback(async (email: string, password: string) => {
    try {
      const res = await fetch('/api/auth/login', {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, password }),
      })

      const data = await res.json()

      if (!res.ok) {
        return { success: false, error: data.error ?? 'Credenciais inválidas' }
      }

      if (data.token) sessionStorage.setItem(SESSION_TOKEN_KEY, data.token)
      if (data.user) sessionStorage.setItem(SESSION_USER_KEY, JSON.stringify(data.user))

      const mapped = mapApiUser(data.user)
      setUser(mapped)
      if (mapped.tenantId) setActiveTenantId(mapped.tenantId)
      // Token já salvo no sessionStorage — revalida todos os SWR
      mutate(() => true, undefined, { revalidate: true })
      return { success: true }
    } catch {
      return { success: false, error: 'Erro de conexão com o servidor' }
    }
  }, [])

  const logout = useCallback(async () => {
    const token = sessionStorage.getItem(SESSION_TOKEN_KEY)
    await fetch('/api/auth/logout', {
      method: 'POST',
      credentials: 'include',
      headers: token ? { Authorization: `Bearer ${token}` } : {},
    }).catch(() => {})
    sessionStorage.removeItem(SESSION_USER_KEY)
    sessionStorage.removeItem(SESSION_TOKEN_KEY)
    setUser(null)
    setActiveTenantId(null)
  }, [])

  return (
    <AuthContext.Provider
      value={{
        user,
        isAuthenticated: !!user,
        isLoading,
        login,
        logout,
        activeTenantId,
        setActiveTenantId,
      }}
    >
      {children}
    </AuthContext.Provider>
  )
}

export function useAuth() {
  const ctx = useContext(AuthContext)
  if (!ctx) throw new Error('useAuth must be used inside AuthProvider')
  return ctx
}

export function isAdminGlobal(role?: UserRole) {
  return role === 'admin_global'
}

export function isTenantAdmin(role?: UserRole) {
  return role === 'tenant_admin' || role === 'admin_global'
}
