import { API_BASE_URL } from "@/utils/constants";
import { ApiError } from "@/services/apiClient";
import { tryDemoLogin } from "@/lib/demoAuth";
import type { ApiResponse, AuthTokens, LoginCredentials, User } from "@/types";

const API_LOGIN_TIMEOUT_MS = 12000;

function isApiUnreachable(error: unknown): boolean {
  if (error instanceof DOMException && error.name === "AbortError") {
    return true;
  }
  if (error instanceof TypeError) {
    return true;
  }
  return false;
}

async function loginViaApi(
  credentials: LoginCredentials,
): Promise<{ user: User; token: string }> {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), API_LOGIN_TIMEOUT_MS);

  try {
    const response = await fetch(`${API_BASE_URL}/auth/login`, {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        email: credentials.email.trim(),
        password: credentials.password,
      }),
      signal: controller.signal,
    });

    const payload = await response.json().catch(() => null);

    if (!response.ok) {
      const body = payload as {
        message?: string;
        errors?: Record<string, string[]>;
      };
      const fieldMsg = body?.errors?.email?.[0];
      throw new ApiError(
        fieldMsg ?? body?.message ?? "E-mail ou senha inválidos.",
        response.status,
        payload,
      );
    }

    const data = (payload as ApiResponse<{ user: User; token: AuthTokens }>).data;
    const token =
      typeof data.token === "string" ? data.token : data.token?.accessToken;

    if (!data?.user || !token) {
      throw new Error("Resposta inválida do servidor de autenticação.");
    }

    return { user: data.user, token };
  } finally {
    clearTimeout(timeoutId);
  }
}

/** Login administrativo — sempre via API real (sem modo demo). */
export async function loginAdminUser(
  credentials: LoginCredentials,
): Promise<{ user: User; token: string }> {
  try {
    const result = await loginViaApi(credentials);
    if (result.user.role !== "admin") {
      throw new Error("Esta área é exclusiva para administradores.");
    }
    return result;
  } catch (error) {
    if (error instanceof ApiError) {
      const payload = error.payload as {
        message?: string;
        errors?: Record<string, string[]>;
      };
      const fieldMsg = payload?.errors?.email?.[0];
      throw new Error(fieldMsg ?? error.message ?? "E-mail ou senha inválidos.");
    }

    if (isApiUnreachable(error)) {
      throw new Error(
        "Não foi possível contactar o servidor. Inicie o backend (php artisan serve) e confira NEXT_PUBLIC_API_URL no .env.local.",
      );
    }

    if (error instanceof Error) {
      throw error;
    }

    throw new Error("Não foi possível entrar. Verifique sua conexão e tente novamente.");
  }
}

export async function loginUser(
  credentials: LoginCredentials,
): Promise<{ user: User; token: string }> {
  try {
    return await loginViaApi(credentials);
  } catch (error) {
    if (error instanceof ApiError) {
      const payload = error.payload as {
        message?: string;
        errors?: Record<string, string[]>;
      };
      const fieldMsg = payload?.errors?.email?.[0];
      throw new Error(fieldMsg ?? error.message ?? "E-mail ou senha inválidos.");
    }

    if (isApiUnreachable(error)) {
      const demo = tryDemoLogin(credentials.email, credentials.password);
      if (demo) {
        return demo;
      }
      throw new Error(
        "O servidor não respondeu. Verifique se o backend está ativo (php artisan serve).",
      );
    }

    throw new Error(
      error instanceof Error
        ? error.message
        : "Não foi possível entrar. Verifique sua conexão e tente novamente.",
    );
  }
}
