/**
 * Serviço de Autenticação (Frontend)
 * Chama Supabase diretamente
 */

import axios from "axios";
import { API_CONFIG } from "../api/config";
import type {
  LoginInput,
  LoginResponse,
  AuthUser,
  RefreshTokenResponse,
} from "./types";

class AuthService {
  /**
   * Faz login com email e senha
   */
  async login(credentials: LoginInput): Promise<LoginResponse> {
    try {
      console.log("[authService] Tentando login com:", credentials.email);
      const response = await axios.post<LoginResponse>(
        `${API_CONFIG.AUTH_URL}/token?grant_type=password`,
        {
          email: credentials.email,
          password: credentials.password,
        },
        {
          headers: {
            "Content-Type": "application/json",
            apikey: API_CONFIG.SUPABASE_ANON_KEY,
          },
        }
      );

      console.log("[authService] Login bem-sucedido:", response.data);

      // Salva tokens e user no localStorage
      if (response.data.access_token) {
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN,
          response.data.access_token
        );
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.REFRESH_TOKEN,
          response.data.refresh_token
        );
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.USER,
          JSON.stringify(response.data.user)
        );
      }

      return response.data;
    } catch (error: any) {
      console.error("[authService] Erro no login:", error);
      console.error("[authService] Response data:", error.response?.data);
      console.error("[authService] Response status:", error.response?.status);
      throw error;
    }
  }

  /**
   * Registro público (signup) com email e senha
   * POST /auth/v1/signup
   * Não requer autenticação - permite auto-registro
   */
  async signup(data: {
    email: string;
    password: string;
    full_name: string;
    phone?: string;
  }): Promise<LoginResponse> {
    try {
      const response = await axios.post<LoginResponse>(
        `${API_CONFIG.AUTH_URL}/signup`,
        {
          email: data.email,
          password: data.password,
          options: {
            data: {
              full_name: data.full_name,
              phone: data.phone,
            },
          },
        },
        {
          headers: {
            "Content-Type": "application/json",
            apikey: API_CONFIG.SUPABASE_ANON_KEY,
          },
        }
      );

      // Salva tokens e user no localStorage
      if (response.data.access_token) {
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN,
          response.data.access_token
        );
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.REFRESH_TOKEN,
          response.data.refresh_token
        );
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.USER,
          JSON.stringify(response.data.user)
        );
      }

      return response.data;
    } catch (error) {
      console.error("Erro no signup:", error);
      throw error;
    }
  }

  /**
   * Envia magic link para o email do usuário
   * POST /auth/v1/otp
   */
  async sendMagicLink(
    email: string,
    redirectUrl?: string
  ): Promise<{ success: boolean; message: string }> {
    try {
      await axios.post(
        `${API_CONFIG.AUTH_URL}/otp`,
        {
          email,
          options: {
            emailRedirectTo:
              redirectUrl || `${API_CONFIG.APP_URL}/auth/callback`,
          },
        },
        {
          headers: {
            "Content-Type": "application/json",
            apikey: API_CONFIG.SUPABASE_ANON_KEY,
          },
        }
      );

      return {
        success: true,
        message: "Magic link enviado com sucesso",
      };
    } catch (error) {
      console.error("Erro ao enviar magic link:", error);
      throw error;
    }
  }

  /**
   * Solicita reset de senha via email (público)
   * POST /auth/v1/recover
   * 
   * Envia redirectTo dentro de options para controlar para onde o Supabase redireciona
   */
  async requestPasswordReset(
    email: string
  ): Promise<{ success: boolean; message: string }> {
    try {
      const redirectUrl = `${API_CONFIG.APP_URL}/reset-password`;
      
      console.log("[authService.requestPasswordReset] Email:", email);
      console.log("[authService.requestPasswordReset] Redirect URL:", redirectUrl);
      console.log("[authService.requestPasswordReset] Usando endpoint /auth/v1/recover");
      
      const payload = {
        email,
        options: {
          redirectTo: redirectUrl,
        },
      };
      
      console.log("[authService.requestPasswordReset] Payload:", JSON.stringify(payload, null, 2));
      
      await axios.post(
        `${API_CONFIG.AUTH_URL}/recover`,
        payload,
        {
          headers: {
            "Content-Type": "application/json",
            apikey: API_CONFIG.SUPABASE_ANON_KEY,
          },
        }
      );

      console.log("[authService.requestPasswordReset] ✅ Email de recuperação enviado");

      return {
        success: true,
        message: "Email de recuperação de senha enviado com sucesso. Verifique sua caixa de entrada.",
      };
    } catch (error: any) {
      console.error("[authService.requestPasswordReset] ❌ Erro:", error);
      console.error("[authService.requestPasswordReset] Response:", error.response?.data);
      throw error;
    }
  }

  /**
   * Atualiza a senha do usuário usando o token de recuperação
   * PUT /auth/v1/user
   */
  async updatePassword(
    accessToken: string,
    newPassword: string
  ): Promise<{ success: boolean; message: string }> {
    try {
      console.log("[authService.updatePassword] Iniciando atualização de senha");
      console.log("[authService.updatePassword] Token (primeiros 30 chars):", accessToken.substring(0, 30));
      console.log("[authService.updatePassword] Nova senha length:", newPassword.length);
      console.log("[authService.updatePassword] URL:", `${API_CONFIG.AUTH_URL}/user`);

      const response = await axios.put(
        `${API_CONFIG.AUTH_URL}/user`,
        {
          password: newPassword,
        },
        {
          headers: {
            "Content-Type": "application/json",
            apikey: API_CONFIG.SUPABASE_ANON_KEY,
            Authorization: `Bearer ${accessToken}`,
          },
        }
      );

      console.log("[authService.updatePassword] ✅ Senha atualizada com sucesso");
      console.log("[authService.updatePassword] Response status:", response.status);

      return {
        success: true,
        message: "Senha atualizada com sucesso",
      };
    } catch (error: any) {
      console.error("[authService.updatePassword] ❌ Erro ao atualizar senha:", error);
      console.error("[authService.updatePassword] Error response:", error.response?.data);
      console.error("[authService.updatePassword] Error response (stringified):", JSON.stringify(error.response?.data, null, 2));
      console.error("[authService.updatePassword] Error status:", error.response?.status);
      console.error("[authService.updatePassword] Error statusText:", error.response?.statusText);
      console.error("[authService.updatePassword] Error headers:", error.response?.headers);
      console.error("[authService.updatePassword] Request URL:", error.config?.url);
      console.error("[authService.updatePassword] Request headers:", error.config?.headers);
      console.error("[authService.updatePassword] Request data:", error.config?.data);
      
      // Se for 422, mostrar mensagem específica
      if (error.response?.status === 422) {
        const errorMsg = error.response?.data?.msg || error.response?.data?.message || error.response?.data?.error_description || "Token inválido ou expirado";
        console.error("[authService.updatePassword] ⚠️ Erro 422 - Possíveis causas:");
        console.error("  1. Token de recuperação expirado (válido por 1 hora)");
        console.error("  2. Token já foi usado");
        console.error("  3. Formato do token incorreto");
        console.error("  4. Usuário não existe");
        console.error("[authService.updatePassword] Mensagem do servidor:", errorMsg);
      }
      
      throw error;
    }
  }

  /**
   * Faz logout (invalida sessão no servidor e limpa localStorage)
   */
  async logout(): Promise<void> {
    try {
      const token = localStorage.getItem(API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN);

      if (token) {
        // Chama API para invalidar sessão no servidor
        await axios.post(
          `${API_CONFIG.AUTH_URL}/logout`,
          {},
          {
            headers: {
              "Content-Type": "application/json",
              apikey: API_CONFIG.SUPABASE_ANON_KEY,
              Authorization: `Bearer ${token}`,
            },
          }
        );
      }
    } catch (error) {
      console.error("Erro ao invalidar sessão no servidor:", error);
      // Continua mesmo com erro, para garantir limpeza local
    } finally {
      // Sempre limpa o localStorage
      localStorage.removeItem(API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN);
      localStorage.removeItem(API_CONFIG.STORAGE_KEYS.REFRESH_TOKEN);
      localStorage.removeItem(API_CONFIG.STORAGE_KEYS.USER);
    }
  }

  /**
   * Verifica se usuário está autenticado
   */
  isAuthenticated(): boolean {
    return !!localStorage.getItem(API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN);
  }

  /**
   * Retorna o usuário atual do localStorage
   */
  getCurrentUser(): AuthUser | null {
    const userStr = localStorage.getItem(API_CONFIG.STORAGE_KEYS.USER);
    if (!userStr) return null;

    try {
      return JSON.parse(userStr);
    } catch {
      return null;
    }
  }

  /**
   * Retorna o access token
   */
  getAccessToken(): string | null {
    return localStorage.getItem(API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN);
  }

  /**
   * Renova o access token usando o refresh token
   */
  async refreshToken(): Promise<RefreshTokenResponse> {
    try {
      const refreshToken = localStorage.getItem(
        API_CONFIG.STORAGE_KEYS.REFRESH_TOKEN
      );

      if (!refreshToken) {
        throw new Error("Refresh token não encontrado");
      }

      const response = await axios.post<RefreshTokenResponse>(
        `${API_CONFIG.AUTH_URL}/token?grant_type=refresh_token`,
        {
          refresh_token: refreshToken,
        },
        {
          headers: {
            "Content-Type": "application/json",
            apikey: API_CONFIG.SUPABASE_ANON_KEY,
          },
        }
      );

      // Atualiza tokens e user no localStorage
      if (response.data.access_token) {
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.ACCESS_TOKEN,
          response.data.access_token
        );
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.REFRESH_TOKEN,
          response.data.refresh_token
        );
        localStorage.setItem(
          API_CONFIG.STORAGE_KEYS.USER,
          JSON.stringify(response.data.user)
        );
      }

      return response.data;
    } catch (error) {
      console.error("Erro ao renovar token:", error);
      // Se falhar, limpa tudo e força novo login
      this.logout();
      throw error;
    }
  }
}

export const authService = new AuthService();
