<script setup lang="ts">
import { computed, provide, ref, toRef } from "vue";
import { Head, router, useForm, usePage } from "@inertiajs/vue3";
import { useBuilderRoutes } from "../../composables/useBuilderRoutes";
import Button from "../../components/ui/Button.vue";
import Dialog from "../../components/ui/Dialog.vue";
import DialogScrollContent from "../../components/ui/DialogScrollContent.vue";
import DialogHeader from "../../components/ui/DialogHeader.vue";
import DialogTitle from "../../components/ui/DialogTitle.vue";
import DialogDescription from "../../components/ui/DialogDescription.vue";
import DialogFooter from "../../components/ui/DialogFooter.vue";
import FormActionBar from "../../components/FormActionBar.vue";
import type { RecordActionDef } from "../../components/FormActionBar.vue";
import FormSection from "../../components/FormSection.vue";
import PageHeader from "../../components/PageHeader.vue";
import HorizontalTabNavigation from "../../components/HorizontalTabNavigation.vue";
import { useTranslations } from "../../composables/useTranslations";
import { useBuilderPrefix } from "../../composables/useBuilderPrefix";
import { useFormSections } from "../../composables/useFormSections";
import { useAutoGenerateFields } from "../../composables/useAutoGenerateFields";
import { useTabGroups } from "../../composables/useTabGroups";
import type {
  FormResourceDefinition,
  FormField,
} from "../../composables/useFormSections";
import {
  hierarchyContextKey,
  type HierarchyOption,
} from "../../composables/useHierarchyContext";
import { formLocaleKey } from "../../composables/useFormLocale";
import { provideFormSlugBase } from "../../composables/useFormSlugBase";
import type { Language } from "../../types";

const { t } = useTranslations();
const prefix = useBuilderPrefix();
const routes = useBuilderRoutes();

const props = defineProps<{
  resource: FormResourceDefinition;
  record: Record<string, unknown> | null;
  currentLocale: string | null;
  availableLocales: Language[];
  // Per-record actions filtered server-side (only present on edit)
  record_actions?: Array<{ key: string; label: string; confirm: boolean }>;
  can_delete?: boolean;
  revision_count?: number | null;
}>();

const isEditing = computed(() => props.record !== null);

const allFields = computed<FormField[]>(() =>
  props.resource.sections.flatMap((s) => s.fields),
);

// Hierarchy: parent slug prefix for slug auto-generation preview.
// On edit, the server passes _parentSlug; on create it starts empty.
const parentOption = ref<HierarchyOption | null>(
  props.resource.isHierarchical && props.record?.["_parentSlug"]
    ? {
        id: props.record[props.resource.parentField] as string | number,
        label: "",
        slug: props.record["_parentSlug"] as string,
      }
    : null,
);

const parentSlugPrefix = computed<string>(
  () => (parentOption.value?.slug as string) ?? "",
);

provide(formLocaleKey, props.currentLocale);

const page = usePage();
const slugBase = computed<string>(() => {
  const base = props.resource.publicUrlBase ?? "";
  // Only show URL preview when the resource has a public URL base configured.
  if (!base) return "";
  const publicUrl =
    ((page.props as Record<string, unknown>).publicUrl as string | undefined) ??
    "";
  const isDefault =
    props.availableLocales.find((l) => l.code === props.currentLocale)
      ?.is_default ?? true;
  const localePart =
    !isDefault && props.currentLocale ? props.currentLocale : "";
  return [publicUrl, localePart, base]
    .filter(Boolean)
    .join("/")
    .replace(/\/+$/, "");
});
provideFormSlugBase(slugBase);

if (props.resource.isHierarchical) {
  provide(hierarchyContextKey, {
    parentField: props.resource.parentField,
    parentSlugPrefix,
    setParentOption: (option: HierarchyOption) => {
      parentOption.value = option;
    },
    clearParentOption: () => {
      parentOption.value = null;
    },
  });
}

// When editing, strip the parent slug prefix from generateFrom fields so the
// input shows only the local part (e.g. "team" instead of "over-ons/team").
const initialData = Object.fromEntries(
  allFields.value.map((f) => {
    let value = props.record?.[f.name] ?? f.default;
    if (f.generateFrom && parentSlugPrefix.value && typeof value === "string") {
      const prefix = parentSlugPrefix.value + "/";
      if (value.startsWith(prefix)) {
        value = value.slice(prefix.length);
      }
    }
    return [f.name, value];
  }),
);

const form = useForm({
  _locale: props.currentLocale ?? "",
  ...initialData,
});

// Provide the live form data so field components (e.g. FieldSeoInput) can
// read sibling field values reactively without receiving them as props.
provide("builderFormValues", form);

useAutoGenerateFields(
  form as unknown as Record<string, unknown>,
  allFields,
  initialData,
);

const hasLocales = computed(() => props.availableLocales.length > 1);

function switchLocale(code: string) {
  if (form.isDirty && !confirm(t("builder.resources.unsaved_locale_switch"))) {
    return;
  }
  const url = props.record?.id
    ? `/${prefix}/${props.resource.slug}/${props.record.id}/edit`
    : `/${prefix}/${props.resource.slug}/create`;
  router.get(url, { locale: code });
}

function submit() {
  const url = isEditing.value
    ? `/${prefix}/${props.resource.slug}/${props.record!.id}`
    : `/${prefix}/${props.resource.slug}`;

  const slugFieldNames = allFields.value
    .filter((f) => f.generateFrom !== null)
    .map((f) => f.name);

  const withPrefix = form.transform((data) => {
    if (!props.resource.isHierarchical || !parentSlugPrefix.value) {
      return data;
    }
    const transformed = { ...data } as Record<string, unknown>;
    for (const name of slugFieldNames) {
      const local = transformed[name];
      if (local && typeof local === "string") {
        transformed[name] = `${parentSlugPrefix.value}/${local}`;
      }
    }
    return transformed;
  });

  if (isEditing.value) {
    const formData = form as unknown as Record<string, unknown>;
    const optimisticRecord: Record<string, unknown> = {};
    for (const f of allFields.value) {
      let value = formData[f.name];
      if (
        f.generateFrom &&
        parentSlugPrefix.value &&
        typeof value === "string"
      ) {
        value = `${parentSlugPrefix.value}/${value}`;
      }
      optimisticRecord[f.name] = value;
    }

    withPrefix
      .optimistic((pageProps) => ({
        record: {
          ...(pageProps.record as Record<string, unknown>),
          ...optimisticRecord,
        },
      }))
      .put(url);
  } else {
    withPrefix.post(url);
  }
}

const confirmDelete = ref(false);

function deleteRecord(): void {
  const localeParam = props.currentLocale
    ? `?locale=${props.currentLocale}`
    : "";
  router.delete(
    `/${prefix}/${props.resource.slug}/${props.record!.id}${localeParam}`,
  );
}

function sectionHasErrors(section: { fields: { name: string }[] }): boolean {
  return section.fields.some(
    (f) =>
      f.name in form.errors ||
      Object.keys(form.errors).some((k) => k.startsWith(f.name + ".")),
  );
}

// Section logic
const { mainSections, sidebarSections, hasSidebarSections } = useFormSections(
  toRef(props, "resource"),
  toRef(props, "currentLocale"),
);

// Tab group logic
const { activeTabPerGroup, buildContentItems } = useTabGroups();
const orderedContent = computed(() => buildContentItems(mainSections.value));

// Sidebar tab group logic
const {
  activeTabPerGroup: sidebarActiveTabPerGroup,
  buildContentItems: buildSidebarContentItems,
} = useTabGroups();
const orderedSidebarContent = computed(() =>
  buildSidebarContentItems(sidebarSections.value),
);

const pageTitle = computed((): string => {
  if (isEditing.value) {
    return (
      ((props.record?.name ?? props.record?.title ?? null) as string | null) ??
      props.resource.label
    );
  }
  return t("builder.resources.create_title", {
    label: props.resource.singularLabel.toLowerCase(),
  });
});

const recordActions = computed((): RecordActionDef[] => {
  if (!isEditing.value) {
    return [];
  }
  const raw = props.record_actions ?? [];
  return raw.map((a) => ({
    ...a,
    url: `/${prefix}/${props.resource.slug}/${props.record!.id}/action/${a.key}`,
  }));
});

const duplicateUrl = computed((): string | null => {
  if (!isEditing.value || !props.resource.duplicatable) {
    return null;
  }
  return `/${prefix}/${props.resource.slug}/${props.record!.id}/duplicate`;
});
</script>

<template>
  <Head :title="pageTitle" />

  <form @submit.prevent="submit">
    <PageHeader
      :title="pageTitle"
      :back-href="`/${prefix}/${resource.slug}`"
      :back-label="t('builder.resources.back_to_overview')"
      :current-locale="currentLocale"
      :languages="availableLocales"
      :on-switch-locale="switchLocale"
    />

    <FormActionBar
      :is-editing="isEditing"
      :record="record"
      :processing="form.processing"
      :show-timestamps="resource.showTimestamps"
      :can-delete="isEditing && (can_delete ?? true)"
      :record-actions="recordActions"
      :duplicate-url="duplicateUrl"
      :is-revisable="resource.isRevisable"
      :revisions-url="
        isEditing && record
          ? routes.resourceRevisions(
              resource.slug,
              record['id'] as string | number,
            )
          : null
      "
      @delete="confirmDelete = true"
    />

    <!-- Content: main column + optional sidebar -->
    <div
      :class="
        hasSidebarSections
          ? 'grid grid-cols-1 xl:grid-cols-[1fr_380px]'
          : 'w-full'
      "
    >
      <!-- Main column -->
      <div>
        <template
          v-for="(item, index) in orderedContent"
          :key="
            item.type === 'tab-group'
              ? '__tab__' + item.groupKey
              : item.section.key
          "
        >
          <!-- Tab group -->
          <div v-if="item.type === 'tab-group'" class="py-6">
            <div
              :class="
                hasSidebarSections
                  ? '-ml-6 pl-6 border-b mb-6'
                  : '-mx-6 px-6 border-b mb-6'
              "
            >
              <HorizontalTabNavigation
                v-model="activeTabPerGroup[item.groupKey]"
                :tabs="
                  item.sections.map((s) => ({
                    key: s.key,
                    label: s.label,
                    hasError: sectionHasErrors(s),
                  }))
                "
              />
            </div>

            <template v-for="tab in item.sections" :key="tab.key">
              <div
                v-if="activeTabPerGroup[item.groupKey] === tab.key"
                :class="hasSidebarSections ? 'space-y-4 xl:pr-6' : 'space-y-4'"
              >
                <FormSection
                  :section="tab"
                  :form="form as Record<string, unknown>"
                  :errors="form.errors"
                  :current-locale="currentLocale"
                  @update:field="
                    (name, value) =>
                      ((form as Record<string, unknown>)[name] = value)
                  "
                />
              </div>
            </template>
          </div>

          <!-- Regular section -->
          <div
            v-else
            :class="[
              hasSidebarSections ? 'py-6 xl:pr-6' : 'py-6',
              index > 0 ? 'border-t' : '',
            ]"
          >
            <FormSection
              :section="item.section"
              :form="form as Record<string, unknown>"
              :errors="form.errors"
              :current-locale="currentLocale"
              @update:field="
                (name, value) =>
                  ((form as Record<string, unknown>)[name] = value)
              "
            />
          </div>
        </template>
      </div>

      <!-- Sidebar column -->
      <div
        v-if="hasSidebarSections"
        class="space-y-6 border-t pt-6 pr-6 xl:border-t-0 xl:border-l xl:pl-8 self-stretch"
      >
        <template
          v-for="(item, index) in orderedSidebarContent"
          :key="
            item.type === 'tab-group'
              ? '__tab__' + item.groupKey
              : item.section.key
          "
        >
          <!-- Tab group -->
          <div v-if="item.type === 'tab-group'">
            <div class="-ml-8 pl-8 -mr-6 pr-6 border-b mb-4">
              <HorizontalTabNavigation
                v-model="sidebarActiveTabPerGroup[item.groupKey]"
                :tabs="
                  item.sections.map((s) => ({
                    key: s.key,
                    label: s.label,
                    hasError: sectionHasErrors(s),
                  }))
                "
              />
            </div>

            <template v-for="tab in item.sections" :key="tab.key">
              <div v-if="sidebarActiveTabPerGroup[item.groupKey] === tab.key">
                <FormSection
                  :section="tab"
                  :form="form as Record<string, unknown>"
                  :errors="form.errors"
                  :current-locale="currentLocale"
                  :sidebar="true"
                  @update:field="
                    (name, value) =>
                      ((form as Record<string, unknown>)[name] = value)
                  "
                />
              </div>
            </template>
          </div>

          <!-- Regular section -->
          <div
            v-else
            :class="index > 0 ? '-ml-8 -mr-6 pl-8 pr-6 border-t pt-6' : ''"
          >
            <FormSection
              :section="item.section"
              :form="form as Record<string, unknown>"
              :errors="form.errors"
              :current-locale="currentLocale"
              :sidebar="true"
              @update:field="
                (name, value) =>
                  ((form as Record<string, unknown>)[name] = value)
              "
            />
          </div>
        </template>
      </div>
    </div>

    <!-- Delete confirmation dialog -->
    <Dialog v-model:open="confirmDelete">
      <DialogScrollContent>
        <DialogHeader>
          <DialogTitle>
            {{ t("builder.resources.delete_confirm_title") }}
          </DialogTitle>
          <DialogDescription>
            {{ t("builder.resources.delete_confirm_message") }}
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <Button
            type="button"
            variant="outline"
            @click="confirmDelete = false"
          >
            {{ t("builder.resources.cancel") }}
          </Button>
          <Button type="button" variant="destructive" @click="deleteRecord">
            {{ t("builder.resources.delete") }}
          </Button>
        </DialogFooter>
      </DialogScrollContent>
    </Dialog>
  </form>
</template>
