import axios from "axios";
import Config from "../models/config";
import * as env from "../config/env.config";
import * as loggers from "../common/logger";
import BancamigaPagoMovil from "../models/bancamigaPagoMovil";

const accessTokenDefault =
  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE4MDYyNDE4MjcsImlhdCI6MTc0NDAzMzgyN30.tCe4aaOapv43ni5K1KfR9qPLajYl0_dxwYQlF9KEwOg";

const bancamigaApiUrl = env.BANCAMIGA_API_URL;
const bancamigaUsername = env.BANCAMIGA_USER;
const bancamigaPassword = env.BANCAMIGA_PASSWORD;

export const getToken = async () => {
  try {
    const accessToken = await Config.findOne({ key: "bancamiga-access-token" });

    if (accessToken) {
      return {
        success: true,
        message: "Se ha obtenido un nuevo token exitosamente",
        data: accessToken.value,
      };
    }
    // Hacemos la petición
    const response = await axios.post(
      bancamigaApiUrl + "/public/auth/security/users/token",
      { Dni: bancamigaUsername, Pass: bancamigaPassword },
      {
        headers: {
          Authorization: `Bearer ${accessTokenDefault}`,
        },
        validateStatus: () => true,
      }
    );

    if (response.status === 200) {
      const tokenConfig = {
        key: "bancamiga-access-token",
        description: "Bancamiga Access Token",
        value: response.data.token,
        type: "string",
      };
      await Config.create(tokenConfig);

      const refreshTokenConfig = {
        key: "bancamiga-refresh-token",
        description: "Bancamiga Refresh Token",
        value: response.data.refresToken,
        type: "string",
      };

      await Config.create(refreshTokenConfig);

      return {
        success: true,
        message: "Se ha obtenido un nuevo token exitosamente",
        data: response.data.token,
      };
    } else {
      return {
        success: false,
        message: "No se pudo obtener el token.",
        data: response.data,
      };
    }
  } catch (error) {
    return {
      success: false,
      message: "Ocurrió un error al obtener el token.",
      data: null,
      error,
    };
  }
};

export const refreshToken = async () => {
  try {
    const accessTokenConfig = await Config.findOne({
      key: "bancamiga-access-token",
    });
    const refreshTokenConfig = await Config.findOne({
      key: "bancamiga-refresh-token",
    });

    if (!refreshTokenConfig || !accessTokenConfig) {
      const result = await getToken();
      return result;
    }

    const response = await axios.post(
      bancamigaApiUrl + "/public/re/refresh",
      { refresh_token: refreshTokenConfig.value },
      {
        validateStatus: () => true,
      }
    );

    if (response.status !== 200) {
      return {
        success: false,
        message: "No se pudo refrescar el token.",
        data: response.data,
      };
    }

    accessTokenConfig.value = response.data.token;
    await accessTokenConfig.save();

    refreshTokenConfig.value = response.data.refresToken;
    await refreshTokenConfig.save();

    return {
      success: true,
      message: "Se ha refrescado el token exitosamente",
      data: response.data.token,
    };
  } catch (error) {
    return {
      success: false,
      message: "Ocurrió un error al refrescar el token.",
      data: null,
      error,
    };
  }
};

export const findPaymentMobile = async (
  body: env.BancamigaFindPaymentMobileBody
) => {
  const resultToken = await getToken();
  if (!resultToken.success) {
    return resultToken;
  }

  const token = resultToken.data;

  loggers.bancamiga(`Request Pago movil: ${JSON.stringify(body)}`);
  const response = await axios.post(
    bancamigaApiUrl + "/public/protected/pm/find",
    {
      Phone: body.phone,
      Bank: body.bank,
      Date: body.date,
    },
    {
      headers: {
        Authorization: `Bearer ${token}`,
      },
      validateStatus: () => true,
    }
  );
  loggers.bancamiga(`Respuesta Pago movil: ${JSON.stringify(response.data)}`);

  if (response.status !== 200 || !response.data) {
    return {
      success: false,
      message: "No se pudo confirmar la transacción.",
      data: response.data,
    };
  }

  const transaction = response.data.lista.find(
    (t: env.BancamigaPagoMovil) =>
      t.NroReferenciaCorto === body.reference &&
      (t.Amount === body.amount || env.TESTING)
  ) as env.BancamigaPagoMovil | undefined;

  if (!transaction) {
    return {
      success: false,
      message: "No se encontró la transacción.",
      data: response.data,
    };
  }

  const config = await Config.findOne({ key: "ignore-payment-exists" })
    .lean()
    .exec();

  if (!config?.value) {
    const existsTransaction = await BancamigaPagoMovil.exists({
      ID: transaction.ID,
    });

    if (existsTransaction) {
      return {
        success: false,
        message: "La transacción ya se encuentra registrada.",
        data: null,
      };
    }
  }

  await BancamigaPagoMovil.create(transaction);

  return {
    success: true,
    message: "Transacción confirmada exitosamente",
    data: transaction,
  };
};
