<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";

const props = defineProps({
  show: Boolean,
  membership: Object,
  loading: Boolean,
});

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

const api = useApi();
const quantity = ref(1);
const unitAmountInPeso = ref(null);
const totalAmountInPeso = ref(null);
const loadingUnitAmountInPeso = ref(false);
const loadingTotalAmountInPeso = ref(false);
const umaConversionCache = ref({});

const hasExpiration = computed(() => Boolean(props.membership?.expires_at));

const isNoExpires = computed(() => props.membership?.status === "no_expires");

const isExpired = computed(() => {
  if (!props.membership || isNoExpires.value || !props.membership.expires_at) {
    return false;
  }

  return new Date(props.membership.expires_at) <= new Date();
});

const daysUntilExpiration = computed(() => {
  if (!props.membership || isNoExpires.value || !props.membership.expires_at) {
    return null;
  }

  const expirationDate = new Date(props.membership.expires_at);
  const now = new Date();
  const diffTime = expirationDate - now;

  return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
});

const statusLabel = computed(() => {
  if (isNoExpires.value) return "Sin vencimiento";
  if (isExpired.value || props.membership?.status === "expired") return "Vencida";
  if (props.membership?.status === "active") return "Activa";
  return props.membership?.status || "Sin estatus";
});

const statusClasses = computed(() => {
  if (isNoExpires.value) return "bg-slate-100 text-slate-700";
  if (isExpired.value || props.membership?.status === "expired") {
    return "bg-red-100 text-red-700";
  }
  if (props.membership?.status === "active") {
    return "bg-green-100 text-green-700";
  }
  return "bg-gray-100 text-gray-700";
});

const formattedExpiration = computed(() => {
  if (!hasExpiration.value) return "No aplica";

  return new Date(props.membership.expires_at).toLocaleDateString("es-MX", {
    year: "numeric",
    month: "long",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
});

const unitAmount = computed(() => {
  const concept = props.membership?.charge_concept;
  if (!concept) return 0;

  return parseFloat(concept.unit_cost_peso ?? concept.unit_cost_uma ?? 0);
});

const isPesoCharge = computed(() =>
  props.membership?.charge_concept?.charge_type?.startsWith("peso_")
);

const unitAmountLabel = computed(() => {
  if (!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 (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 paymentsCount = computed(() => props.membership?.payments?.length || 0);

const expirationHint = computed(() => {
  if (!hasExpiration.value || isNoExpires.value || daysUntilExpiration.value == null) {
    return "No requiere renovación";
  }

  if (daysUntilExpiration.value < 0) {
    return "Membresía vencida";
  }

  if (daysUntilExpiration.value === 0) return "Vence hoy";
  if (daysUntilExpiration.value === 1) return "Vence mañana";

  return `Faltan ${daysUntilExpiration.value} días para que venza`;
});

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,
  })}`;
});

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, props.membership?.id],
  () => {
    quantity.value = 1;
    unitAmountInPeso.value = null;
    totalAmountInPeso.value = null;
  }
);

watch(
  () => [props.show, isPesoCharge.value, unitAmount.value],
  async ([show, isPesoChargeValue]) => {
    if (!show || isPesoChargeValue) {
      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) {
      totalAmountInPeso.value = null;
      return;
    }

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

function submitPayment() {
  emit("pay", { quantity: parseInt(quantity.value, 10) || 1 });
}
</script>

<template>
  <ShowModal
    :show="show"
    :title="membership?.charge_concept?.name || 'Detalle de membresía'"
    @close="emit('close')"
  >
    <div v-if="membership" class="space-y-4 p-4">
      <div class="flex items-center justify-between gap-4 rounded-lg bg-gray-50 p-4">
        <div>
          <p class="text-xs uppercase tracking-wide text-gray-500">Estatus</p>
          <p class="mt-1 text-sm font-semibold text-gray-900">
            {{ membership.status || "Sin estatus" }}
          </p>
          <p class="mt-1 text-xs" :class="isExpired ? 'text-red-600' : 'text-green-700'">
            {{ expirationHint }}
          </p>
        </div>
        <span
          class="rounded-full px-3 py-1 text-xs font-semibold"
          :class="statusClasses"
        >
          {{ statusLabel }}
        </span>
      </div>

      <div class="grid gap-4 md:grid-cols-2">
        <Input
          :model-value="membership.charge_concept?.name || ''"
          id="Concepto"
          type="text"
          disabled
        />
        <Input
          :model-value="membership.charge_concept?.short_name || ''"
          id="Clave"
          type="text"
          disabled
        />
        <Input
          :model-value="membership.charge_concept?.charge_type || ''"
          id="Tipo de cobro"
          type="text"
          disabled
        />
        <Input
          :model-value="formattedExpiration"
          id="Vencimiento"
          type="text"
          disabled
        />
        <div>
          <Input
            :model-value="unitAmountLabel"
            id="Costo unitario"
            type="text"
            disabled
          />
          <p
            v-if="!isPesoCharge && loadingUnitAmountInPeso"
            class="mt-1 text-xs text-gray-500"
          >
            Calculando equivalente en pesos...
          </p>
          <p
            v-else-if="!isPesoCharge && unitAmountInPesoLabel"
            class="mt-1 text-xs font-medium text-emerald-700"
          >
            Equivalente en pesos: {{ unitAmountInPesoLabel }}
          </p>
        </div>
        <Input
          :model-value="String(paymentsCount)"
          id="Pagos registrados"
          type="text"
          disabled
        />
      </div>

      <div
        v-if="isExpired"
        class="space-y-4 rounded-xl border border-red-200 bg-red-50 p-4"
      >
        <p class="text-sm font-medium text-red-700">
          La membresía está vencida. Puedes registrar un nuevo pago para renovarla.
        </p>

        <div class="grid gap-4 md:grid-cols-2">
          <Input
            v-model="quantity"
            id="Cantidad"
            type="number"
            min="1"
            :disabled="loading"
          />
          <div>
            <Input
              :model-value="isPesoCharge ? totalLabel : totalAmountInPesoLabel"
              id="Monto estimado"
              type="text"
              disabled
            />
            <p
              v-if="!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>

      <div
        v-else-if="isNoExpires"
        class="rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm text-slate-700"
      >
        Esta membresía no tiene fecha de vencimiento, por lo que no requiere renovación.
      </div>

      <div
        v-else
        class="rounded-xl border border-green-200 bg-green-50 p-4 text-sm text-green-700"
      >
        Esta membresía sigue activa y no requiere pago por el momento.
      </div>
    </div>

    <template #buttons>
      <button
        v-if="membership && isExpired"
        type="button"
        class="rounded-md bg-green-700 px-4 py-2 text-sm font-semibold text-white transition hover:bg-green-600 disabled:cursor-not-allowed disabled:opacity-50"
        :disabled="loading"
        @click="submitPayment"
      >
        {{ loading ? "Procesando..." : "Renovar membresía" }}
      </button>
    </template>
  </ShowModal>
</template>
