<script setup lang="ts">
import { computed, defineAsyncComponent, ref, reactive } from "vue";
import { CheckboxRoot, CheckboxIndicator } from "reka-ui";
import { cn } from "@/lib/utils";
import Select from "@/components/ui/Select.vue";
import SelectContent from "@/components/ui/SelectContent.vue";
import SelectItem from "@/components/ui/SelectItem.vue";
import SelectTrigger from "@/components/ui/SelectTrigger.vue";
import SelectValue from "@/components/ui/SelectValue.vue";
import Popover from "@/components/ui/Popover.vue";
import PopoverTrigger from "@/components/ui/PopoverTrigger.vue";
import PopoverContent from "@/components/ui/PopoverContent.vue";
import Sheet from "@/components/ui/sheet/Sheet.vue";
import SheetContent from "@/components/ui/sheet/SheetContent.vue";
import SheetHeader from "@/components/ui/sheet/SheetHeader.vue";
import SheetTitle from "@/components/ui/sheet/SheetTitle.vue";
import SheetFooter from "@/components/ui/sheet/SheetFooter.vue";
import Button from "@/components/ui/Button.vue";
const DynamicField = defineAsyncComponent(
  () => import("@/components/DynamicField.vue"),
);
import { useBuilderPrefix } from "@/composables/useBuilderPrefix";
import { useCsrfToken } from "@/composables/useCsrfToken";
import type { FieldDefinition } from "./types";

type QuickCreateMeta = {
  sections: Array<{ fields: FieldDefinition[]; [key: string]: unknown }>;
  fields: FieldDefinition[];
  singularLabel: string;
  currentLocale: string | null;
  availableLocales: { code: string; name: string; is_active: boolean }[];
};

const props = defineProps<{
  field: FieldDefinition;
  modelValue?: unknown;
  error?: string;
  currentLocale?: string | null;
}>();

const emit = defineEmits<{
  "update:modelValue": [value: string | string[]];
}>();

// --- Single-select helpers ---

// Normalise single value: Eloquent eager-loads a relation as an array of objects.
// Extract the first item's id so the Select renders the correct initial selection.
const normalizedSingleValue = computed<string>(() => {
  if (Array.isArray(props.modelValue)) {
    const first = (props.modelValue as unknown[])[0];
    if (first == null) return "";
    if (typeof first === "object" && first !== null) {
      return String((first as Record<string, unknown>).id ?? "");
    }
    return String(first);
  }
  return props.modelValue != null ? String(props.modelValue) : "";
});

// --- Multi-select helpers ---

// Normalise multi-value: Eloquent eager-loads return arrays of objects — extract id.
const normalizedMultiValue = computed<string[]>(() => {
  if (!Array.isArray(props.modelValue)) return [];
  return (props.modelValue as unknown[]).map((v) => {
    if (typeof v === "object" && v !== null) {
      return String((v as Record<string, unknown>).id ?? "");
    }
    return String(v);
  });
});

const multiLabel = computed<string>(() => {
  if (normalizedMultiValue.value.length === 0) return "";
  return normalizedMultiValue.value
    .map((id) => {
      const opts = effectiveOptions.value;
      return String(opts[id as keyof typeof opts] ?? id);
    })
    .join(", ");
});

function toggleMultiOption(value: string): void {
  if (normalizedMultiValue.value.includes(value)) {
    emit(
      "update:modelValue",
      normalizedMultiValue.value.filter((v) => v !== value),
    );
  } else {
    emit("update:modelValue", [...normalizedMultiValue.value, value]);
  }
}

// --- Quick-create state ---

const builderPrefix = useBuilderPrefix();
const csrfToken = useCsrfToken();

/** Extra options appended after a successful quick-create (keyed id → label). */
const extraOptions = ref<Record<string, string>>({});

/** Options used in the template: merges prop options with quick-created items. */
const effectiveOptions = computed<Record<string, string>>(() => ({
  ...(props.field.options ?? {}),
  ...extraOptions.value,
}));

const quickCreateOpen = ref(false);
const quickCreateLoading = ref(false);
const quickCreateErrors = ref<Record<string, string[]>>({});
const quickCreateMeta = ref<QuickCreateMeta | null>(null);
const quickCreateFormData = reactive<Record<string, unknown>>({});
const quickCreateManualOverrides = new Set<string>();

/** All fields from sections + top-level fields, excluding hidden inputs. */
const quickCreateFields = computed<FieldDefinition[]>(() => {
  if (!quickCreateMeta.value) return [];
  const list: FieldDefinition[] = [...quickCreateMeta.value.fields];
  for (const section of quickCreateMeta.value.sections) {
    list.push(...section.fields);
  }
  return list.filter((f) => f.component !== "HiddenInput");
});

function initFormData(): void {
  for (const key of Object.keys(quickCreateFormData)) {
    delete quickCreateFormData[key];
  }
  for (const f of quickCreateFields.value) {
    quickCreateFormData[f.name] = f.default ?? null;
  }
  quickCreateErrors.value = {};
  quickCreateManualOverrides.clear();
}

function updateQuickCreateField(fieldName: string, value: unknown): void {
  quickCreateFormData[fieldName] = value;

  // Mark manually-edited auto-generate targets so we stop overwriting them.
  const isAutoTarget = quickCreateFields.value.some(
    (f) => f.generateFrom && f.name === fieldName,
  );
  if (isAutoTarget) {
    quickCreateManualOverrides.add(fieldName);
  }

  // Auto-generate derived fields (e.g. slug from name/title).
  for (const f of quickCreateFields.value) {
    if (f.generateFrom !== fieldName) continue;
    if (quickCreateManualOverrides.has(f.name)) continue;
    quickCreateFormData[f.name] = String(value ?? "")
      .toLowerCase()
      .replace(/[^a-z0-9]+/g, "-")
      .replace(/^-|-$/g, "");
  }
}

async function openQuickCreate(): Promise<void> {
  if (!props.field.quickCreate) return;

  if (!quickCreateMeta.value) {
    try {
      const localeParam = props.currentLocale
        ? `?locale=${encodeURIComponent(props.currentLocale)}`
        : "";
      const url = `/${builderPrefix}/${props.field.quickCreate.resource}/quick-create-meta${localeParam}`;
      const response = await fetch(url, {
        headers: {
          "X-CSRF-TOKEN": csrfToken,
          Accept: "application/json",
        },
      });

      if (response.ok) {
        quickCreateMeta.value = (await response.json()) as QuickCreateMeta;
      } else {
        quickCreateErrors.value = {
          _fetch: [`Failed to load form (${response.status}).`],
        };
        return;
      }
    } catch {
      quickCreateErrors.value = { _fetch: ["Failed to load form."] };
      return;
    }
  }

  initFormData();
  quickCreateOpen.value = true;
}

async function submitQuickCreate(): Promise<void> {
  if (!props.field.quickCreate || !quickCreateMeta.value) return;

  quickCreateLoading.value = true;
  quickCreateErrors.value = {};

  const url = `/${builderPrefix}/${props.field.quickCreate.resource}/quick-store`;
  const payload: Record<string, unknown> = {
    ...quickCreateFormData,
    _label_key: props.field.quickCreate.labelKey,
  };

  if (quickCreateMeta.value.currentLocale) {
    payload._locale = quickCreateMeta.value.currentLocale;
  }

  try {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-CSRF-TOKEN": csrfToken,
        Accept: "application/json",
      },
      body: JSON.stringify(payload),
    });

    const data = (await response.json()) as
      | { id: string | number; label: string }
      | { errors: Record<string, string[]> };

    if (!response.ok) {
      quickCreateErrors.value =
        (data as { errors: Record<string, string[]> }).errors ?? {};
      return;
    }

    const created = data as { id: string | number; label: string };

    extraOptions.value[String(created.id)] = created.label;
    emit("update:modelValue", String(created.id));
    quickCreateOpen.value = false;
  } finally {
    quickCreateLoading.value = false;
  }
}
</script>

<template>
  <!-- Multi-select: shadcn Popover with checkboxes -->
  <Popover v-if="field.multiple">
    <PopoverTrigger as-child>
      <button
        :id="field.name"
        type="button"
        :disabled="field.readonly"
        :class="
          cn(
            'border-input bg-background focus:ring-ring flex h-9 w-full items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
            error && 'border-destructive',
          )
        "
      >
        <span
          v-if="normalizedMultiValue.length === 0"
          class="text-muted-foreground"
        >
          Select…
        </span>
        <span v-else class="truncate text-left">
          {{ multiLabel }}
        </span>
        <svg
          class="h-4 w-4 shrink-0 opacity-50"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="M6 9l6 6 6-6"
          />
        </svg>
      </button>
    </PopoverTrigger>
    <PopoverContent align="start" class="min-w-[10rem] p-1">
      <div class="max-h-60 overflow-y-auto">
        <button
          v-for="(label, value) in effectiveOptions"
          :key="value"
          type="button"
          class="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent focus:bg-accent focus:outline-none"
          @click.prevent="toggleMultiOption(String(value))"
        >
          <CheckboxRoot
            :checked="normalizedMultiValue.includes(String(value))"
            class="border-input ring-offset-background h-4 w-4 shrink-0 rounded-sm border data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground"
            as="span"
          >
            <CheckboxIndicator
              class="flex items-center justify-center text-current"
            >
              <svg
                class="h-3 w-3"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
                stroke-width="3"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  d="M5 13l4 4L19 7"
                />
              </svg>
            </CheckboxIndicator>
          </CheckboxRoot>
          {{ label }}
        </button>
      </div>
    </PopoverContent>
  </Popover>

  <!-- Single-select: shadcn Select with optional quick-create button -->
  <template v-else>
    <div :class="field.quickCreate ? 'flex gap-2' : ''">
      <Select
        :model-value="normalizedSingleValue"
        :disabled="field.readonly"
        :class="field.quickCreate ? 'flex-1 min-w-0' : ''"
        @update:model-value="emit('update:modelValue', $event)"
      >
        <SelectTrigger
          :id="field.name"
          :name="field.name"
          :class="cn(error && 'border-destructive')"
        >
          <SelectValue placeholder="— Select —" />
        </SelectTrigger>
        <SelectContent>
          <template v-for="(label, value) in effectiveOptions" :key="value">
            <SelectItem v-if="String(value) !== ''" :value="String(value)">
              {{ label }}
            </SelectItem>
          </template>
        </SelectContent>
      </Select>

      <!-- Quick-create trigger button -->
      <button
        v-if="field.quickCreate"
        type="button"
        class="border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md border shadow-xs transition-colors"
        @click="openQuickCreate"
      >
        <svg
          class="h-4 w-4"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
          stroke-width="2"
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            d="M12 4v16m8-8H4"
          />
        </svg>
      </button>
    </div>

    <!-- Quick-create sheet (rendered outside the flex container to avoid layout issues) -->
    <Sheet v-if="field.quickCreate" v-model:open="quickCreateOpen">
      <SheetContent side="right" class="flex flex-col sm:max-w-md">
        <form class="contents" @submit.prevent="submitQuickCreate">
          <SheetHeader>
            <SheetTitle>
              {{ quickCreateMeta ? quickCreateMeta.singularLabel : "…" }}
            </SheetTitle>
          </SheetHeader>

          <div
            v-if="quickCreateMeta"
            class="flex-1 overflow-y-auto space-y-4 px-4 py-4"
          >
            <DynamicField
              v-for="f in quickCreateFields"
              :key="f.name"
              :field="f"
              :model-value="quickCreateFormData[f.name]"
              :error="(quickCreateErrors[f.name] ?? [])[0]"
              :current-locale="quickCreateMeta.currentLocale"
              @update:model-value="updateQuickCreateField(f.name, $event)"
            />
          </div>

          <div v-else class="flex-1 px-4 py-4">
            <div class="space-y-3">
              <div
                v-for="i in 3"
                :key="i"
                class="bg-muted h-10 animate-pulse rounded-md"
              />
            </div>
          </div>

          <SheetFooter>
            <Button
              type="button"
              variant="outline"
              @click="quickCreateOpen = false"
            >
              Cancel
            </Button>
            <Button
              type="submit"
              :disabled="quickCreateLoading || !quickCreateMeta"
            >
              {{
                quickCreateLoading
                  ? "Saving…"
                  : `Add ${quickCreateMeta?.singularLabel ?? ""}`
              }}
            </Button>
          </SheetFooter>
        </form>
      </SheetContent>
    </Sheet>
  </template>
</template>
