import axios from "axios";
import { AdminDatasourceInf } from "../admin_datasource";
import { Admin, AdminFormValues } from "./entities/admin_form_values";
import { APIUrl } from "../../../core/constants/api_url";
import { AdminModel } from "../../../domain/model/AdminModel";
import { UserRole } from "../../../core/constants/roles";
import {
  API_ROUTE_ADMIN,
  API_ROUTE_ADMIN_CHANGE_PASSWORD,
  API_ROUTE_ADMIN_GENERATE_RESET_CODE,
  API_ROUTE_ADMIN_RESET_PASSWORD,
  API_ROUTE_ADMIN_SIGNUP,
  API_ROUTE_ADMIN_WHOAMI,
} from "../../../core/constants/api_routes";
import { ResetPasswordValues } from "./entities/reset_password_values";

export class AdminDatasourceProd implements AdminDatasourceInf {
  /**
   * Registers a new admin using the provided form data.
   * @param form - The admin data to be registered.
   * @returns A promise that resolves when the admin is successfully registered.
   */
  async registerAdmin(form: AdminFormValues): Promise<void> {
    await axios.post(APIUrl + API_ROUTE_ADMIN_SIGNUP, {
      email: form.email,
      idTown: form.townAdmin,
      password: form.password,
      name: form.name,
      lastName: form.lastName,
    });
  }

  /**
   * Retrieves admin information using the provided token.
   * @param token - The token of the admin.
   * @returns A promise that resolves to an Admin object.
   */
  async getAdminInfo(token: string): Promise<Admin> {
    const { data } = await axios.get<AdminModel>(
      APIUrl + API_ROUTE_ADMIN_WHOAMI,
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      }
    );
    const admin: Admin = {
      email: data.email,
      name: data.name,
      lastName: data.lastName,
      role:
        data.role === UserRole.SUPERADMIN
          ? UserRole.SUPERADMIN
          : UserRole.ADMIN,
      idTown: data.idTown,
    };
    return admin;
  }

  /**
   * Changes the password of the admin.
   * @param token - The token of the admin.
   * @param prevPassword - The previous password.
   * @param newPassword - The new password.
   * @returns A promise that resolves when the password is successfully changed.
   */
  async changePassword(
    token: string,
    prevPassword: string,
    newPassword: string
  ): Promise<void> {
    await axios.post(
      APIUrl + API_ROUTE_ADMIN_CHANGE_PASSWORD,
      {
        prevPassword: prevPassword,
        newPassword: newPassword,
      },
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      }
    );
  }

  /**
   * Retrieves a list of admins by town ID.
   * @param idTown - The ID of the town.
   * @returns A promise that resolves to an array of Admin objects.
   */
  async getAdminsByTown(idTown: number): Promise<Admin[]> {
    const { data } = await axios.get<AdminModel[]>(
      APIUrl + API_ROUTE_ADMIN + `/${idTown}`
    );
    const admins: Admin[] = data.map((admin): Admin => {
      return {
        email: admin.email,
        idTown: admin.idTown,
        name: admin.name,
        lastName: admin.lastName,
        status: admin.status,
      };
    });
    return admins;
  }

  /**
   * Generates a reset code for the given email.
   * @param email - The email of the admin.
   * @returns A promise that resolves when the reset code is successfully generated.
   */
  async generateResetCode(email: string): Promise<void> {
    await axios.post(APIUrl + API_ROUTE_ADMIN_GENERATE_RESET_CODE, {
      email: email,
    });
  }

  /**
   * Resets the password using the provided form data.
   * @param form - The reset password form values.
   * @returns A promise that resolves when the password is successfully reset.
   */
  async resetPassword(form: ResetPasswordValues): Promise<void> {
    await axios.post(APIUrl + API_ROUTE_ADMIN_RESET_PASSWORD, {
      email: form.email,
      resetCode: form.code,
      newPassword: form.newPassword,
    });
  }
}
