<script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core'
import type { AuditType } from 'nocodb-sdk'
import { timeAgo } from 'nocodb-sdk'

const props = defineProps<{
  loading: boolean
}>()

const { loadCommentsAndLogs, commentsAndLogs, saveComment: _saveComment, comment, updateComment } = useExpandedFormStoreOrThrow()

const { isExpandedFormCommentMode } = storeToRefs(useConfigStore())

const commentsWrapperEl = ref<HTMLDivElement>()

const { user, appInfo } = useGlobal()

const isExpandedFormLoading = computed(() => props.loading)

const tab = ref<'comments' | 'audits'>('comments')

const { isUIAllowed } = useRoles()

const hasEditPermission = computed(() => isUIAllowed('commentEdit'))

const editLog = ref<AuditType>()

const isEditing = ref<boolean>(false)

const isCommentMode = ref(false)

const focusCommentInput: VNodeRef = (el) => {
  if (!isExpandedFormLoading.value && (isCommentMode.value || isExpandedFormCommentMode.value) && !isEditing.value) {
    if (isExpandedFormCommentMode.value) {
      setTimeout(() => {
        isExpandedFormCommentMode.value = false
      }, 400)
    }
    return (el as HTMLInputElement)?.focus()
  }
  return el
}
const focusInput: VNodeRef = (el) => (el as HTMLInputElement)?.focus()

function onKeyDown(event: KeyboardEvent) {
  if (event.key === 'Escape') {
    onKeyEsc(event)
  } else if (event.key === 'Enter' && !event.shiftKey) {
    onKeyEnter(event)
  }
}

function onKeyEnter(event: KeyboardEvent) {
  event.stopImmediatePropagation()
  event.preventDefault()
  onEditComment()
}

function onKeyEsc(event: KeyboardEvent) {
  event.stopImmediatePropagation()
  event.preventDefault()
  onCancel()
}

async function onEditComment() {
  if (!isEditing.value || !editLog.value) return

  isCommentMode.value = true

  await updateComment(editLog.value.id!, {
    description: editLog.value.description,
  })
  onStopEdit()
}

function onCancel() {
  if (!isEditing.value) return
  editLog.value = undefined
  onStopEdit()
}

function onStopEdit() {
  loadCommentsAndLogs()
  isEditing.value = false
  editLog.value = undefined
}

onKeyStroke('Enter', (event) => {
  if (isEditing.value) {
    onKeyEnter(event)
  }
})

const comments = computed(() => commentsAndLogs.value.filter((log) => log.op_type === 'COMMENT'))
const audits = computed(() => commentsAndLogs.value.filter((log) => log.op_type !== 'COMMENT' && log.details))

function editComment(log: AuditType) {
  editLog.value = log
  isEditing.value = true
}

const value = computed({
  get() {
    return editLog.value?.description?.substring(editLog.value?.description?.indexOf(':') + 1) ?? ''
  },
  set(val) {
    if (!editLog.value) return
    editLog.value.description = val
  },
})

function scrollComments() {
  if (commentsWrapperEl.value) commentsWrapperEl.value.scrollTop = commentsWrapperEl.value?.scrollHeight
}

const isSaving = ref(false)

const saveComment = async () => {
  if (isSaving.value) return

  isCommentMode.value = true
  isSaving.value = true

  try {
    await _saveComment()

    scrollComments()
  } catch (e) {
    console.error(e)
  } finally {
    isSaving.value = false
  }
}

watch(commentsWrapperEl, () => {
  scrollComments()
})
</script>

<template>
  <div class="flex flex-col !h-full w-full">
    <NcTabs v-model:activeKey="tab" class="h-full">
      <a-tab-pane key="comments" class="w-full h-full">
        <template #tab>
          <div v-e="['c:row-expand:comment']" class="flex items-center gap-2">
            <GeneralIcon icon="messageCircle" class="w-4 h-4" />
            <span class="<lg:hidden"> Comments </span>
          </div>
        </template>
        <div
          class="h-full"
          :class="{
            'pb-1': tab !== 'comments' && !appInfo.ee,
          }"
        >
          <div v-if="isExpandedFormLoading" class="flex flex-col h-full">
            <GeneralLoader class="!mt-16" size="xlarge" />
          </div>
          <div v-else class="flex flex-col h-full">
            <div v-if="comments.length === 0" class="flex flex-col my-1 text-center justify-center h-full nc-scrollbar-thin">
              <div class="text-center text-3xl text-gray-700">
                <GeneralIcon icon="commentHere" />
              </div>
              <div class="font-medium text-center my-6 text-gray-500">{{ $t('activity.startCommenting') }}</div>
            </div>
            <div v-else ref="commentsWrapperEl" class="flex flex-col h-full py-1 nc-scrollbar-thin">
              <div v-for="log of comments" :key="log.id">
                <div class="group gap-3 overflow-hidden hover:bg-gray-200 flex items-start px-3 pt-3 pb-4">
                  <GeneralUserIcon size="medium" :name="log.display_name" :email="log.user" class="mt-0.7" />
                  <div class="flex-1 flex flex-col gap-0.5 max-w-[calc(100%_-_24px)]">
                    <div class="w-full flex justify-between gap-3 min-h-7">
                      <div class="flex items-center max-w-[calc(100%_-_40px)]">
                        <div class="w-full flex flex-wrap items-center">
                          <NcTooltip class="truncate max-w-42 mr-2" show-on-truncate-only>
                            <template #title>
                              {{ log.display_name?.trim() || log.user || 'Shared source' }}
                            </template>
                            <span
                              class="text-ellipsis overflow-hidden text-gray-500 font-weight-500 text-small"
                              :style="{
                                wordBreak: 'keep-all',
                                whiteSpace: 'nowrap',
                                display: 'inline',
                              }"
                            >
                              {{ log.display_name?.trim() || log.user || 'Shared source' }}
                            </span>
                          </NcTooltip>
                          <div v-if="log.id !== editLog?.id" class="text-xs text-gray-400">
                            {{
                              log.created_at !== log.updated_at ? `Edited ${timeAgo(log.updated_at)}` : timeAgo(log.created_at)
                            }}
                          </div>
                        </div>
                      </div>

                      <NcDropdown
                        v-if="log.user === user!.email && !editLog"
                        placement="bottomRight"
                        overlay-class-name="!min-w-[160px]"
                      >
                        <NcButton
                          type="text"
                          size="xsmall"
                          class="nc-expand-form-more-actions !w-7 !h-7 !hover:(bg-transparent text-brand-500)"
                        >
                          <GeneralIcon icon="threeDotVertical" class="text-md invisible group-hover:visible" />
                        </NcButton>
                        <template #overlay>
                          <NcMenu>
                            <NcMenuItem v-e="['c:row-expand:comment:edit']" class="text-gray-700" @click="editComment(log)">
                              <div class="flex gap-2 items-center">
                                <component :is="iconMap.rename" class="cursor-pointer" />
                                {{ $t('general.edit') }}
                              </div>
                            </NcMenuItem>
                            <!-- eslint-disable vue/no-constant-condition -->
                            <template v-if="false">
                              <NcDivider />
                              <NcMenuItem v-e="['c:row-expand:comment:delete']" class="!text-red-500 !hover:bg-red-50">
                                <div class="flex gap-2 items-center">
                                  <GeneralIcon icon="delete" />
                                  {{ $t('general.delete') }}
                                </div>
                              </NcMenuItem>
                            </template>
                          </NcMenu>
                        </template>
                      </NcDropdown>
                    </div>

                    <a-textarea
                      v-if="log.id === editLog?.id"
                      :ref="focusInput"
                      v-model:value="value"
                      class="!p-1.5 !m-0 w-full !rounded-md !text-gray-800 !text-small !leading-18px !min-h-[70px] nc-scrollbar-thin"
                      @keydown.stop="onKeyDown($event)"
                    />
                    <div v-else class="nc-comment-description text-small leading-18px text-gray-800">
                      <pre>{{ log.description.substring(log.description.indexOf(':') + 1).trim() }}</pre>
                    </div>
                    <div v-if="log.id === editLog?.id" class="flex justify-end gap-1 mt-1">
                      <NcButton size="small" type="secondary" @click="onCancel"> Cancel </NcButton>
                      <NcButton v-e="['a:row-expand:comment:save']" size="small" @click="onEditComment"> Save </NcButton>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div v-if="hasEditPermission" class="p-3 gap-2 flex">
              <div class="flex flex-row w-full items-end gap-2">
                <div class="expanded-form-comment-input-wrapper">
                  <a-textarea
                    :ref="focusCommentInput"
                    v-model:value="comment"
                    class="expanded-form-comment-input !py-1.5 !px-3 !m-0 w-full !border-1 !border-gray-200 !rounded-lg !bg-transparent !text-gray-800 !text-small !leading-18px !max-h-[694px] nc-scrollbar-thin"
                    auto-size
                    hide-details
                    :disabled="isSaving"
                    placeholder="Comment..."
                    data-testid="expanded-form-comment-input"
                    @keydown.stop
                    @keydown.enter.exact.prevent="saveComment"
                  />
                </div>
                <NcButton
                  v-e="['a:row-expand:comment:save']"
                  size="small"
                  :loading="isSaving"
                  :disabled="!isSaving && !comment.length"
                  :icon-only="isSaving"
                  class="!disabled:bg-gray-100 !shadow-none"
                  @click="saveComment"
                >
                  <GeneralIcon v-if="!isSaving" icon="send" />
                </NcButton>
              </div>
            </div>
          </div>
        </div>
      </a-tab-pane>

      <a-tab-pane key="audits" class="w-full" :disabled="appInfo.ee">
        <template #tab>
          <NcTooltip v-if="appInfo.ee" class="tab flex-1">
            <template #title>
              <span class="!text-base"> Coming soon </span>
            </template>

            <div v-e="['c:row-expand:audit']" class="flex items-center gap-2 text-gray-400">
              <GeneralIcon icon="audit" class="w-4 h-4" />
              <span class="<lg:hidden"> Audits </span>
            </div>
          </NcTooltip>

          <div v-else v-e="['c:row-expand:audit']" class="flex items-center gap-2">
            <GeneralIcon icon="audit" class="w-4 h-4" />
            <span class="<lg:hidden"> Audits </span>
          </div>
        </template>
        <div
          class="h-full"
          :class="{
            'pb-1': !appInfo.ee,
          }"
        >
          <div v-if="isExpandedFormLoading" class="flex flex-col h-full">
            <GeneralLoader class="!mt-16" size="xlarge" />
          </div>

          <div v-else ref="commentsWrapperEl" class="flex flex-col h-full py-1 nc-scrollbar-thin !overflow-y-auto">
            <template v-if="audits.length === 0">
              <div class="flex flex-col text-center justify-center h-full">
                <div class="text-center text-3xl text-gray-600">
                  <MdiHistory />
                </div>
                <div class="font-bold text-center my-1 text-gray-600">See changes to this record</div>
              </div>
            </template>

            <div v-for="log of audits" :key="log.id" class="nc-audit-item">
              <div class="group gap-3 overflow-hidden flex items-start p-3">
                <GeneralUserIcon size="medium" :email="log.user" :name="log.display_name" />
                <div class="flex-1 flex flex-col gap-1 max-w-[calc(100%_-_24px)]">
                  <div class="flex flex-wrap items-center min-h-7">
                    <NcTooltip class="truncate max-w-42 mr-2" show-on-truncate-only>
                      <template #title>
                        {{ log.display_name?.trim() || log.user || 'Shared source' }}
                      </template>
                      <span
                        class="text-ellipsis overflow-hidden font-bold text-gray-800"
                        :style="{
                          wordBreak: 'keep-all',
                          whiteSpace: 'nowrap',
                          display: 'inline',
                        }"
                      >
                        {{ log.display_name?.trim() || log.user || 'Shared source' }}
                      </span>
                    </NcTooltip>
                    <div v-if="log.id !== editLog?.id" class="text-xs text-gray-400">
                      {{ timeAgo(log.created_at) }}
                    </div>
                  </div>
                  <div v-dompurify-html="log.details" class="text-sm font-medium"></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </a-tab-pane>
    </NcTabs>
  </div>
</template>

<style lang="scss" scoped>
.tab {
  @apply max-w-1/2;
}

.nc-audit-item {
  @apply border-b-1 gap-3 border-gray-200;
}

.nc-audit-item:last-child {
  @apply border-b-0;
}

.tab .tab-title {
  @apply min-w-0 flex justify-center gap-2 font-semibold items-center;
  word-break: 'keep-all';
  white-space: 'nowrap';
  display: 'inline';
}

.text-decoration-line-through {
  text-decoration: line-through;
}

:deep(.red.lighten-4) {
  @apply bg-red-100 rounded-md line-through;
}

:deep(.green.lighten-4) {
  @apply bg-green-100 rounded-md !mr-3 !leading-6;
}

:deep(.ant-tabs) {
  .ant-tabs-nav {
    @apply px-3;
    .ant-tabs-nav-list {
      @apply w-[99%] mx-auto gap-6;

      .ant-tabs-tab {
        @apply flex-1 flex items-center justify-center pt-3 pb-2.5;

        & + .ant-tabs-tab {
          @apply !ml-0;
        }
      }
    }
  }
  .ant-tabs-content-holder {
    .ant-tabs-content {
      @apply h-full;
    }
  }
}

.nc-comment-description {
  pre {
    @apply !mb-0 py-[1px] !text-small !text-gray-700 !leading-18px;
    white-space: break-spaces;
    font-size: unset;
    font-family: unset;
  }
}
.expanded-form-comment-input-wrapper {
  @apply flex-1 bg-white rounded-lg relative;
}
:deep(.expanded-form-comment-input) {
  @apply transition-all duration-150;
  box-shadow: none;
  &:focus {
    @apply min-h-16;
  }
  &::placeholder {
    @apply !text-gray-400;
  }
}
</style>
