
import React, { createContext, useContext, useState, ReactNode, useEffect } from 'react';
import { User, UserRole } from '../types';

// Mock Users Database
const MOCK_USERS: User[] = [
  {
    id: 'superadmin-1',
    name: 'Dev Admin',
    email: 'admin@photum.com',
    role: UserRole.SUPERADMIN,
    avatar: 'https://i.pravatar.cc/150?u=admin'
  },
  {
    id: 'owner-1',
    name: 'PHOTUM CEO',
    email: 'empresa@photum.com',
    role: UserRole.BUSINESS_OWNER,
    avatar: 'https://i.pravatar.cc/150?u=ceo'
  },
  {
    id: 'photographer-1',
    name: 'COLABORADOR PHOTUM',
    email: 'foto@photum.com',
    role: UserRole.PHOTOGRAPHER,
    avatar: 'https://i.pravatar.cc/150?u=photo'
  },
  {
    id: 'client-1',
    name: 'PARCEIRO PHOTUM',
    email: 'cliente@photum.com',
    role: UserRole.EVENT_OWNER,
    avatar: 'https://i.pravatar.cc/150?u=client'
  },
  {
    id: 'viewer-1',
    name: 'VISUALIZADOR PHOTUM',
    email: 'viewer@photum.com',
    role: UserRole.AGENDA_VIEWER,
    avatar: 'https://i.pravatar.cc/150?u=viewer'
  }
];

interface AuthContextType {
  user: User | null;
  login: (email: string, password?: string) => Promise<boolean>;
  logout: () => void;
  register: (data: { nome: string; email: string; senha: string; telefone: string; role: string; empresaId?: string; tipo_profissional?: string }) => Promise<{ success: boolean; userId?: string; token?: string }>;
  availableUsers: User[]; // Helper for the login screen demo
  token: string | null;
}

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

export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<User | null>(null);
  const [token, setToken] = useState<string | null>(localStorage.getItem("token"));

  useEffect(() => {
    const restoreSession = async () => {
      if (!token) return;

      try {
        const API_URL = import.meta.env.VITE_API_URL || "http://localhost:8080";
        const response = await fetch(`${API_URL}/api/me`, {
          headers: {
            'Authorization': `Bearer ${token}`
          }
        });

        if (response.ok) {
          const data = await response.json();
          const backendUser = data.user;
          const mappedUser: User = {
            id: backendUser.id,
            email: backendUser.email,
            name: data.profissional?.nome || data.empresa?.nome || backendUser.name || backendUser.nome || backendUser.email.split('@')[0],
            role: backendUser.role as UserRole,
            ativo: backendUser.ativo,
            empresaId: backendUser.company_id || backendUser.empresa_id || backendUser.companyId,
            companyName: backendUser.company_name || backendUser.empresa_nome || backendUser.companyName,
            avatar: data.profissional?.avatar_url || data.empresa?.avatar_url || backendUser.avatar,
          };
          if (!backendUser.ativo) {
            console.warn("User is not active, logging out.");
            logout();
            return;
          }
          setUser(mappedUser);
        } else {
          // Token invalid or expired
          logout();
        }
      } catch (err) {
        console.error("Session restore error:", err);
        logout();
      }
    };

    if (!user && token) {
      restoreSession();
    }
  }, [token]); // removed 'user' from dependency to avoid loop if user is set, though !user check handles it. safer to just depend on token mount.

  const getErrorMessage = (errorKey: string): string => {
    // Map backend error messages to Portuguese
    const errorMap: { [key: string]: string } = {
      "email already registered": "Este e-mail já está cadastrado.",
      "invalid credentials": "E-mail ou senha incorretos.",
      "user not found": "Usuário não encontrado.",
      "crypto/bcrypt: hashedPassword is not the hash of the given password": "Senha incorreta.",
      "password is too short": "A senha é muito curta.",
      "cpf already registered": "CPF já cadastrado.",
    };

    // Check for partial matches or exact matches
    if (errorMap[errorKey]) return errorMap[errorKey];

    // Fallbacks
    if (errorKey.includes('hashedPassword')) return "Senha incorreta.";
    if (errorKey.includes('email')) return "Erro relacionado ao e-mail.";
    if (errorKey.includes('password')) return "Erro relacionado à senha.";

    return "Ocorreu um erro inesperado. Tente novamente.";
  };

const API_URL = import.meta.env.VITE_API_URL || "http://localhost:8080";

const login = async (email: string, password?: string) => {
    // 1. Try Real API first
    try {
      const response = await fetch(`${API_URL}/auth/login`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, senha: password })
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(getErrorMessage(errorData.error || 'Falha no login'));
      }

      const data = await response.json();

      const backendUser = data.user;

      // Enforce active check
      if (!backendUser.ativo) {
        throw new Error("Cadastro pendente de aprovação.");
      }

      // Store token (optional, if you need it for other requests outside cookies)
      localStorage.setItem('token', data.access_token);
      setToken(data.access_token);

      // Map backend user to frontend User type
      const mappedUser: User = {
        id: backendUser.id,
        email: backendUser.email,
        name: data.profissional?.nome || data.empresa?.nome || backendUser.name || backendUser.nome || backendUser.email.split('@')[0],
        role: backendUser.role as UserRole,
        ativo: backendUser.ativo,
        empresaId: backendUser.company_id || backendUser.empresa_id || backendUser.companyId,
        companyName: backendUser.company_name || backendUser.empresa_nome || backendUser.companyName,
        avatar: data.profissional?.avatar_url || data.empresa?.avatar_url || backendUser.avatar,
      };

      setUser(mappedUser);
      return true;
    } catch (err) {
      console.error('Login error:', err);

      // 2. Fallback to Demo/Mock users if API fails
      const mockUser = MOCK_USERS.find(u => u.email === email);
      if (mockUser) {
        console.log('Using demo user:', mockUser.email);
        await new Promise(resolve => setTimeout(resolve, 500)); // Simulate delay
        setUser({ ...mockUser, ativo: true });
        return true;
      }

      throw err;
    }
  };

  const logout = async () => {
    try {
      if (token) {
        await fetch(`${import.meta.env.VITE_API_URL}/auth/logout`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}` // Though refresh token is in cookie
          },
          // body: JSON.stringify({ refresh_token: ... }) // If we had it in client state, but it is in cookie.
        });
      }
    } catch (error) {
      console.error("Logout failed", error);
    } finally {
      localStorage.removeItem('token');
      setToken(null);
      setUser(null);
      // Force redirect or let app router handle it safely
      window.location.href = '/';
    }
  };

  const register = async (data: { nome: string; email: string; senha: string; telefone: string; role: string; empresaId?: string; tipo_profissional?: string }) => {
    try {
      // Destructure to separate empresaId from the rest
      const { empresaId, ...rest } = data;
      const payload = {
        ...rest,
        empresa_id: empresaId
      };
      const response = await fetch(`${import.meta.env.VITE_API_URL}/auth/register`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        const rawError = errorData.error || 'Falha no cadastro';
        throw new Error(getErrorMessage(rawError));
      }

      const responseData = await response.json();

      // IF user is returned (auto-login), logic:
      // Only set user/token if they are ACTIVE (which they won't be for standard clients/professionals)
      // This allows the "Pending Approval" modal to show instead of auto-redirecting.
      if (responseData.user && responseData.user.ativo) {
        if (responseData.access_token) {
          localStorage.setItem('token', responseData.access_token);
          setToken(responseData.access_token);
        }

        const backendUser = responseData.user;
        const mappedUser: User = {
          id: backendUser.id,
          email: backendUser.email,
          name: backendUser.nome || backendUser.email.split('@')[0],
          role: backendUser.role as UserRole,
          ativo: backendUser.ativo,
          empresaId: backendUser.company_id || backendUser.empresa_id || backendUser.companyId,
          companyName: backendUser.company_name || backendUser.empresa_nome || backendUser.companyName,
        };
        setUser(mappedUser);
      }
      // If user is NOT active, we do NOT set the token/user state, preventing auto-login.

      return {
        success: true,
        userId: responseData.user?.id || responseData.userId,
        token: responseData.access_token
      };
    } catch (err) {
      console.error('Registration error:', err);
      throw err;
    }
  };

  return (
    <AuthContext.Provider value={{ user, token, login, logout, register, availableUsers: MOCK_USERS }}>
      {children}
    </AuthContext.Provider>
  );
};

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