// src/services/api/authService.ts
import { VerifyUserPayload } from "@/record-management/services/api/authService";
import axiosInstance from "./axiosInstance";
import { withHeaders } from "@/record-management/services/api/withHeaders";
import axios from "axios";

export interface SignupPayload {
  email: string;
  username: string;
  password: string;
  userType: string;
  name: {
    am: string;
    en: string;
  };
}

export interface LoginPayload {
  email?: string;
  phoneNumber?: string;
  userName?: string;
  password: string;
}

export interface AuthHeaders {
  tenantKey: string;
  unitId?: string;
}

export interface SetPasswordPayload {
  userId?: string;
  email?: string;
  phoneNumber?: string;
  verificationCode: string;
  newPassword: string;
  confirmPassword: string;
}
export interface SetFayidaPasswordPayload {
  userId: string;
  newPassword: string;
  confirmPassword: string;
}
export interface ChangePasswordPayload {
  oldPassword: string;
  newPassword: string;
  confirmPassword: string;
}
export interface UpdateProfilePayload {
  email: string;
  username: string;
  phoneNumber: string;
  name: {
    am: string;
    en: string;
  };
}
export interface OtpVerificationPayload {
  email: string;
  phoneNumber: string;
  verificationCode: string;
}

export interface GenerateVerifcationCodePayload {
  phoneNumber: string;
  email?: string;
  verificationCode?: string;
}

export enum EOtpType {
  SET_PASSWORD = "set-password",
  RESET_PASSWORD = "reset-password",
  VERIFY_PHONE_NUMBER = "verify-phone-number",
}

export const signup = async (payload: SignupPayload, headers: AuthHeaders) => {
  return axiosInstance.post("/auth/signup", payload, {
    headers: {
      "x-organization-tenant-key": headers.tenantKey,
      ...(headers.unitId && { "x-organization-unit-id": headers.unitId }),
    },
  });
};

export const login = async (payload: LoginPayload) => {
  // Validate that at least one identifier is provided
  if (!payload.email && !payload.phoneNumber && !payload.userName) {
    throw new Error(
      "At least one login identifier (email, phoneNumber, or userName) is required",
    );
  }

  return axiosInstance.post("/auth/login", payload);
};

export const getProfile = async (
  config?: Parameters<typeof axiosInstance.get>[1],
) => {
  return axiosInstance.get("/auth/me", {
    ...config,
    headers: {
      ...withHeaders(),
      ...(config?.headers ?? {}),
    },
  });
};
export const updateProfile = async (payload: UpdateProfilePayload) => {
  return axiosInstance.patch("/auth/update-profile", payload);
};

export const setPassword = async (payload: SetPasswordPayload) => {
  return axiosInstance.patch("/auth/set-password", payload);
};
export const setFayidaPass = async (payload: SetFayidaPasswordPayload) => {
  return axiosInstance.patch("/auth/set-fayda-password", payload);
};
export const changePassword = async (payload: ChangePasswordPayload) => {
  return axiosInstance.patch("/auth/change-password", payload);
};
export const resendVerificationCode = async (
  payload: GenerateVerifcationCodePayload,
) => {
  const payloadObj = {
    ...payload,
    type: EOtpType.SET_PASSWORD,
  };
  return axiosInstance.patch("/auth/generate-verification-code", payloadObj);
};
export const verifyOTPCode = async (
  payload: GenerateVerifcationCodePayload,
) => {
  return axiosInstance.patch("/auth/verify-phone-number", payload);
};
export const resendOtpCode = async (
  payload: GenerateVerifcationCodePayload,
) => {
  const payloadObj = {
    ...payload,
    type: EOtpType.VERIFY_PHONE_NUMBER,
  };
  return axiosInstance.patch("/auth/generate-verification-code", payloadObj);
};

export const refreshAuthToken = async (payload: { refreshToken: string }) => {
  return axiosInstance.post("/auth/refresh-token", payload);
};

export const requestForgotPassword = async (identifier: string) => {
  try {
    // The API expects the identifier in the email field regardless of whether it's an email or phone
    const payload = { email: identifier };

    const response = await axiosInstance.post("/auth/forgot-password", payload);
    return response.data;
  } catch (error) {
    throw error;
  }
};

export const logout = async () => {
  return axiosInstance.patch("/auth/logout");
};

export const verifyMFAUser = async (payload: VerifyUserPayload) => {
  return axiosInstance.post("/auth/mfa-verify", payload, {
    headers: withHeaders(),
  });
};

export interface RegisterWithFaydaPayload {
  code: string;
}

export interface RegisterWithFaydaResponse {
  userId?: string;
  token?: string;
  refreshToken?: string;
  fullName?: string;
  faydaId?: string;
  user?: {
    id?: string;
    userId?: string;
    fullName?: string;
    faydaId?: string;
    name?: string | { am?: string; en?: string };
    [key: string]: unknown;
  };
  citizen?: {
    fullName?: string;
    faydaId?: string;
  };
  [key: string]: unknown;
}

export const signinWithFayda = async (payload: RegisterWithFaydaPayload) => {
  return axiosInstance.post<RegisterWithFaydaResponse>(
    "/auth/signin-with-fayda",
    payload,
    { headers: withHeaders() },
  );
};

export const signupWithFayda = async (payload: RegisterWithFaydaPayload) => {
  return axiosInstance.post<RegisterWithFaydaResponse>(
    "/auth/signup-with-fayda",
    payload,
    { headers: withHeaders() },
  );
};

export const signinWithEtrade = async (payload: EtradeSigninPayload) => {
  return axiosInstance.post<RegisterWithEtradeResponse>(
    "/auth/signin-with-etrade",
    payload,
    { headers: withHeaders() },
  );
};

export const signupWithEtrade = async (payload: EtradeSignupPayload) => {
  return axiosInstance.post<RegisterWithEtradeResponse>(
    "/auth/signup-with-etrade",
    payload,
    { headers: withHeaders() },
  );
};

export const verifyEtradeOtp = async (payload: VerifyEtradeOtpPayload) => {
  return axiosInstance.post("/auth/verify-etrade-otp", payload, {
    headers: withHeaders(),
  });
};

export const registerWithFayda = async (payload: RegisterWithFaydaPayload) => {
  const trySignin = () => signinWithFayda(payload);

  const trySignup = () => signupWithFayda(payload);

  const isUserNotFound = (err: unknown) => {
    if (!axios.isAxiosError(err)) return false;
    const status = err.response?.status;
    const data = err.response?.data as any;
    const code =
      typeof data?.code === "string"
        ? data.code
        : typeof data?.errorCode === "string"
          ? data.errorCode
          : typeof data?.message === "string"
            ? data.message
            : "";
    const codeLower = code.toLowerCase();
    return (
      status === 404 ||
      codeLower.includes("not_found") ||
      codeLower.includes("user_not_found") ||
      codeLower.includes("does_not_exist") ||
      codeLower.includes("not exist")
    );
  };

  try {
    return await trySignin();
  } catch (err) {
    if (!isUserNotFound(err)) throw err;
    return await trySignup();
  }
};

export interface EtradeSignupPayload {
  tin: string;
  licenseNumber: string;
}

export interface EtradeSigninPayload {
  licenseNumber: string;
}

/** @deprecated Use EtradeSigninPayload */
export interface RegisterWithEtradePayload {
  licenseNumber: string;
}

export type RegisterWithEtradeResponse = RegisterWithFaydaResponse;

export interface VerifyEtradeOtpPayload {
  licenseNo: string;
  otp: string;
}

export const registerWithEtrade = async (
  payload:
    | EtradeSigninPayload
    | EtradeSignupPayload
    | RegisterWithEtradePayload
    | { tin: string; licenseNo: string }
    | { licenseNo: string },
) => {
  const resolveLicenseNumber = () => {
    if ("licenseNumber" in payload) return payload.licenseNumber;
    if ("licenseNo" in payload) return payload.licenseNo;
    return payload.licenseNumber;
  };

  const trySignin = () =>
    signinWithEtrade({ licenseNumber: resolveLicenseNumber() });

  const trySignup = () => {
    if ("tin" in payload && ("licenseNumber" in payload || "licenseNo" in payload)) {
      return signupWithEtrade({
        tin: payload.tin,
        licenseNumber: resolveLicenseNumber(),
      });
    }
    return signupWithEtrade({
      tin: "",
      licenseNumber: resolveLicenseNumber(),
    });
  };

  const isUserNotFound = (err: unknown) => {
    if (!axios.isAxiosError(err)) return false;
    const status = err.response?.status;
    const data = err.response?.data as any;
    const code =
      typeof data?.code === "string"
        ? data.code
        : typeof data?.errorCode === "string"
          ? data.errorCode
          : typeof data?.message === "string"
            ? data.message
            : "";
    const codeLower = code.toLowerCase();
    return (
      status === 404 ||
      codeLower.includes("not_found") ||
      codeLower.includes("user_not_found") ||
      codeLower.includes("does_not_exist") ||
      codeLower.includes("not exist")
    );
  };

  try {
    return await trySignin();
  } catch (err) {
    if (!isUserNotFound(err)) throw err;
    return await trySignup();
  }
};
