<template>
  <q-dialog ref="dialogRef" @hide="onDialogHide">
    <div style="width: 100%; max-width: 700px">
      <q-card
        class="dialog-form-card"
        style="width: 100%"
      >
        <DefaultDialogHeader
          :title="props.package ? 'Editar Pacote' : 'Novo Pacote'"
          @close="onDialogCancel"
        />

        <DefaultForm
          ref="formRef"
          @submit="onOKClick"
        >
          <q-scroll-area
            ref="scrollAreaRef"
            class="dialog-form-scroll"
          >
            <q-card-section class="q-pt-sm">
              <div class="row q-col-gutter-sm">
                <DefaultInput
                  v-model="form.name"
                  v-model:error="validationErrors.name"
                  class="col-12"
                  label="Nome do Pacote"
                  :rules="[inputRules.required]"
                />

                <DefaultInput
                  v-model="form.quantity_classes"
                  v-model:error="validationErrors.quantity_classes"
                  class="col-12"
                  label="Quantidade de Aulas"
                  type="number"
                  :rules="[inputRules.required, inputRules.minValue(1)]"
                />

                <DefaultInput
                  v-model="form.class_duration_hours"
                  v-model:error="validationErrors.class_duration_minutes"
                  class="col-12"
                  label="Duração da Aula (horas)"
                  max="24"
                  min="0.5"
                  step="0.5"
                  type="number"
                  :rules="[
                    inputRules.required,
                    inputRules.minValue(0.5),
                    inputRules.maxValue(24),
                  ]"
                />

                <div class="col-12 package-duration-hint">
                  A duração padrão das aulas é de 2 horas e pode ser alterada se
                  necessário. É possível configurar no máximo dois dias.
                </div>

                <DefaultSelect
                  v-model="form.weekday"
                  class="col-4"
                  clearable
                  emit-value
                  label="1º Dia da Semana"
                  map-options
                  option-label="label"
                  option-value="value"
                  :options="weekdays"
                  :rules="form.start_time ? [inputRules.required] : []"
                />

                <DefaultInput
                  v-model="form.start_time"
                  class="col-4"
                  label="Horário Inicial"
                  mask="##:##"
                  :rules="
                    form.weekday !== null
                      ? [inputRules.required]
                      : []
                  "
                />

                <DefaultInput
                  :model-value="firstEndTime"
                  class="col-4"
                  disable
                  label="Horário Final"
                />

                <DefaultSelect
                  v-model="form.second_weekday"
                  class="col-4"
                  clearable
                  emit-value
                  label="2º Dia da Semana"
                  map-options
                  option-label="label"
                  option-value="value"
                  :options="secondWeekdayOptions"
                  :rules="
                    form.second_start_time
                      ? [inputRules.required]
                      : []
                  "
                />

                <DefaultInput
                  v-model="form.second_start_time"
                  class="col-4"
                  label="Horário Inicial do 2º dia"
                  mask="##:##"
                  :rules="
                    form.second_weekday !== null
                      ? [inputRules.required]
                      : []
                  "
                />

                <DefaultInput
                  :model-value="secondEndTime"
                  class="col-4"
                  disable
                  label="Horário Final do 2º dia"
                />

                <DefaultCurrencyInput
                  v-model="form.contract_register_value"
                  v-model:error="validationErrors.contract_register_value"
                  class="col-4"
                  label="R$ Matrícula"
                  :rules="[inputRules.required]"
                />

                <DefaultCurrencyInput
                  v-model="form.contract_value"
                  v-model:error="validationErrors.contract_value"
                  class="col-4"
                  label="R$ Total do Contrato"
                  :rules="[inputRules.required]"
                />

                <DefaultInput
                  v-model="form.contrat_discount_value"
                  class="col-4"
                  label="Desconto em %"
                  max="100"
                  min="0"
                  type="number"
                />

                <div
                  v-for="(material, index) in form.materials"
                  :key="index"
                  class="col-12"
                >
                  <div class="row q-col-gutter-sm items-center">
                    <DefaultSelect
                      v-model="material.product_id"
                      class="col-4"
                      emit-value
                      label="Material"
                      map-options
                      :options="productOptions"
                      :rules="
                        material.product_id
                          ? [inputRules.required]
                          : []
                      "
                      @update:model-value="onProductSelected(material)"
                    />

                    <DefaultInput
                      v-model="material.quantity"
                      class="col-4"
                      label="Qtd"
                      min="1"
                      type="number"
                      :rules="
                        material.product_id
                          ? [
                              inputRules.required,
                              inputRules.minValue(1),
                            ]
                          : []
                      "
                    />

                    <DefaultCurrencyInput
                      v-model="material.price"
                      class="col"
                      label="R$ Unitário"
                      :rules="
                        material.product_id
                          ? [inputRules.required]
                          : []
                      "
                    />

                    <div class="col-auto">
                      <q-btn
                        v-if="index === form.materials.length - 1"
                        color="primary"
                        icon="mdi-plus"
                        style="
                          border-radius: 8px;
                          height: 40px;
                          width: 40px;
                        "
                        unelevated
                        @click="addMaterial"
                      />

                      <q-btn
                        v-else
                        color="negative"
                        dense
                        flat
                        icon="mdi-delete-outline"
                        round
                        @click="removeMaterial(index)"
                      />
                    </div>
                  </div>
                </div>
              </div>
            </q-card-section>
          </q-scroll-area>

          <q-card-actions
            align="right"
            class="q-px-md q-pb-md"
          >
            <q-btn
              color="primary"
              label="Cancelar"
              no-caps
              outline
              @click="onDialogCancel"
            />

            <q-btn
              color="primary"
              label="Salvar"
              no-caps
              type="submit"
              :loading="loading"
            />
          </q-card-actions>
        </DefaultForm>
      </q-card>
    </div>
  </q-dialog>
</template>

<script setup>
import {
  computed,
  onMounted,
  ref,
  useTemplateRef,
  watch,
} from "vue";

import {
  createUnitPackage,
  getUnitPackage,
  updateUnitPackage,
} from "src/api/package";

import { getProductsForSelect } from "src/api/product";
import { useDialogPluginComponent } from "quasar";
import { useForm } from "src/composables/useForm";
import { useInputRules } from "src/composables/useInputRules";
import { useScroll } from "src/composables/useScroll";
import { useSubmitHandler } from "src/composables/useSubmitHandler";

import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
import DefaultForm from "src/components/defaults/DefaultForm.vue";
import DefaultInput from "src/components/defaults/DefaultInput.vue";
import DefaultSelect from "src/components/defaults/DefaultSelect.vue";

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

const props = defineProps({
  package: {
    type: Object,
    default: null,
  },
});

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

const { inputRules } = useInputRules();
const { scrollToComponent } = useScroll();

const formRef = useTemplateRef("formRef");
const scrollAreaRef = useTemplateRef("scrollAreaRef");

const products = ref([]);

const firstEndTime = computed(() =>
  calculateEndTime(
    form.start_time,
    form.class_duration_hours,
  ),
);

const productOptions = computed(() =>
  products.value.map((product) => ({
    label: product.name,
    price_sale: product.price_sale,
    value: product.id,
  })),
);

const secondEndTime = computed(() =>
  calculateEndTime(
    form.second_start_time,
    form.class_duration_hours,
  ),
);

const secondWeekdayOptions = computed(() =>
  weekdays.filter(
    (weekday) => weekday.value !== form.weekday,
  ),
);

const weekdays = [
  {
    label: "Segunda",
    value: 1,
  },
  {
    label: "Terça",
    value: 2,
  },
  {
    label: "Quarta",
    value: 3,
  },
  {
    label: "Quinta",
    value: 4,
  },
  {
    label: "Sexta",
    value: 5,
  },
  {
    label: "Sábado",
    value: 6,
  },
  {
    label: "Domingo",
    value: 0,
  },
];

const trimTime = (time) =>
  time ? time.slice(0, 5) : null;

const { form, getUpdatedFields } = useForm({
  class_duration_hours:
    (props.package?.class_duration_minutes ?? 120) / 60,

  contract_register_value:
    props.package?.contract_register_value ?? null,

  contract_value: props.package?.contract_value ?? null,

  contrat_discount_value:
    props.package?.contrat_discount_value ?? null,

  materials: [
    {
      price: null,
      product_id: null,
      quantity: 1,
    },
  ],

  name: props.package?.name ?? null,
  quantity_classes: props.package?.quantity_classes ?? null,

  second_start_time: trimTime(
    props.package?.second_start_time,
  ),

  second_weekday: props.package?.second_weekday ?? null,
  start_time: trimTime(props.package?.start_time),
  weekday: props.package?.weekday ?? null,
});

const {
  loading,
  validationErrors,
  execute,
} = useSubmitHandler({
  containerRef: scrollAreaRef,
  formRef,
  onSuccess: (result) => {
    onDialogOK(result);
  },
  scrollFn: scrollToComponent,
});

const addMaterial = () => {
  form.materials.push({
    price: null,
    product_id: null,
    quantity: 1,
  });
};

const calculateEndTime = (startTime, durationHours) => {
  if (!/^\d{2}:\d{2}$/.test(startTime ?? "")) {
    return null;
  }

  const [hours, minutes] = startTime
    .split(":")
    .map(Number);

  if (hours > 23 || minutes > 59) {
    return null;
  }

  const durationMinutes = Math.round(
    Number(durationHours) * 60,
  );

  const endMinutes =
    (hours * 60 + minutes + durationMinutes) %
    (24 * 60);

  return `${String(
    Math.floor(endMinutes / 60),
  ).padStart(2, "0")}:${String(
    endMinutes % 60,
  ).padStart(2, "0")}`;
};

const onOKClick = async () => {
  const validMaterials = form.materials.filter(
    (material) => material.product_id,
  );

  const payload = {
    class_duration_minutes: Math.round(
      Number(form.class_duration_hours) * 60,
    ),

    contract_register_value:
      form.contract_register_value,

    contract_value: form.contract_value,

    contrat_discount_value:
      form.contrat_discount_value,

    materials: validMaterials.map((material) => ({
      price: Number(material.price),
      product_id: material.product_id,
      quantity: Number(material.quantity),
    })),

    name: form.name,
    quantity_classes: form.quantity_classes,

    second_start_time:
      form.second_start_time || null,

    second_weekday: form.second_weekday,
    start_time: form.start_time || null,
    weekday: form.weekday,
  };

  await execute(() => {
    if (!props.package?.id) {
      return createUnitPackage(payload);
    }

    const changedFields = getUpdatedFields.value;
    const updatePayload = {};

    const directKeys = [
      "name",
      "quantity_classes",
      "contract_value",
      "contract_register_value",
      "contrat_discount_value",
      "weekday",
      "start_time",
      "second_weekday",
      "second_start_time",
    ];

    for (const key of directKeys) {
      if (key in changedFields) {
        updatePayload[key] = payload[key];
      }
    }

    if ("class_duration_hours" in changedFields) {
      updatePayload.class_duration_minutes =
        payload.class_duration_minutes;
    }

    if ("materials" in changedFields) {
      updatePayload.materials = payload.materials;
    }

    return updateUnitPackage(
      props.package.id,
      updatePayload,
    );
  });
};

const onProductSelected = (material) => {
  const option = productOptions.value.find(
    (product) => product.value === material.product_id,
  );

  if (option) {
    material.price = option.price_sale;
  }
};

const removeMaterial = (index) => {
  form.materials.splice(index, 1);
};

watch(
  () => form.weekday,
  (weekday) => {
    if (form.second_weekday === weekday) {
      form.second_weekday = null;
    }
  },
);

onMounted(async () => {
  const productsResponse = await getProductsForSelect();

  products.value = productsResponse;

  if (!props.package?.id) return;

  const packageData = await getUnitPackage(
    props.package.id,
  );

  form.class_duration_hours =
    (packageData.class_duration_minutes ?? 120) / 60;

  form.second_start_time = trimTime(
    packageData.second_start_time,
  );

  form.second_weekday =
    packageData.second_weekday ?? null;

  form.start_time = trimTime(packageData.start_time);

  form.weekday = packageData.weekday ?? null;

  if (packageData.materials?.length) {
    form.materials = packageData.materials.map(
      (material) => ({
        price: material.price,
        product_id: material.product_id,
        quantity: material.quantity,
      }),
    );
  }
});
</script>

<style scoped>
.package-duration-hint {
  padding-top: 4px;
  padding-bottom: 2px;
  color: #757575;
  font-size: 12px;
  line-height: 1.35;
}
</style>
