<script lang="ts" setup>
import { computed, useAttrs, 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 {
  alignCenter?: boolean;
  beforeClose?: BeforeClose;
  cancelText?: string;
  centered?: boolean;
  closable?: boolean;
  closeOnClickModal?: boolean;
  confirmLoading?: boolean;
  confirmText?: string;
  description?: string;
  destroyOnClose?: boolean;
  draggable?: boolean;
  modelValue?: boolean;
  open?: boolean;
  showCancelButton?: boolean;
  showConfirmButton?: boolean;
  showFooter?: boolean;
  submitting?: boolean;
  title: string;
  width?: 'lg' | 'md' | 'xl' | number | string;
}

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

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

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

const attrs = useAttrs();

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),1120px)]',
    widthClassMap[widthKey] || widthClassMap.lg,
    attrs.class,
  );
});

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
    :class="modalClass"
    :centered="centered || alignCenter"
    :closable="closable"
    :close-on-click-modal="closeOnClickModal"
    :confirm-loading="confirmLoading"
    :description="description"
    :destroy-on-close="destroyOnClose"
    :draggable="draggable"
    :footer="showFooter"
    :fullscreen-button="false"
    :show-cancel-button="false"
    :show-confirm-button="false"
    :submitting="submitting"
    :title="title"
  >
    <slot></slot>

    <template v-if="showFooter" #footer>
      <slot name="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="submitting"
              :loading="confirmLoading || submitting"
              @click="handleConfirm"
            >
              {{ confirmText || $t('button.confirm') }}
            </EasyFlowButton>
          </div>
        </div>
      </slot>
    </template>
  </Modal>
</template>
