import {
  defineComponent,
  withDirectives,
} from 'vue'
import type { SetupContext } from '@vue/runtime-core'
import type { R } from '@/common/utils/http-util.ts'
import Utils from '@/common/utils'
import ADialog from '@/components/a-dialog/ADialog.vue'
import {
  ElButton,
  ElLoading,
} from 'element-plus'
import styles from '@/components/a-detail-panel/a-detail-panel.module.styl'

interface ADetailPanelType<D extends object> {
  title: string
  width: string
  detailsLoader: (id: string) => Promise<R<D> | undefined | null | void>
}

const component = defineComponent(
  <D extends object>(props: ADetailPanelType<D>, {slots, expose}: SetupContext) => {

    const showDialog = ref(false)
    const loading = ref(false)

    const detailData = Utils.resetAble(reactive<D>({} as D))
    const dialogCloseHandler = () => {
      detailData.$reset()
    }
    const open = (id: string) => {
      showDialog.value = true
      loading.value = true
      props.detailsLoader(id)
        .then(res => {
          detailData.$reset((res?.data ?? {}) as any)
        })
        .finally(() => {
          loading.value = false
        })
    }
    expose({open})
    return () => (
      <ADialog
        width={props.width}
        show={showDialog.value}
        onUpdate:show={show => showDialog.value = show}
        closed={dialogCloseHandler}
        title={props.title}>
        {{
          default: () => (withDirectives(
            <div class={[ styles.detailPanel, 'detail-panel-wrapper' ]}>
              {slots.default!(detailData as D)}
            </div>,
            [ [ ElLoading.directive, loading.value ] ],
          )),
          footer: () => (<div class={styles.footer}>
            {
              slots.footer?.(detailData as D)
            }
            <ElButton onClick={() => showDialog.value = false}>关闭</ElButton>
          </div>),
        }}
      </ADialog>
    )
  },
  {
    name: 'ADetailPanel',
    props: [ 'title', 'width', 'detailsLoader' ],
  },
)

export interface ADetailPanelInstance extends InstanceType<typeof component> {
  open: (id: string) => void
}


export function buildDetailPanelProps<D extends object>({title, width, detailsLoader}: DeepPartial<ADetailPanelType<D>>) {
  return reactive({
    title: title ?? '详情',
    width: width ?? 'fit-content',
    detailsLoader: detailsLoader ?? (() => Promise.resolve()),
  } as ADetailPanelType<D>)
}

export default component
