<template>
  <section
    v-if="section?.enabled"
    class="relative flex items-center"
    id="contact"
  >
    <div class="relative mx-auto w-full max-w-4xl">
      <div class="mb-10 flex justify-center text-center gap-6">
        <div>
          <h2
            v-if="section?.title"
            class="text-2xl sm:text-5xl font-bold tracking-tight text-dark"
          >
            {{ section.title }}
          </h2>

          <p v-if="section?.description" class="mt-2 text-md text-dark">
            {{ section?.description }}
          </p>
        </div>
      </div>

      <form @submit.prevent="onSubmit" novalidate class="group">
        <div v-if="showSuccess" ref="successPanel">
          <div class="flex items-center justify-center text-center gap-4">
            <div>
              <div class="flex justify-center items-center py-6">
                <img
                  src="/images/egg-walking.gif"
                  alt="Egg Gif"
                  aria-hidden="true"
                  class="h-56 w-56"
                />
              </div>

              <h3 class="text-2xl font-semibold text-softlight">
                {{ t("Message sent!") }}
              </h3>

              <p class="mt-1 text-lg text-dark">
                {{ t("We'll get back to you soon.") }}
              </p>

              <button
                type="button"
                @click="
                  showSuccess = false;
                  nextTick(() => firstInput?.focus());
                "
                class="cursor-pointer mt-6 inline-flex items-center gap-2 border border-dark px-4 py-2 text-dark font-bold hover:bg-light focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-light focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-900"
              >
                {{ t("Send another message") }}
              </button>
            </div>
          </div>
        </div>

        <div v-else>
          <div class="sm:p-2 md:p-6">
            <div class="grid sm:grid-cols-2">
              <!-- Full name field -->
              <div class="p-4">
                <label
                  for="full-name"
                  class="block text-md font-medium text-dark px-1"
                >
                  {{ t("Full Name") }} <span class="text-red-600">*</span>
                </label>

                <input
                  id="full-name"
                  ref="firstInput"
                  v-model.trim="form.fullName"
                  @input="touched.fullName = true"
                  type="text"
                  :aria-invalid="!!errors.fullName || undefined"
                  :aria-describedby="
                    errors.fullName ? 'full-name-error' : undefined
                  "
                  class="bg-[#fff]/40 mt-2 w-full border border-dark/20 px-3 py-3 text-dark placeholder-dark/40 outline-none focus:ring-1 focus:ring-light focus:border-transparent transition"
                  :placeholder="t('Full Name')"
                  autocomplete="name"
                />

                <p
                  v-if="touched.fullName && errors.fullName"
                  id="full-name-error"
                  class="mt-2 text-sm text-red-500 px-1"
                >
                  {{ errors.fullName }}
                </p>
              </div>

              <!-- Subject selection -->
<!-- Subject selection -->
<div class="p-4">
  <label
    for="subject"
    class="block text-md font-medium text-dark px-1"
  >
    {{ t("Subject") }} <span class="text-red-600">*</span>
  </label>

  <div class="relative mt-2">
    <!-- Trigger -->
    <button
      type="button"
      @click="isSubjectOpen = !isSubjectOpen"
      @blur="handleSubjectBlur"
      :aria-invalid="!!errors.subject || undefined"
      :aria-describedby="
        errors.subject ? 'subject-error' : undefined
      "
      class="group flex w-full items-center justify-between border border-dark/20 bg-[#fff]/40 px-4 py-3 text-left text-dark outline-none transition hover:bg-white/60 focus:ring-1 focus:ring-light"
    >
      <span
        :class="
          form.subject
            ? 'text-dark'
            : 'text-dark/40'
        "
      >
        {{
          selectedSubjectLabel ||
          t("Select a subject")
        }}
      </span>

      <svg
        class="h-5 w-5 shrink-0 text-dark/50 transition"
        :class="isSubjectOpen ? 'rotate-180' : ''"
        viewBox="0 0 24 24"
        fill="none"
      >
        <path
          d="M6 9l6 6 6-6"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        />
      </svg>
    </button>

    <!-- Dropdown -->
    <transition
      enter-active-class="transition duration-150 ease-out"
      enter-from-class="opacity-0 -translate-y-1"
      enter-to-class="opacity-100 translate-y-0"
      leave-active-class="transition duration-100 ease-in"
      leave-from-class="opacity-100 translate-y-0"
      leave-to-class="opacity-0 -translate-y-1"
    >
      <div
        v-if="isSubjectOpen"
        class="absolute left-0 right-0 z-20 mt-2 overflow-hidden border border-dark/10 bg-white/90 shadow-xl backdrop-blur-xl"
      >
        <button
          v-for="opt in subjects"
          :key="opt.value"
          type="button"
          @click="selectSubject(opt.value)"
          class="flex w-full items-center justify-between px-4 py-3 text-left text-dark transition hover:bg-dark/3"
        >
          <span>
            {{ opt.label }}
          </span>

          <span
            v-if="form.subject === opt.value"
            class="text-sm text-softlight"
          >
            ✓
          </span>
        </button>
      </div>
    </transition>
  </div>

  <label
    v-if="form.subject === 'something-else'"
    for="subject-other"
    class="sr-only"
  >
    {{ t("Other Subject") }}
  </label>

  <input
    v-if="form.subject === 'something-else'"
    id="subject-other"
    v-model.trim="form.subjectOther"
    @input="touched.subject = true"
    type="text"
    :placeholder="t('Other Subject')"
    class="bg-[#fff]/40 mt-3 w-full border border-dark/20 px-3 py-3 text-dark placeholder-dark/40 outline-none transition focus:border-transparent focus:ring-1 focus:ring-light"
    name="subjectOther"
  />

  <p
    v-if="touched.subject && errors.subject"
    id="subject-error"
    class="mt-2 px-1 text-sm text-red-500"
  >
    {{ errors.subject }}
  </p>
</div>
            </div>
            <div class="grid sm:grid-cols-2">
              <!-- Email field -->
              <div class="p-4">
                <label
                  for="email"
                  class="block text-md font-medium text-dark px-1"
                >
                  {{ t("Email") }} <span class="text-red-600">*</span>
                </label>

                <input
                  id="email"
                  v-model.trim="form.email"
                  @input="touched.email = true"
                  type="email"
                  :aria-invalid="!!errors.email || undefined"
                  :aria-describedby="errors.email ? 'email-error' : undefined"
                  class="bg-[#fff]/40 mt-2 w-full border border-dark/20 px-3 py-3 text-dark placeholder-dark/40 outline-none focus:ring-1 focus:ring-light focus:border-transparent transition"
                  placeholder="you@example.com"
                  autocomplete="email"
                  autocapitalize="off"
                  spellcheck="false"
                  inputmode="email"
                />

                <p
                  v-if="touched.email && errors.email"
                  id="email-error"
                  class="mt-2 text-sm text-red-500 px-1"
                >
                  {{ errors.email }}
                </p>
              </div>

              <!-- Phone field -->
              <div class="p-4">
                <label
                  for="phone"
                  class="block text-md font-medium text-dark px-1"
                >
                  {{ t("Phone") }}
                </label>

                <input
                  id="phone"
                  v-model.trim="form.phone"
                  @input="touched.phone = true"
                  type="tel"
                  :aria-invalid="!!errors.phone || undefined"
                  :aria-describedby="errors.phone ? 'phone-error' : undefined"
                  class="bg-[#fff]/40 mt-2 w-full border border-dark/20 px-3 py-3 text-dark placeholder-dark/40 outline-none focus:ring-1 focus:ring-light focus:border-transparent transition"
                  :placeholder="t('Phone')"
                  autocomplete="tel"
                  inputmode="tel"
                />

                <p
                  v-if="touched.phone && errors.phone"
                  id="phone-error"
                  class="mt-2 text-sm text-red-500 px-1"
                >
                  {{ errors.phone }}
                </p>
              </div>
            </div>

            <!-- Message -->
            <div class="mt-3 p-4 relative">
              <label
                for="message"
                class="block text-md font-medium text-dark px-1"
              >
                {{ t("Message") }} <span class="text-red-600">*</span>
              </label>

              <textarea
                id="message"
                v-model.trim="form.message"
                @input="
                  touched.message = true;
                  if (form.message.length > 600)
                    form.message = form.message.slice(0, 600);
                "
                rows="5"
                :aria-invalid="!!errors.message || undefined"
                :aria-describedby="errors.message ? 'message-error' : undefined"
                class="bg-[#fff]/40 border border-dark/20 mt-2 w-full px-3 py-3 text-dark placeholder-dark/40 outline-none focus:ring-1 focus:ring-light focus:border-transparent transition resize-y min-h-36"
                :placeholder="t('Write your message here…')"
                maxlength="600"
              />

              <span
                class="absolute bottom-0 right-4 text-xs select-none"
                :class="
                  form.message.length >= 600 ? 'text-red-500' : 'text-dark'
                "
                aria-live="polite"
              >
                {{ form.message.length }}/600
              </span>

              <p
                v-if="touched.message && errors.message"
                id="message-error"
                class="mt-2 text-sm text-red-500 px-1"
              >
                {{ errors.message }}
              </p>
            </div>

            <!-- Consent -->
            <div class="mt-2 p-4">
              <label
                for="consent"
                class="flex items-start gap-3 cursor-pointer select-none"
              >
                <input
                  id="consent"
                  v-model="form.consent"
                  @input="touched.consent = true"
                  type="checkbox"
                  class="bg-[#fff]/40 peer sr-only"
                  :aria-invalid="!!errors.consent || undefined"
                  :aria-describedby="
                    errors.consent ? 'consent-error' : undefined
                  "
                />

                <div
                  class="flex h-5 w-5 shrink-0 items-center justify-center rounded-md border-2 border-dark/20 bg-white transition-all duration-200 peer-checked:border-highlight peer-checked:bg-highlight peer-focus:ring-2 peer-focus:ring-light peer-focus:ring-offset-2 peer-focus:ring-offset-highlight"
                >
                  <svg
                    class="h-3.5 w-3.5 scale-0 text-white transition-all duration-200 peer-checked:scale-100"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="3"
                    viewBox="0 0 24 24"
                  >
                    <path
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      d="M5 13l4 4L19 7"
                    />
                  </svg>
                </div>

                <span class="text-sm text-dark">
                  {{ t("I agree to be contacted regarding my inquiry.") }}
                  <span class="text-red-600">*</span>
                </span>
              </label>

              <p
                v-if="touched.consent && errors.consent"
                id="consent-error"
                class="mt-2 px-1 text-sm text-red-500"
              >
                {{ errors.consent }}
              </p>
            </div>

            <!-- Honeypot -->
            <div class="sr-only" aria-hidden="true">
              <label for="checkIfYouAreNotARobot">
                Check if you are not a robot
              </label>

              <input
                id="checkIfYouAreNotARobot"
                v-model.trim="form.checkIfYouAreNotARobot"
                type="text"
                tabindex="-1"
                autocomplete="off"
              />
            </div>

            <!-- Turnstile -->
            <div class="p-4">
              <div
                v-if="turnstileSiteKey"
                ref="turnstileContainer"
                :id="turnstileId"
              ></div>

              <p v-else class="text-xs text-dark">
                Bot protection not configured (recommended).
              </p>
            </div>

            <input type="hidden" :value="turnstileToken" />

            <!-- Submit -->
            <div class="flex flex-col text-center gap-4 p-4">
              <p
                v-if="status.message"
                :class="status.ok ? 'text-emerald-400' : 'text-red-500'"
                class="text-sm font-bold"
                role="alert"
                aria-live="polite"
              >
                {{ status.message }}
              </p>

              <Button
                type="submit"
                :disabled="submitting || !isValid"
                variant="highlight"
                size="sm"
                class="cursor-pointer sm:w-auto sm:min-w-40 ml-auto"
              >
                <span v-if="!submitting">{{ t("Send") }}</span>
                <span v-else>{{ t("Sending…") }}</span>
              </Button>
            </div>
          </div>
        </div>
      </form>
    </div>
  </section>
</template>

<script setup lang="ts">
import { reactive, computed, ref, watch, nextTick, onMounted } from "vue";
import { useI18n } from "vue-i18n";

const { t } = useI18n();

const props = defineProps<{
  section?: {
    enabled?: boolean;
    title?: string | null;
    description?: string | null;
  };
  defaultSubject?: string;
}>();

const turnstileSiteKey =
  (typeof window !== "undefined" && (window as any).__TURNSTILE_SITEKEY) ||
  import.meta.env?.VITE_TURNSTILE_SITEKEY ||
  "";

const subjects = computed(() => [
  { value: "job-application", label: t("Job Application") },
  { value: "suggestion", label: t("Suggestion") },
  { value: "something-else", label: t("Something Else") },
]);

const form = reactive({
  fullName: "",
  email: "",
  phone: "",
  subject: "",
  subjectOther: "",
  message: "",
  consent: false,
  checkIfYouAreNotARobot: "",
});

const touched = reactive({
  fullName: false,
  email: false,
  phone: false,
  subject: false,
  message: false,
  consent: false,
});

const submitting = ref(false);
const isSubjectOpen = ref(false);

const status = reactive<{ ok: boolean; message: string | null }>({
  ok: false,
  message: null,
});

const showSuccess = ref(false);
const successPanel = ref<HTMLElement | null>(null);
const firstInput = ref<HTMLInputElement | null>(null);

const turnstileToken = ref("");
const turnstileId = `turnstile-${Math.random().toString(36).slice(2, 9)}`;
const turnstileContainer = ref<HTMLElement | null>(null);

const selectedSubjectLabel = computed(() => {
  return subjects.value.find((item) => item.value === form.subject)?.label || "";
});

watch(showSuccess, async (v) => {
  if (v) {
    await nextTick();

    try {
      successPanel.value?.focus?.();
    } catch (_) {}
  }
});

watch(
  () => form.subject,
  (val) => {
    if (val !== "something-else") {
      form.subjectOther = "";
    }
  },
);

function selectSubject(value: string) {
  form.subject = value;
  touched.subject = true;
  isSubjectOpen.value = false;
}

function handleSubjectBlur() {
  window.setTimeout(() => {
    isSubjectOpen.value = false;
  }, 120);
}

function validateFullName(v: string) {
  if (!v) return t("Name is required");
  if (v.length < 4) return t("Please enter at least 4 characters");
  return "";
}

function validateEmail(v: string) {
  if (!v) return t("Email is required");

  const re = /^(?:[^\s@]+)@(?:[^\s@]+)\.[^\s@]{2,}$/i;

  if (!re.test(v)) return t("Please enter a valid email");

  return "";
}

function validatePhone(v: string) {
  if (!v) return "";

  const re =
    /^\+?[1-9]\d{0,3}[\s\-().]?\d{1,4}[\s\-().]?\d{1,4}[\s\-().]?\d{1,9}$/;

  if (!re.test(v)) return t("Please enter a valid phone number");

  return "";
}

function validateSubject(v: string) {
  if (!v) return t("Subject is required");

  if (v === "something-else" && !form.subjectOther) {
    return t("Please specify the subject");
  }

  return "";
}

function validateMessage(v: string) {
  if (!v) return t("Message is required");
  if (v.length < 25) return t("Please write at least 25 characters");
  if (v.length > 600) return t("Please keep your message under 600 characters");
  return "";
}

function validateConsent(v: boolean) {
  if (!v) return t("Please confirm you agree to be contacted");
  return "";
}

const errors = reactive<{ [k: string]: string | "" }>({
  fullName: "",
  email: "",
  phone: "",
  subject: "",
  message: "",
  consent: "",
});

const isValid = computed(() => {
  errors.fullName = validateFullName(form.fullName);
  errors.email = validateEmail(form.email);
  errors.phone = validatePhone(form.phone);
  errors.subject = validateSubject(form.subject);
  errors.message = validateMessage(form.message);
  errors.consent = validateConsent(form.consent);

  return (
    !errors.fullName &&
    !errors.email &&
    !errors.phone &&
    !errors.subject &&
    !errors.message &&
    !errors.consent
  );
});

onMounted(() => {
  if (
    props.defaultSubject &&
    subjects.value.some((item) => item.value === props.defaultSubject)
  ) {
    form.subject = props.defaultSubject;
    touched.subject = true;
  }

  if (!turnstileSiteKey) return;

  if (!(window as any).turnstile) {
    const s = document.createElement("script");
    s.src = "https://challenges.cloudflare.com/turnstile/v0/api.js";
    s.async = true;
    s.defer = true;
    document.head.appendChild(s);

    s.onload = () => {
      renderTurnstile();
    };
  } else {
    renderTurnstile();
  }
});

function renderTurnstile() {
  try {
    if (!(window as any).turnstile || !turnstileContainer.value) return;

    (window as any).turnstile.render(turnstileContainer.value, {
      sitekey: turnstileSiteKey,
      theme: "light",
      language: document?.documentElement?.lang || "auto",
      callback: (token: string) => {
        turnstileToken.value = token;
      },
      "expired-callback": () => {
        turnstileToken.value = "";
      },
    });
  } catch (e) {
    console.warn("Turnstile render failed", e);
  }
}

async function onSubmit() {
  if (form.checkIfYouAreNotARobot) {
    status.ok = true;
    status.message = t("I'll get back to you soon.");
    return;
  }

  touched.fullName = true;
  touched.email = true;
  touched.phone = true;
  touched.subject = true;
  touched.message = true;
  touched.consent = true;

  if (!isValid.value) {
    status.ok = false;
    status.message = t("Please fix the errors above.");
    return;
  }

  if (turnstileSiteKey && !turnstileToken.value) {
    status.ok = false;
    status.message = t("Please complete the bot verification.");
    return;
  }

  try {
    submitting.value = true;
    status.ok = false;
    status.message = null;

    const payload: Record<string, unknown> = {
      fullName: form.fullName,
      email: form.email,
      phone: form.phone,
      subject: form.subject,
      subjectOther: form.subjectOther,
      message: form.message,
      consent: form.consent,
      checkIfYouAreNotARobot: form.checkIfYouAreNotARobot,
    };

    if (turnstileToken.value) {
      payload.turnstileToken = turnstileToken.value;
    }

    const res = await fetch("/contact", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    const result = await res.json().catch(() => ({ success: false }));

    if (!result.success) {
      throw new Error(result.error || "Unknown error");
    }

    status.ok = true;
    showSuccess.value = true;
    status.message = null;

    nextTick(() => {
      if (successPanel.value) {
        const top =
          successPanel.value.getBoundingClientRect().top + window.scrollY;

        window.scrollTo({
          top: top - 250,
          behavior: "smooth",
        });
      }
    });

    Object.assign(form, {
      fullName: "",
      email: "",
      phone: "",
      subject: "",
      subjectOther: "",
      message: "",
      consent: false,
      checkIfYouAreNotARobot: "",
    });

    (Object.keys(touched) as (keyof typeof touched)[]).forEach((key) => {
      touched[key] = false;
    });

    turnstileToken.value = "";

    try {
      if ((window as any).turnstile?.reset) {
        (window as any).turnstile.reset();
      }
    } catch (_) {}
  } catch (e) {
    console.error(e);
    status.ok = false;
    status.message = t("Something went wrong. Please try again.");
  } finally {
    submitting.value = false;
  }
}
</script>