/**
 * Auth API
 *
 * 认证相关接口
 *
 */
import { z } from "zod";

import {
  CheckoutHandoffConsumeRequest,
  CheckoutHandoffConsumeResponse,
  CheckoutHandoffConsumeResponseSchema,
  CheckoutHandoffCreateRequest,
  CheckoutHandoffCreateResponse,
  CheckoutHandoffCreateResponseSchema,
  FacebookIdentityRequest,
  FacebookIdentityResponse,
  FacebookIdentityResponseSchema,
  FacebookLoginRequest,
  FbIdLoginRequest,
  GoogleLoginRequest,
  GuestLoginRequest,
  GuestLoginResponse,
  GuestLoginResponseSchema,
  LoginRequest,
  LoginResponse,
  LoginResponseSchema,
  RefreshTokenRequest,
  RefreshTokenResponse,
  RefreshTokenResponseSchema,
  RegisterRequest,
  TopUpHandoffRequest,
  TopUpHandoffResponse,
  TopUpHandoffResponseSchema,
} from "@/data/schemas/auth";
import { User, UserSchema } from "@/data/schemas/user";
import type { UserData } from "@/data/schemas/user/user";
import { Logger } from "@/utils/logger";
import { ApiPath } from "./api_path";
import { httpClient } from "./http_client";
import { ApiEnvelope, unwrap } from "./response_helper";

const log = new Logger("DataServicesApiAuthApi");

export class AuthApi {
  /**
   * 邮箱密码登录
   */
  async emailLogin(body: LoginRequest): Promise<LoginResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.emailLogin, {
      method: "POST",
      body,
    });
    return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
  }

  /**
   * 注册
   */
  async register(body: RegisterRequest): Promise<void> {
    await httpClient<ApiEnvelope<unknown>>(ApiPath.register, {
      method: "POST",
      body,
    });
  }

  /**
   * Google 登录
   */
  async googleLogin(body: GoogleLoginRequest): Promise<LoginResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.googleLogin, {
      method: "POST",
      body,
    });
    return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
  }

  /**
   * Facebook 登录
   */
  async facebookLogin(body: FacebookLoginRequest): Promise<LoginResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.facebookLogin, {
      method: "POST",
      body,
    });
    return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
  }

  /**
   * Facebook ID 登录（v7.0 新增）
   */
  async facebookIdLogin(body: FbIdLoginRequest): Promise<LoginResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(
      ApiPath.facebookIdLogin,
      { method: "POST", body },
    );
    return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
  }

  /** 消费一次性充值登录凭证。当前正式登录 token 会由拦截器自动携带。 */
  async consumeTopUpHandoff(
    body: TopUpHandoffRequest,
  ): Promise<TopUpHandoffResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(
      ApiPath.topUpHandoffConsume,
      { method: "POST", body },
    );
    return TopUpHandoffResponseSchema.parse(
      unwrap(env) as Record<string, unknown>,
    );
  }

  /** 在创建支付订单前生成一次性外部浏览器交接链接。 */
  async createCheckoutHandoff(
    body: CheckoutHandoffCreateRequest,
  ): Promise<CheckoutHandoffCreateResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(
      ApiPath.checkoutHandoffCreate,
      { method: "POST", body },
    );
    return CheckoutHandoffCreateResponseSchema.parse(
      unwrap(env) as Record<string, unknown>,
    );
  }

  /** 消费一次性支付交接凭证并恢复正式登录态与购买意图。 */
  async consumeCheckoutHandoff(
    body: CheckoutHandoffConsumeRequest,
  ): Promise<CheckoutHandoffConsumeResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(
      ApiPath.checkoutHandoffConsume,
      { method: "POST", body },
    );
    return CheckoutHandoffConsumeResponseSchema.parse(
      unwrap(env) as Record<string, unknown>,
    );
  }

  /**
   * 绑定 Facebook ASID / PSID 到当前用户
   */
  async bindFacebookIdentity(
    body: FacebookIdentityRequest,
  ): Promise<FacebookIdentityResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(
      ApiPath.userFacebookIdentity,
      { method: "POST", body },
    );
    return FacebookIdentityResponseSchema.parse(
      unwrap(env) as Record<string, unknown>,
    );
  }

  /**
   * 退出登录（fire-and-forget）
   *
   * 后端 logout 端点的 envelope `data` 字段常为 `null`（登出端点没有业务数据），
   * 不要再用 `unwrap` + `LogoutResponseSchema.parse` 解析 —— Zod schema 是 z.object，
   * 对 null 会抛 ZodError "Invalid input: expected object, received null"。
   *
   * 对齐 `register` 的写法：调通就完事，不解析响应体。
   */
  async logout(): Promise<void> {
    await httpClient<ApiEnvelope<unknown>>(ApiPath.logout, {
      method: "POST",
    });
  }

  /**
   * 游客登录
   */
  async guestLogin(body: GuestLoginRequest): Promise<GuestLoginResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.guestLogin, {
      method: "POST",
      body,
    });
    log.debug("[AuthApi.guestLogin] raw envelope from backend", env);
    const unwrapped = unwrap(env) as Record<string, unknown>;
    const userObj = unwrapped.user as { lastMessageAt?: unknown } | undefined;
    log.debug("[AuthApi.guestLogin] unwrapped data (pre-parse)", {
      hasUser: "user" in unwrapped,
      userKeys:
        userObj && typeof userObj === "object" ? Object.keys(userObj) : null,
      lastMessageAt: userObj?.lastMessageAt,
      lastMessageAtType: typeof userObj?.lastMessageAt,
    });
    try {
      return GuestLoginResponseSchema.parse(unwrapped);
    } catch (e) {
      if (e instanceof z.ZodError) {
        log.error("[AuthApi.guestLogin] ZodError parsing response", {
          issueCount: e.issues.length,
          firstIssue: e.issues[0],
          allPaths: e.issues.map((i) => i.path),
        });
      } else {
        log.error("[AuthApi.guestLogin] unexpected error", e);
      }
      throw e;
    }
  }

  /**
   * 刷新 Token
   */
  async refreshToken(body: RefreshTokenRequest): Promise<RefreshTokenResponse> {
    const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.refresh, {
      method: "POST",
      body,
    });
    return RefreshTokenResponseSchema.parse(
      unwrap(env) as Record<string, unknown>,
    );
  }

  /**
   * 获取当前用户信息
   */
  async getCurrentUser(): Promise<User> {
    const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.getCurrentUser);
    return UserSchema.parse(unwrap(env) as UserData);
  }
}

/**
 * 全局单例
 */
export const authApi = new AuthApi();
