<script lang="ts" setup>
import { computed, watch } from 'vue';

import { $t } from '@easyflow/locales';

import { useEasyFlowModal } from '@easyflow-core/popup-ui';
import { EasyFlowButton } from '@easyflow-core/shadcn-ui';
import { cn } from '@easyflow-core/shared/utils';

type BeforeClose = () => boolean | Promise<boolean | void> | void;

interface Props {
  beforeClose?: BeforeClose;
  cancelText?: string;
  centered?: boolean;
  closable?: boolean;
  closeOnClickModal?: boolean;
  confirmDisabled?: boolean;
  confirmLoading?: boolean;
  confirmText?: string;
  description?: string;
  draggable?: boolean;
  modelValue?: boolean;
  open?: boolean;
  showCancelButton?: boolean;
  showConfirmButton?: boolean;
  showFooter?: boolean;
  showPreview?: boolean;
  submitting?: boolean;
  title: string;
  width?: 'lg' | 'md' | 'xl' | number | string;
}

defineOptions({
  name: 'EasyFlowFormModal',
});

const props = withDefaults(defineProps<Props>(), {
  beforeClose: undefined,
  cancelText: '',
  centered: false,
  closable: true,
  closeOnClickModal: false,
  confirmDisabled: false,
  confirmLoading: false,
  confirmText: '',
  description: '',
  draggable: false,
  modelValue: undefined,
  open: undefined,
  showCancelButton: true,
  showConfirmButton: true,
  showFooter: true,
  showPreview: false,
  submitting: false,
  width: 'lg',
});

const emit = defineEmits<{
  cancel: [];
  confirm: [];
  'update:modelValue': [boolean];
  'update:open': [boolean];
}>();

const [Modal, modalApi] = useEasyFlowModal({
  async onBeforeClose() {
    const result = await props.beforeClose?.();
    return result !== false;
  },
  onOpenChange(isOpen) {
    emit('update:modelValue', isOpen);
    emit('update:open', isOpen);
  },
});

const widthClassMap: Record<string, string> = {
  '482': 'sm:w-[482px]',
  '482px': 'sm:w-[482px]',
  '50%': 'sm:w-[min(50vw,720px)]',
  '500px': 'sm:w-[500px]',
  '520px': 'sm:w-[520px]',
  '550px': 'sm:w-[550px]',
  '600px': 'sm:w-[600px]',
  '762': 'sm:w-[762px]',
  '762px': 'sm:w-[762px]',
  '800px': 'sm:w-[800px]',
  '80%': 'sm:w-[min(80vw,1120px)]',
  'min(920px, 92vw)': 'sm:w-[min(92vw,920px)]',
  'min(980px, 92vw)': 'sm:w-[min(92vw,980px)]',
  md: 'sm:w-[560px]',
  lg: 'sm:w-[720px]',
  xl: 'sm:w-[960px]',
};

const modalClass = computed(() => {
  const widthKey = String(props.width);
  return cn(
    'w-[calc(100vw-24px)] max-w-[calc(100vw-24px)] sm:max-w-[min(calc(100vw-48px),960px)]',
    widthClassMap[widthKey] || widthClassMap.lg,
  );
});

watch(
  () => props.open ?? props.modelValue ?? false,
  (value) => {
    modalApi.setState({ isOpen: value });
  },
  { immediate: true },
);

function handleCancel() {
  emit('cancel');
  modalApi.close();
}

function handleConfirm() {
  emit('confirm');
}
</script>

<template>
  <Modal
    :bordered="false"
    :class="modalClass"
    :centered="centered"
    :closable="closable"
    :close-on-click-modal="closeOnClickModal"
    :confirm-disabled="confirmDisabled || submitting"
    :confirm-loading="confirmLoading"
    content-class="p-0"
    :description="description"
    :draggable="draggable"
    :footer="showFooter"
    :fullscreen-button="false"
    :show-cancel-button="false"
    :show-confirm-button="false"
    :submitting="submitting"
    :title="title"
  >
    <div class="flex flex-col">
      <section
        v-if="showPreview && $slots.preview"
        class="bg-[linear-gradient(135deg,hsl(var(--modal-preview-surface))/0.96),hsl(var(--modal-preview-surface-strong))/0.88)] border-b border-[hsl(var(--modal-divider))/0.9] px-5 py-4 sm:px-6"
      >
        <slot name="preview"></slot>
      </section>

      <div class="px-5 pb-5 pt-4 sm:px-6 sm:pb-6 sm:pt-5">
        <slot></slot>
      </div>
    </div>

    <template v-if="showFooter" #footer>
      <div class="flex w-full items-center justify-between gap-3">
        <div class="min-w-0 flex-1">
          <slot name="footer-extra"></slot>
        </div>
        <div class="flex items-center gap-3">
          <EasyFlowButton
            v-if="showCancelButton"
            variant="ghost"
            :disabled="submitting"
            @click="handleCancel"
          >
            {{ cancelText || $t('button.cancel') }}
          </EasyFlowButton>
          <EasyFlowButton
            v-if="showConfirmButton"
            :disabled="confirmDisabled || submitting"
            :loading="confirmLoading || submitting"
            @click="handleConfirm"
          >
            {{ confirmText || $t('button.confirm') }}
          </EasyFlowButton>
        </div>
      </div>
    </template>
  </Modal>
</template>
