<template>
  <q-dialog
    ref="dialogRef"
    maximized
    persistent
    transition-hide="slide-down"
    transition-show="slide-up"
  >
    <div class="bg-page full-height column no-shadow">
      <div class="row items-center q-px-md q-pt-md q-pb-sm bg-white shadow-profile bg-surface">
        <q-btn
          class="header-back-btn"
          color="primary"
          dense
          flat
          icon="mdi-chevron-left"
          round
          @click="onDialogCancel"
        />

        <q-space />

        <span class="text-subtitle1 text-primary font16 fontbold gradient-diarista">
          {{ $t('profile.payments.title') }}
        </span>

        <q-space />

        <div style="width: 32px"></div>
      </div>

      <div class="col overflow-auto q-px-md q-pt-lg q-pb-xl">
        <div class="text-h6 text-primary q-mb-md font16 fontbold gradient-diarista" style="text-transform: capitalize;">
          {{ paymentMethod ? $t('profile.payments.edit_title') : $t('profile.payments.add_card') }}
        </div>

        <div class="virtual-card q-mb-xl">
          <div class="card-top-row row items-start justify-between">
            <span class="card-brand-label">
              {{ brandDisplayName }}
            </span>

            <q-icon
              class="nfc-icon"
              color="white"
              name="mdi-wifi-strength-4"
              size="24px"
              style="transform: rotate(90deg);"
            />
          </div>

          <div class="card-number-preview">
            {{ maskedCardNumberPreview }}
          </div>

          <div class="card-bottom-row row items-end justify-between">
            <div class="column">
              <span class="card-holder-name">
                {{ form.holder_name || 'Nome do Titular' }}
              </span>
            </div>

            <div class="column items-end">
              <span class="card-expiry">
                {{ form.expiration || '**/****' }}
              </span>
            </div>
          </div>
        </div>

        <q-form
          ref="formRef"
          class="column q-gutter-y-sm text-text"
          @submit="onOKClick"
        >
          <div>
            <div class="input-label font14 fontbold">
              {{ $t('profile.payments.card_number') }}
            </div>

            <q-input
              v-model="form.card_number"
              class="bg-surface input-border-dark"
              hide-bottom-space
              input-class="text-text"
              mask="#### #### #### ####"
              outlined
              unmasked-value
              :error="!!serverErrors.card_number"
              :error-message="serverErrors.card_number"
              :rules="cardNumberRules"
              @update:model-value="onCardNumberChange"
            />
          </div>

          <div class="q-pt-lg">
            <div class="input-label font14 fontbold">
              {{ $t('profile.payments.holder_name') }}
            </div>

            <q-input
              v-model="form.holder_name"
              class="bg-surface input-border-dark"
              hide-bottom-space
              input-class="text-text"
              outlined
              placeholder="Nome como está no cartão"
              :error="!!serverErrors.holder_name"
              :error-message="serverErrors.holder_name"
              :rules="[inputRules.requiredHideMessage]"
              @update:model-value="serverErrors.holder_name = null"
            />
          </div>

          <div class="row col-12 q-col-gutter-sm q-pt-lg">
            <div class="col-7">
              <div class="input-label font14 fontbold">
                {{ $t('profile.payments.expiration') }}
              </div>

              <q-input
                v-model="form.expiration"
                class="col bg-surface input-border-dark"
                hide-bottom-space
                input-class="text-text"
                mask="##/##"
                outlined
                :error="!!serverErrors.expiration"
                :error-message="serverErrors.expiration"
                :placeholder="$t('profile.payments.mmyyyy')"
                :rules="[inputRules.requiredHideMessage, validateExpiration]"
                @update:model-value="serverErrors.expiration = null"
              />
            </div>

            <div class="col-5">
              <div class="input-label row items-center q-gutter-x-xs font14 fontbold">
                <span>
                  {{ $t('profile.payments.cvv') }}
                </span>

                <q-icon
                  class="cursor-pointer"
                  color="grey-8"
                  name="mdi-help-circle-outline"
                  size="16px"
                >
                  <q-tooltip>
                    {{ $t('profile.payments.cvv_help') }}
                  </q-tooltip>
                </q-icon>
              </div>

              <q-input
                v-model="form.cvv"
                class="col bg-surface input-border-dark"
                hide-bottom-space
                input-class="text-text"
                mask="####"
                outlined
                placeholder="***"
                type="text"
                unmasked-value
                :error="!!serverErrors.cvv"
                :error-message="serverErrors.cvv"
                :rules="cvvRules"
                @update:model-value="serverErrors.cvv = null"
              />
            </div>
          </div>

          <div class="row items-center justify-center q-gutter-x-xs q-mt-sm q-mb-xs">
            <q-icon
              color="positive"
              name="mdi-shield-check"
              size="18px"
            />

            <span class="security-text-new font12 fontmedium">
              {{ $t('profile.payments.security_badge') }}
            </span>
          </div>

          <q-btn
            class="full-width"
            color="primary"
            no-caps
            padding="8px 12px"
            rounded
            type="submit"
            unelevated
            :disable="!hasUpdatedFields"
            :label="paymentMethod ? $t('profile.payments.save_btn') : $t('profile.payments.add_card')"
            :loading="loading || tokenizing"
          />
        </q-form>
      </div>
    </div>
  </q-dialog>
</template>

<script setup>
import { computed, ref } from 'vue';

import { useDialogPluginComponent, useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';

import { createClientPaymentMethod, updateClientPaymentMethod } from 'src/api/clientPaymentMethod';

import { useFormUpdateTracker } from 'src/composables/useFormUpdateTracker';
import { useInputRules } from 'src/composables/useInputRules';
import { useSubmitHandler } from 'src/composables/useSubmitHandler';

import { detectCardBrand, validateCardExpiration } from 'src/helpers/utils';

const props = defineProps({
  clientId: {
    required: true,
    type: Number,
  },

  paymentMethod: {
    default: null,
    type: Object,
  },
});

defineEmits([...useDialogPluginComponent.emits]);

const $q = useQuasar();

const { dialogRef, onDialogCancel, onDialogOK } = useDialogPluginComponent();

const { inputRules } = useInputRules();

const { t } = useI18n();

const { form, hasUpdatedFields } = useFormUpdateTracker({
  brand: props.paymentMethod ? props.paymentMethod.brand : null,
  card_name: props.paymentMethod ? props.paymentMethod.card_name : null,
  card_number: null,
  client_id: props.paymentMethod ? props.paymentMethod.client_id : props.clientId,
  cvv: null,

  expiration: props.paymentMethod
    ? (
      props.paymentMethod.expiration?.includes('/')
      && props.paymentMethod.expiration.split('/')[1].length === 2
        ? `${props.paymentMethod.expiration.split('/')[0]}/20${props.paymentMethod.expiration.split('/')[1]}`
        : props.paymentMethod.expiration
    )
    : null,

  holder_name: props.paymentMethod ? props.paymentMethod.holder_name : null,
  is_active: props.paymentMethod ? props.paymentMethod.is_active : true,
  last_four_digits: props.paymentMethod ? props.paymentMethod.last_four_digits : null,
});

const {
  execute: submitForm,
  loading,
  serverErrors,
} = useSubmitHandler(() => onDialogOK(true));

const formRef = ref(null);

const tokenizing = ref(false);

const brandDisplayName = computed(() => {
  if (!form.brand) {
    return '';
  }

  const names = {
    diners: 'Diners',
    discover: 'Discover',
    elo: 'Elo',
    hipercard: 'Hipercard',
    mastercard: 'Mastercard',
    visa: 'VISA',
  };

  return names[form.brand] ?? form.brand;
});

const cardNumberRules = computed(() => (
  props.paymentMethod
    ? []
    : [inputRules.requiredHideMessage]
));

const cvvRules = computed(() => (
  props.paymentMethod
    ? []
    : [inputRules.requiredHideMessage]
));

const expirationMonth = computed(() => (
  form.expiration
    ? form.expiration.split('/')[0]
    : ''
));

const expirationYear = computed(() => (
  form.expiration
    ? form.expiration.split('/')[1]
    : ''
));

const maskedCardNumberPreview = computed(() => {
  const raw = form.card_number
    ? String(form.card_number).replace(/\D/g, '')
    : '';

  if (raw && !raw.includes('*')) {
    const lastFour = raw.slice(-4).padStart(4, '*');

    return `**** **** **** ${lastFour}`;
  }

  if (form.last_four_digits) {
    return `**** **** **** ${String(form.last_four_digits).padStart(4, '*')}`;
  }

  return '**** **** **** ****';
});

const pagarmeCardNumber = computed(() => (
  form.card_number
    ? String(form.card_number).replace(/\D/g, '')
    : ''
));

const pagarmeCvv = computed(() => (
  form.cvv
    ? String(form.cvv).replace(/\D/g, '')
    : ''
));

const pagarmeExpirationMonth = computed(() => expirationMonth.value);

// Pagar.me espera o ano com 2 digitos (YY)
const pagarmeExpirationYear = computed(() => {
  const year = expirationYear.value || '';

  return year.length === 4 ? year.slice(-2) : year;
});

const getPagarmePublicKey = () => (
  process.env.PAGARME_PUBLIC_KEY
);

const onCardNumberChange = () => {
  serverErrors.value.card_number = null;

  const raw = form.card_number
    ? String(form.card_number).replace(/\D/g, '')
    : '';

  if (!raw) {
    form.brand = null;
    form.last_four_digits = null;

    return;
  }

  if (raw.length >= 6 && !String(form.card_number).includes('*')) {
    const brand = detectCardBrand(raw);

    if (brand) {
      form.brand = brand;
    }

    if (raw.length >= 4) {
      form.last_four_digits = raw.slice(-4);
    }
  }
};

const tokenizeCard = async () => {
  const publicKey = getPagarmePublicKey();

  if (!publicKey) {
    throw new Error('PAGARME_PUBLIC_KEY não configurada');
  }

  const url = `https://api.pagar.me/core/v5/tokens?appId=${encodeURIComponent(publicKey)}`;

  const payload = {
    card: {
      cvv: pagarmeCvv.value,
      exp_month: Number(pagarmeExpirationMonth.value),
      exp_year: Number(pagarmeExpirationYear.value),
      holder_name: form.holder_name,
      number: pagarmeCardNumber.value,
    },
    type: 'card',
  };

  let response;

  try {
    response = await fetch(url, {
      body: JSON.stringify(payload),
      headers: { 'Content-Type': 'application/json' },
      method: 'POST',
    });
  } catch (error) {
    throw new Error(`Falha de rede ao tokenizar o cartão: ${error?.message || error}`);
  }

  const data = await response.json().catch(() => ({}));

  if (!response.ok || !data?.id) {
    const detail = data?.message
      || (data?.errors ? JSON.stringify(data.errors) : JSON.stringify(data));

    throw new Error(`Pagar.me recusou a tokenização (${response.status}): ${String(detail).slice(0, 200)}`);
  }

  return data.id;
};

const validateExpiration = (val) => {
  if (!val) {
    return true;
  }

  const [month, year] = val.split("/");

  if (!month || !year) {
    return t("profile.payments.expired_card");
  }

  return validateCardExpiration(`${month}/20${year}`)
    ? true
    : t("profile.payments.expired_card");
};

//

const onOKClick = async () => {
  const valid = await formRef.value?.validate();
  const expirationFormatted = (() => {
  const [month, year] = form.expiration.split("/");

  return `${month}/20${year}`;
})();

  if (!valid) {
    return;
  }

  if (props.paymentMethod) {
    const payload = {
      brand: form.brand,
      card_name: form.card_name,
      client_id: props.paymentMethod ? props.paymentMethod.client_id : props.clientId,
      expiration: expirationFormatted,
      holder_name: form.holder_name,
      is_active: form.is_active,
      last_four_digits: form.last_four_digits,
    }

    await submitForm(() => updateClientPaymentMethod(props.paymentMethod.id, payload));

    return;
  }

  tokenizing.value = true;

  try {
    const token = await tokenizeCard();

    const payload = {
      client_id: props.paymentMethod ? props.paymentMethod.client_id : props.clientId,
      expiration: expirationFormatted,
      holder_name: form.holder_name,
      last_four_digits: form.last_four_digits,
      token,
    };

    await submitForm(() => createClientPaymentMethod(payload));
  } catch (error) {
    console.error('Erro ao tokenizar o cartão:', error);

    $q.notify({
      message: error instanceof Error
        ? error.message
        : 'Não foi possível tokenizar o cartão.',
      type: 'negative',
    });
  } finally {
    tokenizing.value = false;
  }
};
</script>

<style scoped lang="scss">
.shadow-profile {
  box-shadow: 0px 1px 8px rgba(0, 0, 0, 0.1);
}

.virtual-card {
  background: linear-gradient(135deg, #6c3fc5 0%, #9c27b0 100%);
  border-radius: 20px;
  padding: 20px 24px;
  min-height: 180px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-shadow: 0 8px 24px rgba(108, 63, 197, 0.4);
  color: white;
}

.nfc-icon {
  opacity: 0.85;
}

.card-brand-label {
  letter-spacing: 1px;
  opacity: 0.9;
}

.card-number-preview {
  letter-spacing: 3px;
  text-align: center;
  margin: 12px 0;
}

.card-label-sm {
  opacity: 0.7;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.card-holder-name {
  text-transform: uppercase;
  letter-spacing: 1px;
}

.card-expiry {
  letter-spacing: 1px;
}

.input-label {
  color: #444;
  margin-bottom: 2px;
}

.input-border-dark :deep(.q-field__control:before) {
  border: 1px solid #afafaf !important;
  opacity: 1 !important;
}

.input-border-dark :deep(.q-field__control:after) {
  border-color: #666 !important;
  opacity: 1 !important;
}

.input-border-dark :deep(.q-field__control) {
  border-radius: 6px !important;
}

.security-text-new {
  color: #555;
}

</style>
