<script setup lang="ts">
import { computed, defineAsyncComponent, ref, watch } from "vue";
import {
  Sheet,
  SheetContent,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  UiButton,
} from "@builder/ui";
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 { useTranslations } from "@/composables/useTranslations";
const DynamicField = defineAsyncComponent(
  () => import("@/components/DynamicField.vue"),
);
import type { FieldDefinition } from "./types";
import type {
  NestedRecord,
  PublicResource,
  PublicResourceItem,
} from "./NestedResourceEditor.vue";
import type { Language } from "../../types";

const props = defineProps<{
  modelValue: boolean;
  record: NestedRecord | null;
  schema: FieldDefinition[];
  currentLocale: string;
  availableLocales: Language[];
  publicResources: PublicResource[];
  addTitle: string;
  editTitle: string;
  linkTypeUrlLabel: string;
  linkTypeResourceLabel: string;
  selectTypeLabel: string;
  selectRecordLabel: string;
}>();

const emit = defineEmits<{
  "update:modelValue": [open: boolean];
  save: [record: NestedRecord];
}>();

const { t } = useTranslations();

// ─── Form state ───────────────────────────────────────────────────────────────

const form = ref<NestedRecord>({ _key: "" });
const linkMode = ref<"resource" | "url">("resource");
const selectedResourceType = ref<string>("");

function buildEmptyTranslations(): Record<string, Record<string, unknown>> {
  const result: Record<string, Record<string, unknown>> = {};
  for (const locale of props.availableLocales) {
    result[locale.code] = {};
  }
  if (props.currentLocale && !result[props.currentLocale]) {
    result[props.currentLocale] = {};
  }
  return result;
}

function initForm(record: NestedRecord | null): void {
  if (record) {
    form.value = {
      ...record,
      translations: record.translations
        ? Object.fromEntries(
            Object.entries(record.translations).map(([locale, tr]) => [
              locale,
              { ...(tr as object) },
            ]),
          )
        : buildEmptyTranslations(),
    };
    if (record.resource_type) {
      linkMode.value = "resource";
      selectedResourceType.value = record.resource_type as string;
    } else {
      linkMode.value = "url";
      selectedResourceType.value = "";
    }
  } else {
    const defaults: Record<string, unknown> = {};
    for (const f of props.schema) {
      if (f.default !== null && !f.translatable) {
        defaults[f.name] = f.default;
      }
    }
    form.value = {
      _key: "",
      id: null,
      parent_id: null,
      sort_order: 0,
      resource_type: null,
      resource_id: null,
      meta: {},
      ...defaults,
      translations: buildEmptyTranslations(),
    };
    linkMode.value = props.publicResources.length > 0 ? "resource" : "url";
    selectedResourceType.value = "";
  }
}

watch(
  () => props.modelValue,
  (open) => {
    if (open) {
      initForm(props.record);
    }
  },
);

watch(() => props.record, initForm, { immediate: true });

// ─── Field value helpers ──────────────────────────────────────────────────────

function getFieldValue(field: FieldDefinition): unknown {
  if (field.translatable) {
    const translations = form.value.translations as Record<
      string,
      Record<string, unknown>
    >;
    return translations?.[props.currentLocale]?.[field.name] ?? null;
  }
  return form.value[field.name] ?? field.default;
}

function setFieldValue(field: FieldDefinition, value: unknown): void {
  if (field.translatable) {
    if (!form.value.translations) {
      form.value.translations = {};
    }
    const translations = form.value.translations as Record<
      string,
      Record<string, unknown>
    >;
    if (!translations[props.currentLocale]) {
      translations[props.currentLocale] = {};
    }
    translations[props.currentLocale][field.name] = value;
  } else {
    form.value = { ...form.value, [field.name]: value };
  }
}

// ─── Link mode (resource vs URL) ─────────────────────────────────────────────

const showLinkPicker = computed(() => props.publicResources.length > 0);

function setLinkMode(mode: "resource" | "url"): void {
  linkMode.value = mode;
  if (mode === "url") {
    form.value = { ...form.value, resource_type: null, resource_id: null };
    selectedResourceType.value = "";
  } else {
    const translations = {
      ...((form.value.translations as Record<
        string,
        Record<string, unknown>
      >) ?? {}),
    };
    for (const locale of Object.keys(translations)) {
      translations[locale] = { ...translations[locale], url: "" };
    }
    form.value = {
      ...form.value,
      translations,
      resource_type: null,
      resource_id: null,
    };
  }
}

function setResourceType(slug: string): void {
  selectedResourceType.value = slug;
  form.value = {
    ...form.value,
    resource_type: slug || null,
    resource_id: null,
  };
}

function setResourceId(id: string): void {
  form.value = {
    ...form.value,
    resource_id: id ? Number(id) : null,
  };
}

const resourceItems = computed((): PublicResourceItem[] => {
  if (!selectedResourceType.value) return [];
  return (
    props.publicResources.find((r) => r.slug === selectedResourceType.value)
      ?.items ?? []
  );
});

// ─── Visible fields ───────────────────────────────────────────────────────────

const visibleFields = computed(() =>
  props.schema.filter((f) => {
    if (f.component === "HiddenInput") return false;
    if (f.name === "url" && linkMode.value === "resource") return false;
    return true;
  }),
);

// ─── Save ─────────────────────────────────────────────────────────────────────

function save(): void {
  emit("save", { ...form.value });
  emit("update:modelValue", false);
}
</script>

<template>
  <Sheet :open="modelValue" @update:open="$emit('update:modelValue', $event)">
    <SheetContent
      side="right"
      class="flex flex-col overflow-hidden sm:max-w-md"
    >
      <form class="contents" @submit.prevent="save">
        <SheetHeader class="shrink-0 border-b">
          <SheetTitle>
            {{ record ? editTitle : addTitle }}
          </SheetTitle>
        </SheetHeader>

        <!-- Scrollable body -->
        <div class="flex-1 space-y-5 overflow-y-auto px-4 py-4">
          <!-- Link mode picker (resource vs URL) -->
          <template v-if="showLinkPicker">
            <div
              class="flex overflow-hidden rounded-md border border-border text-sm"
            >
              <!-- Existing resource — first -->
              <button
                type="button"
                class="flex-1 px-3 py-1.5 transition-colors"
                :class="
                  linkMode === 'resource'
                    ? 'bg-foreground text-background'
                    : 'text-muted-foreground hover:bg-muted'
                "
                @click="setLinkMode('resource')"
              >
                {{ linkTypeResourceLabel }}
              </button>
              <!-- URL — second -->
              <button
                type="button"
                class="flex-1 border-l px-3 py-1.5 transition-colors"
                :class="
                  linkMode === 'url'
                    ? 'bg-foreground text-background'
                    : 'text-muted-foreground hover:bg-muted'
                "
                @click="setLinkMode('url')"
              >
                {{ linkTypeUrlLabel }}
              </button>
            </div>

            <!-- Resource selects -->
            <template v-if="linkMode === 'resource'">
              <!-- Resource type -->
              <div class="space-y-1.5">
                <label class="text-sm font-medium text-foreground">
                  Type
                </label>
                <Select
                  :model-value="selectedResourceType"
                  @update:model-value="setResourceType($event)"
                >
                  <SelectTrigger>
                    <SelectValue :placeholder="selectTypeLabel" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem
                      v-for="r in publicResources"
                      :key="r.slug"
                      :value="r.slug"
                    >
                      {{ r.label }}
                    </SelectItem>
                  </SelectContent>
                </Select>
              </div>

              <!-- Record within that resource -->
              <div v-if="selectedResourceType" class="space-y-1.5">
                <label class="text-sm font-medium text-foreground">
                  {{
                    publicResources.find((r) => r.slug === selectedResourceType)
                      ?.label ?? "Record"
                  }}
                </label>
                <Select
                  :model-value="
                    form.resource_id ? String(form.resource_id) : ''
                  "
                  @update:model-value="setResourceId($event)"
                >
                  <SelectTrigger>
                    <SelectValue :placeholder="selectRecordLabel" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem
                      v-for="item in resourceItems"
                      :key="item.id"
                      :value="String(item.id)"
                    >
                      {{ item.label }}
                    </SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </template>
          </template>

          <!-- Schema fields (label, url if in url mode, target, etc.) -->
          <DynamicField
            v-for="f in visibleFields"
            :key="f.name"
            :field="f"
            :model-value="getFieldValue(f)"
            :current-locale="sheetLocale"
            @update:model-value="setFieldValue(f, $event)"
          />
        </div>

        <SheetFooter class="shrink-0 border-t">
          <UiButton
            type="button"
            variant="outline"
            @click="$emit('update:modelValue', false)"
          >
            {{ t("builder.resources.cancel") }}
          </UiButton>
          <UiButton type="submit">
            {{ t("builder.resources.save") }}
          </UiButton>
        </SheetFooter>
      </form>
    </SheetContent>
  </Sheet>
</template>
