<template>
  <div class="agendamentos-page">
    <DefaultHeaderPage class="q-px-md" />

    <div class="q-px-md q-pb-md">

      <div class="tabs-row q-mb-md">
        <div
          v-for="tab in tabs"
          :key="tab.name"
          :class="['cat-chip', activeTab === tab.name ? 'cat-chip--selected' : 'cat-chip--default']"
          @click="activeTab = tab.name"
        >
          {{ tab.label }}
        </div>
      </div>

      <!-- Tab: Nova Solicitação -->
      <div v-if="activeTab === 'novo'">
        <div v-if="isOnLeave" class="on-leave-notice">
          <q-icon name="mdi-account-off-outline" size="32px" color="warning-light" />
          <div class="on-leave-notice__text">{{ $t('associado.on_leave_appointment') }}</div>
        </div>

        <q-card v-else flat class="form-card">
          <q-card-section>
            <q-form ref="appointmentFormRef" class="form-column" @submit="submitAppointment">
              <template v-if="!isExameService">
                <q-checkbox
                  v-model="forDependent"
                  color="violet-normal"
                  :label="$t('agendamento.for_dependent_self')"
                />
                <DependenteSelect
                  v-if="forDependent"
                  v-model="selectedDependent"
                  :user-id="user.user?.id ?? null"
                  :rules="[inputRules.required]"
                  class="input-violet"
                />
              </template>
              <PartnerAgreementSelect
                v-model="selectedPartner"
                :label="$t('ui.navigation.convenios')"
                :rules="[inputRules.required]"
                class="input-violet"
                for-associado
              />
              <PartnerAgreementServiceSelect
                v-model="selectedService"
                :partner-agreement-id="selectedPartner?.value"
                :label="$t('associado.service')"
                :rules="[inputRules.required]"
                class="input-violet"
                for-associado
              />

              <ClinicScheduleNotice
                v-if="isExameService"
                :partner="selectedPartner?.data"
                :text="$t('agendamento.exame_aviso_whatsapp')"
                :whatsapp-message="examWhatsappMessage"
                class="q-my-sm"
              />

              <template v-else>
                <ClinicScheduleNotice
                  v-if="selectedPartner"
                  :partner="selectedPartner.data"
                  class="q-my-sm"
                />

                <DefaultInputDatePicker
                  v-model:untreated-date="appointmentForm.date"
                  :label="$t('common.terms.date')"
                  :rules="[inputRules.required, inputRules.exactAdvanceDays(ADVANCE_DAYS)]"
                  :hint="$t('agendamento.data_disponivel', { date: allowedDateLabel })"
                  :date-options="allowedDateOptions"
                  placeholder="dd/mm/aaaa"
                  lazy-rules
                  class="input-violet"
                />
                <DefaultInput
                  v-model="appointmentForm.time"
                  :label="$t('common.terms.hour2')"
                  :rules="[inputRules.required]"
                  mask="##:##"
                  placeholder="HH:MM"
                  class="input-violet"
                />

                <DefaultInput
                  v-model="appointmentForm.observations"
                  :label="$t('associado.notes')"
                  type="textarea"
                  autogrow
                  class="input-violet"
                />
                <div class="flex justify-end q-mt-sm">
                  <q-btn
                    unelevated
                    type="submit"
                    class="btn-gradient"
                    :label="editingId ? $t('common.actions.save') : $t('associado.schedule')"
                    :loading="submitting"
                  />
                </div>
              </template>
            </q-form>
          </q-card-section>
        </q-card>
      </div>

      <!-- Tab: Meus Agendamentos -->
      <div v-else>
        <div v-if="loadingList" class="flex flex-center q-py-xl">
          <q-spinner color="violet-normal" size="48px" />
        </div>

        <div v-else-if="appointments.length === 0" class="text-center text-grey q-py-xl">
          {{ $t("http.errors.no_records_found") }}
        </div>

        <div v-else class="apmt-list">
          <div
            v-for="apt in pagedAppointments"
            :key="apt.id"
            class="apmt-card"
          >
            <div class="apmt-card__header">
              <div class="apmt-card__id">
                <span class="apmt-card__order">#{{ apt.order_number }}</span>
                <span
                  :class="['apmt-card__type', isExame(apt) ? 'apmt-card__type--exame' : 'apmt-card__type--consulta']"
                >
                  <q-icon :name="isExame(apt) ? 'mdi-test-tube' : 'mdi-stethoscope'" size="13px" />
                  {{ isExame(apt) ? $t('agendamento.tipo_exame') : $t('agendamento.tipo_consulta') }}
                </span>
              </div>
              <q-chip
                outline
                :color="statusColor(apt.status)"
                :label="$t(`agendamento.status.${statusValue(apt.status)}`)"
                size="sm"
                dense
                class="apmt-card__status"
              />
            </div>

            <div class="apmt-card__row">
              <q-icon name="mdi-handshake-outline" size="15px" class="apmt-card__icon" />
              <span class="apmt-card__value">{{ apt.partner_agreement?.trade_name || apt.partner_agreement?.company_name || '—' }}</span>
            </div>

            <template v-if="isExame(apt)">
              <div class="apmt-card__exams">
                <div class="apmt-card__exams-title">
                  <q-icon name="mdi-test-tube" size="15px" class="apmt-card__icon" />
                  {{ $t("agendamento.exames") }}
                </div>
                <div
                  v-for="exam in apt.exams"
                  :key="exam.id"
                  class="apmt-card__exam-line"
                >
                  <span class="apmt-card__value">{{ exam.name }}</span>
                  <span class="apmt-card__exam-price">{{ formatToBRLCurrency(exam.service_price) ?? '—' }}</span>
                </div>
                <div class="apmt-card__exam-total">
                  <span>{{ $t("agendamento.total") }}</span>
                  <span>{{ formatToBRLCurrency(apt.service_price) ?? '—' }}</span>
                </div>
              </div>
            </template>

            <template v-else>
              <div class="apmt-card__row">
                <q-icon name="mdi-briefcase-outline" size="15px" class="apmt-card__icon" />
                <span class="apmt-card__value">{{ apt.partner_agreement_service?.name || '—' }}</span>
              </div>

              <div class="apmt-card__row">
                <q-icon name="mdi-cash-multiple" size="15px" class="apmt-card__icon" />
                <span class="apmt-card__label">{{ $t('common.terms.total_amount') }}:</span>
                <span class="apmt-card__price">{{ consultaPrice(apt) }}</span>
              </div>
            </template>

            <div v-if="apt.user_dependent" class="apmt-card__row">
              <q-icon name="mdi-account-child-outline" size="15px" class="apmt-card__icon" />
              <span class="apmt-card__label">{{ $t('associado.dependent') }}:</span>
              <span class="apmt-card__value">{{ apt.user_dependent.name }}</span>
            </div>

            <div class="apmt-card__row">
              <q-icon name="mdi-calendar-clock-outline" size="15px" class="apmt-card__icon" />
              <span class="apmt-card__value">{{ formatDateTime(apt.date, apt.time) }}</span>
            </div>

            <div class="apmt-card__row">
              <q-icon name="mdi-calendar-plus-outline" size="15px" class="apmt-card__icon" />
              <span class="apmt-card__label">{{ $t('agendamento.col.solicitacao') }}:</span>
              <span class="apmt-card__value">{{ formatDate(apt.created_at) }}</span>
            </div>

            <div v-if="apt.refusal_reason" class="apmt-card__row">
              <q-icon name="mdi-comment-alert-outline" size="15px" class="apmt-card__icon" />
              <span class="apmt-card__label">{{ $t('agendamento.motivo_recusa') }}:</span>
              <span class="apmt-card__value">{{ apt.refusal_reason }}</span>
            </div>

            <div v-if="hasActions(apt)" class="apmt-card__actions">
              <q-btn
                v-if="isAwaitingDecision(apt)"
                dense
                flat
                icon="mdi-close-circle-outline"
                color="negative"
                size="sm"
                :label="$t('agendamento.recusar')"
                :disable="decisionId === apt.id"
                @click="onRefuseExam(apt)"
              />
              <q-btn
                v-if="isAwaitingDecision(apt)"
                dense
                unelevated
                icon="mdi-check-circle-outline"
                color="positive"
                size="sm"
                :label="$t('agendamento.aceitar')"
                :loading="decisionId === apt.id"
                @click="onAcceptExam(apt)"
              />
              <q-btn
                v-if="canEdit(apt)"
                dense
                flat
                icon="mdi-pencil-outline"
                color="violet-normal"
                size="sm"
                :label="$t('common.actions.edit')"
                @click="onEditAppointment(apt)"
              />
              <q-btn
                v-if="apt.can_issue_guide"
                dense
                flat
                icon="mdi-file-document-outline"
                color="violet-normal"
                size="sm"
                :label="$t('agendamento.guia')"
                :loading="guideId === apt.id"
                @click="onDownloadGuide(apt)"
              />
            </div>
          </div>
        </div>

        <div v-if="totalPages > 1" class="flex flex-center q-mt-lg">
          <q-pagination
            v-model="currentPage"
            :max="totalPages"
            boundary-numbers
            color="violet-normal"
            active-color="violet-normal"
            direction-links
          />
        </div>
      </div>

    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, useTemplateRef } from "vue";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import {
  createAppointment,
  getMyAppointments,
  updateAppointment,
  downloadMyAppointmentGuide,
  acceptExamAppointment,
  refuseExamAppointment,
} from "src/api/appointment";
import { useInputRules } from "src/composables/useInputRules";
import { formatToBRLCurrency, addDaysToToday, formatDateBR, formatDateTimeBR } from "src/helpers/utils";
import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
import DefaultInput from "src/components/defaults/DefaultInput.vue";
import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
import PartnerAgreementSelect from "src/components/selects/PartnerAgreementSelect.vue";
import DependenteSelect from "src/components/selects/DependenteSelect.vue";
import PartnerAgreementServiceSelect from "src/components/selects/PartnerAgreementServiceSelect.vue";
import ClinicScheduleNotice from "src/components/ClinicScheduleNotice.vue";
import RefuseExamDialog from "src/components/RefuseExamDialog.vue";
import { userStore } from "src/stores/user";

const $q = useQuasar();
const { t } = useI18n();
const { inputRules } = useInputRules();
const appointmentFormRef = useTemplateRef("appointmentFormRef");
const user = userStore();

const isOnLeave = computed(() => {
  const s = user.user?.status;
  return s === "on_leave" || s?.value === "on_leave";
});

const activeTab = ref("novo");
const PER_PAGE = 12;
const currentPage = ref(1);

const tabs = computed(() => [
  { name: "novo",  label: t("associado.new_appointment") },
  { name: "meus", label: t("associado.my_appointments") },
]);

const ADVANCE_DAYS = 2;

const forDependent     = ref(false);
const selectedDependent = ref(null);
const selectedPartner  = ref(null);
const selectedService  = ref(null);
const guideId          = ref(null);
const decisionId       = ref(null);

const allowedDateLabel = computed(() => formatDateBR(addDaysToToday(ADVANCE_DAYS)));

const allowedDateOptions = computed(() => {
  const date = addDaysToToday(ADVANCE_DAYS);
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return [`${date.getFullYear()}/${month}/${day}`];
});

const isExameService = computed(() => {
  const type = selectedService.value?.data?.type;
  return (typeof type === "object" ? type?.value : type) === "exame";
});

const examWhatsappMessage = computed(() =>
  t("agendamento.exame_whatsapp_mensagem", {
    name: user.user?.name ?? "",
    service: selectedService.value?.label ?? "",
  }),
);

watch(forDependent, (value) => {
  if (!value) selectedDependent.value = null;
});
const appointmentForm  = reactive({ observations: "", date: "", time: "" });
const submitting       = ref(false);
const editingId        = ref(null);
const appointments     = ref([]);
const loadingList      = ref(false);

const totalPages = computed(() => Math.max(1, Math.ceil(appointments.value.length / PER_PAGE)));

const pagedAppointments = computed(() => {
  const start = (currentPage.value - 1) * PER_PAGE;
  return appointments.value.slice(start, start + PER_PAGE);
});

const statusValue = (status) => (typeof status === "object" ? status?.value : status);

const statusColor = (status) => {
  const map = {
    pendente: "warning-light",
    aguardando_aceite: "warning-light",
    confirmado: "positive",
    cancelado: "negative",
    recusado: "negative",
    concluido: "grey",
  };
  return map[statusValue(status)] ?? "grey";
};

const typeValue = (apt) => (typeof apt.type === "object" ? apt.type?.value : apt.type);
const isExame = (apt) => typeValue(apt) === "exame";

const isAwaitingDecision = (apt) => statusValue(apt.status) === "aguardando_aceite";

const canEdit = (apt) => !isExame(apt) && statusValue(apt.status) === "pendente";

const hasActions = (apt) => isAwaitingDecision(apt) || canEdit(apt) || apt.can_issue_guide;

const PRICE_UNDEFINED = "-----";

const consultaPrice = (apt) => {
  const service = apt.partner_agreement_service;
  const price = apt.service_price ?? service?.associate_price ?? service?.price;
  return formatToBRLCurrency(price) ?? PRICE_UNDEFINED;
};

const formatDate = (isoStr) => {
  if (!isoStr) return "—";
  const d = new Date(isoStr);
  if (isNaN(d)) return "—";
  return d.toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit", year: "numeric" });
};

const formatDateTime = formatDateTimeBR;

const loadAppointments = async () => {
  loadingList.value = true;
  currentPage.value = 1;
  try {
    appointments.value = await getMyAppointments();
  } catch (e) {
    console.error(e);
  } finally {
    loadingList.value = false;
  }
};

watch(activeTab, (val) => {
  if (val === "meus") loadAppointments();
});

const resetForm = () => {
  forDependent.value           = false;
  selectedDependent.value      = null;
  selectedPartner.value        = null;
  selectedService.value        = null;
  appointmentForm.observations = "";
  appointmentForm.date         = "";
  appointmentForm.time         = "";
  editingId.value              = null;
};

const submitAppointment = async () => {
  if (isExameService.value) return;

  const valid = await appointmentFormRef.value?.validate();
  if (!valid) return;
  submitting.value = true;
  const payload = {
    partner_agreement_id:         selectedPartner.value.value,
    partner_agreement_service_id: selectedService.value.value,
    user_dependent_id:            selectedDependent.value?.value ?? null,
    date:                         appointmentForm.date,
    time:                         appointmentForm.time,
    observations: appointmentForm.observations,
  };
  try {
    if (editingId.value) {
      await updateAppointment(editingId.value, payload);
    } else {
      payload.user_id = user.user.id;
      await createAppointment(payload);
    }
    $q.notify({ type: "positive", message: t("http.success") });
    resetForm();
    activeTab.value = "meus";
  } catch {
    $q.notify({ type: "negative", message: t("http.errors.failed") });
  } finally {
    submitting.value = false;
  }
};

const onDownloadGuide = async (apt) => {
  if (!apt.can_issue_guide) return;
  guideId.value = apt.id;
  try {
    await downloadMyAppointmentGuide(apt.id, apt.order_number);
  } catch (e) {
    $q.notify({ type: "negative", message: e?.message || t("http.errors.failed") });
  } finally {
    guideId.value = null;
  }
};

const onAcceptExam = async (apt) => {
  decisionId.value = apt.id;
  try {
    await acceptExamAppointment(apt.id);
    await loadAppointments();
  } catch (e) {
    $q.notify({ type: "negative", message: e?.response?.data?.message || t("http.errors.failed") });
  } finally {
    decisionId.value = null;
  }
};

const onRefuseExam = (apt) => {
  $q.dialog({ component: RefuseExamDialog }).onOk(async ({ reason }) => {
    decisionId.value = apt.id;
    try {
      await refuseExamAppointment(apt.id, reason || null);
      await loadAppointments();
    } catch (e) {
      $q.notify({ type: "negative", message: e?.response?.data?.message || t("http.errors.failed") });
    } finally {
      decisionId.value = null;
    }
  });
};

const onEditAppointment = (apt) => {
  editingId.value              = apt.id;
  forDependent.value           = !!apt.user_dependent_id;
  selectedDependent.value      = apt.user_dependent_id
    ? { value: apt.user_dependent_id, label: apt.user_dependent?.name || "" }
    : null;
  selectedPartner.value        = { value: apt.partner_agreement_id, label: apt.partner_agreement?.trade_name || apt.partner_agreement?.company_name || "" };
  selectedService.value        = { value: apt.partner_agreement_service_id, label: apt.partner_agreement_service?.name || "" };
  appointmentForm.observations = apt.observations ?? "";
  appointmentForm.date         = apt.date ?? "";
  appointmentForm.time         = apt.time ?? "";
  activeTab.value              = "novo";
};
</script>

<style scoped lang="scss">
@use "src/css/quasar.variables.scss" as vars;

.agendamentos-page {
  background: vars.$violet-light;
  min-height: calc(100dvh - 68px);
  box-sizing: border-box;
  overflow-x: hidden;
}

.tabs-row {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 8px;
}

.cat-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding: 0 16px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s, color 0.15s;

  &--default  { background: #c9a3dc; color: #fff; }
  &--selected { background: #4d1658; color: #fff; }
}

.on-leave-notice {
  background: white;
  border-radius: 12px;
  padding: 32px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);

  &__text {
    font-size: 14px;
    color: vars.$color-text-2;
    line-height: 1.5;
  }
}

.form-card {
  background: white !important;
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.form-column {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.btn-gradient {
  background: linear-gradient(90deg, #4d1658 0%, #8b30a5 100%) !important;
  color: white !important;
  border-radius: 8px !important;

  :deep(.q-icon) { color: white !important; }
}

.apmt-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.apmt-card {
  background: white;
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.07);
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow: hidden;

  &__header {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 4px;
  }

  &__id {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 5px;
    min-width: 0;
  }

  &__order {
    font-size: 13px;
    font-weight: 700;
    color: vars.$violet-normal;
    letter-spacing: 0.3px;
  }

  &__type {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;

    &--consulta {
      background: vars.$violet-light;
      color: vars.$violet-normal;
    }

    &--exame {
      background: #e1f0fa;
      color: #01579b;
    }
  }

  &__status {
    font-size: 11px !important;
    flex-shrink: 0;
  }

  &__row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: vars.$color-text;
    min-width: 0;
  }

  &__icon {
    color: vars.$violet-normal;
    flex-shrink: 0;
    opacity: 0.8;
  }

  &__label {
    color: vars.$color-text-2;
    font-size: 12px;
    flex-shrink: 0;
  }

  &__value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }

  &__price {
    font-weight: 700;
    color: vars.$violet-normal;
  }

  &__actions {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 6px;
    margin-top: 4px;
    border-top: 1px solid vars.$violet-light;
    padding-top: 6px;
  }

  &__exams {
    display: flex;
    flex-direction: column;
    gap: 3px;
    background: vars.$violet-light;
    border-radius: 8px;
    padding: 10px 12px;
  }

  &__exams-title {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: vars.$violet-normal;
    margin-bottom: 2px;
  }

  &__exam-line {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    gap: 10px;
    font-size: 13px;
    color: vars.$color-text;
  }

  &__exam-price {
    flex-shrink: 0;
    color: vars.$color-text-2;
  }

  &__exam-total {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid rgba(77, 22, 88, 0.15);
    font-size: 13px;
    font-weight: 700;
    color: vars.$violet-normal;
  }
}
</style>
