<script setup>
import { computed, ref, watch } from "vue";
import { apiURL, useApi } from "@/services/Api.js";

import ShowModal from "@Holos/Modal/Show.vue";
import Input from "@Holos/Form/Input.vue";
import Selectable from "@Holos/Form/Selectable.vue";

const props = defineProps({
  show: Boolean,
  memberId: [Number, String],
});

const emit = defineEmits(["close", "charged"]);

const api = useApi();
const loadingConcepts = ref(false);
const processing = ref(false);
const conceptOptions = ref([]);
const selectedConcept = ref(null);
const quantity = ref(1);
const unitAmountInPeso = ref(null);
const totalAmountInPeso = ref(null);
const loadingUnitAmountInPeso = ref(false);
const loadingTotalAmountInPeso = ref(false);
const umaConversionCache = ref({});

const unitAmount = computed(() => {
  if (!selectedConcept.value) return 0;

  return parseFloat(
    selectedConcept.value.unit_cost_peso ?? selectedConcept.value.unit_cost_uma ?? 0
  );
});

const isPesoCharge = computed(() =>
  selectedConcept.value?.charge_type?.startsWith("peso_")
);

const unitAmountLabel = computed(() => {
  if (!selectedConcept.value || !unitAmount.value) return "No definido";

  if (isPesoCharge.value) {
    return `$${unitAmount.value.toLocaleString("es-MX", {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    })}`;
  }

  return `${unitAmount.value.toLocaleString("es-MX", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  })} UMA`;
});

const totalLabel = computed(() => {
  const total = unitAmount.value * (parseInt(quantity.value, 10) || 1);

  if (!selectedConcept.value || !total) return "No definido";

  if (isPesoCharge.value) {
    return `$${total.toLocaleString("es-MX", {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    })}`;
  }

  return `${total.toLocaleString("es-MX", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  })} UMA`;
});

const totalUmaAmount = computed(
  () => unitAmount.value * (parseInt(quantity.value, 10) || 1)
);

const unitAmountInPesoLabel = computed(() => {
  if (unitAmountInPeso.value == null) return "";

  return `$${Number(unitAmountInPeso.value).toLocaleString("es-MX", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  })}`;
});

const totalAmountInPesoLabel = computed(() => {
  if (totalAmountInPeso.value == null) return "";

  return `$${Number(totalAmountInPeso.value).toLocaleString("es-MX", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  })}`;
});

function resetForm() {
  selectedConcept.value = null;
  quantity.value = 1;
  unitAmountInPeso.value = null;
  totalAmountInPeso.value = null;
}

async function loadConceptOptions() {
  loadingConcepts.value = true;

  await api.get(apiURL("charge-concepts"), {
    params: {
      type: "membership",
    },
    onSuccess: (data) => {
      conceptOptions.value =
        data.models?.data || data.data || data.models || data || [];
    },
    onFail: (error) => {
      Notify.warning(error.message || "No se pudieron cargar los conceptos");
      conceptOptions.value = [];
    },
    onError: () => {
      Notify.error("Error al cargar los conceptos");
      conceptOptions.value = [];
    },
    onFinish: () => {
      loadingConcepts.value = false;
    },
  });
}

watch(
  () => props.show,
  async (show) => {
    if (show) {
      resetForm();
      await loadConceptOptions();
      return;
    }

    resetForm();
  }
);

async function calculateUmaToPeso(value, targetRef, loadingRef) {
  const numericValue = Number(value);

  if (!numericValue || Number.isNaN(numericValue)) {
    targetRef.value = null;
    return;
  }

  const cacheKey = numericValue.toString();

  if (umaConversionCache.value[cacheKey] != null) {
    targetRef.value = umaConversionCache.value[cacheKey];
    return;
  }

  loadingRef.value = true;

  await api.post(apiURL("charge-concepts/calculate-uma"), {
    data: {
      value: numericValue,
    },
    onSuccess: (data) => {
      umaConversionCache.value[cacheKey] = data.result;
      targetRef.value = data.result;
    },
    onFail: () => {
      targetRef.value = null;
    },
    onError: () => {
      targetRef.value = null;
    },
    onFinish: () => {
      loadingRef.value = false;
    },
  });
}

watch(
  () => [props.show, isPesoCharge.value, unitAmount.value],
  async ([show, isPesoChargeValue]) => {
    if (!show || isPesoChargeValue || !selectedConcept.value) {
      unitAmountInPeso.value = null;
      return;
    }

    await calculateUmaToPeso(
      unitAmount.value,
      unitAmountInPeso,
      loadingUnitAmountInPeso
    );
  },
  { immediate: true }
);

watch(
  () => [props.show, isPesoCharge.value, totalUmaAmount.value],
  async ([show, isPesoChargeValue]) => {
    if (!show || isPesoChargeValue || !selectedConcept.value) {
      totalAmountInPeso.value = null;
      return;
    }

    await calculateUmaToPeso(
      totalUmaAmount.value,
      totalAmountInPeso,
      loadingTotalAmountInPeso
    );
  },
  { immediate: true }
);

async function submitCharge() {
  if (!props.memberId) {
    Notify.warning("Primero debes buscar un miembro");
    return;
  }

  if (!selectedConcept.value?.id) {
    Notify.warning("Selecciona un concepto");
    return;
  }

  const numericQuantity = parseInt(quantity.value, 10) || 0;

  if (numericQuantity <= 0) {
    Notify.warning("La cantidad debe ser mayor a 0");
    return;
  }

  processing.value = true;

  await api.put(apiURL(`members/${props.memberId}/charge-membership`), {
    data: {
      charge_concept_id: selectedConcept.value.id,
      quantity: numericQuantity,
    },
    onSuccess: (response) => {
      Notify.success("Cobro registrado correctamente");
      emit("charged", response);
      emit("close");
    },
    onFail: (error) => {
      Notify.warning(error.message || "No se pudo registrar el cobro");
    },
    onError: () => {
      Notify.error("Error al registrar el cobro");
    },
    onFinish: () => {
      processing.value = false;
    },
  });
}
</script>

<template>
  <ShowModal
    :show="show"
    title="Agregar cobro"
    @close="emit('close')"
  >
    <div class="space-y-4 p-4">
      <Selectable
        v-model="selectedConcept"
        label="name"
        :options="conceptOptions"
        title="Concepto"
        :disabled="loadingConcepts || processing"
        :placeholder="
          loadingConcepts ? 'Cargando conceptos...' : 'Selecciona un concepto'
        "
        required
      />

      <Input
        v-model="quantity"
        id="Cantidad"
        type="number"
        min="1"
        :disabled="processing"
        required
      />

      <div class="grid gap-4 md:grid-cols-2">
        <div>
          <Input
            :model-value="unitAmountLabel"
            id="Costo unitario"
            type="text"
            disabled
          />
          <p
            v-if="selectedConcept && !isPesoCharge && loadingUnitAmountInPeso"
            class="mt-1 text-xs text-gray-500"
          >
            Calculando equivalente en pesos...
          </p>
          <p
            v-else-if="selectedConcept && !isPesoCharge && unitAmountInPesoLabel"
            class="mt-1 text-xs font-medium text-emerald-700"
          >
            Equivalente en pesos: {{ unitAmountInPesoLabel }}
          </p>
        </div>

        <div>
          <Input
            :model-value="isPesoCharge ? totalLabel : totalAmountInPesoLabel || 'No definido'"
            id="Monto estimado"
            type="text"
            disabled
          />
          <p
            v-if="selectedConcept && !isPesoCharge"
            class="mt-1 text-xs text-gray-500"
          >
            <span v-if="loadingTotalAmountInPeso">
              Calculando monto en pesos...
            </span>
            <span v-else>
              Referencia en UMA: {{ totalLabel }}
            </span>
          </p>
        </div>
      </div>
    </div>

    <template #buttons>
      <button
        type="button"
        class="rounded-md bg-primary px-4 py-2 text-sm font-semibold text-white transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50"
        :disabled="processing || loadingConcepts"
        @click="submitCharge"
      >
        {{ processing ? "Registrando..." : "Agregar cobro" }}
      </button>
    </template>
  </ShowModal>
</template>
