<style scoped>
.logs-container {
  padding: 1rem;
  min-width: 100%;
  max-height: 73vh;
  overflow-y: auto;
  overflow-x: auto;
}

hr {
  background-color: unset;
  border-bottom: 1px solid var(--bulma-grey-light) !important
}
</style>

<template>
  <main>
    <div class="mt-1 columns is-multiline">
      <div class="column is-12 is-clearfix is-unselectable">
        <span class="title is-4">
          <span class="icon"><i class="fas fa-cogs" /></span>
          CHANGELOG
        </span>

        <div class="is-pulled-right">
          <div class="field is-grouped">
            <p class="control has-icons-left" v-if="toggleFilter && logs && logs.length > 0">
              <input type="search" v-model.lazy="query" class="input" id="filter"
                placeholder="Filter changelog entries">
              <span class="icon is-left"><i class="fas fa-filter" /></span>
            </p>

            <p class="control" v-if="logs && logs.length > 0">
              <button class="button is-danger is-light" @click="toggleFilter = !toggleFilter">
                <span class="icon"><i class="fas fa-filter" /></span>
                <span v-if="!isMobile">Filter</span>
              </button>
            </p>
          </div>
        </div>

        <div class="is-hidden-mobile">
          <span class="subtitle">This page display the latest changes and updates from the project.</span>
        </div>
      </div>
    </div>

    <div class="columns is-multiline" v-if="isLoading">
      <div class="column is-12">
        <Message message_class="has-background-info-90 has-text-dark" title="Loading" icon="fas fa-spinner fa-spin"
          message="Loading data. Please wait..." />
      </div>
    </div>

    <template v-if="!isLoading">
      <div class="logs-container" v-if="filteredLogs && filteredLogs.length > 0">
        <div class="columns is-multiline">
          <div class="column p-0 m-0 is-12" v-for="(log, index) in filteredLogs" :key="log.tag">
            <div class="content p-0 m-0">
              <h1 class="is-4">
                <span class="icon"><i class="fas fa-code-branch" /></span>
                {{ log.tag }} <span class="tag has-text-success" v-if="isInstalled(log)">Installed</span>
                <template v-if="log.date">
                  <span style="font-size:0.5em;">
                    - <span class="has-tooltip" v-tooltip="`Release Date: ${log.date}`">
                      {{ moment(log.date).fromNow() }}
                    </span></span>
                </template>
              </h1>
              <hr>
              <ul>
                <li v-for="commit in log.commits" :key="commit.sha">
                  <strong>
                    {{ ucFirst(commit.message).replace(/\.$/, "") }}.
                  </strong> -
                  <small>
                    <NuxtLink :to="`${REPO}/commit/${commit.full_sha}`" target="_blank">
                      <span class="has-tooltip" v-tooltip="`SHA: ${commit.full_sha} - Date: ${commit.date}`">
                        {{ moment(commit.date).fromNow() }}
                      </span>
                    </NuxtLink>
                    <span v-tooltip="'Code is at this commit.'" v-if="commit.full_sha === app_sha"
                      class="icon has-text-success"><i class="fas fa-check" /></span>
                  </small>
                </li>
              </ul>
              <hr v-if="index < logs.length - 1">
            </div>
          </div>
        </div>
      </div>

      <div class="columns is-multiline" v-if="!filteredLogs || filteredLogs.length < 1">
        <div class="column is-12">
          <Message title="No Results" class="is-background-warning-80 has-text-dark" icon="fas fa-search"
            v-if="query" :useClose="true" @close="query = ''">
            <p>No changelog entries found for the query: <strong>{{ query }}</strong>.</p>
            <p>Please try a different search term.</p>
          </Message>
        </div>
      </div>
    </template>
  </main>
</template>

<script setup lang="ts">
import moment from 'moment'
import type { changelogs, changeset } from '~/types/changelogs'

const toast = useNotification()
const config = useConfigStore()
const isMobile = useMediaQuery({ maxWidth: 1024 })

useHead({ title: 'CHANGELOG' })

const PROJECT = 'ytptube'
const REPO = `https://github.com/arabcoders/${PROJECT}`
const REPO_URL = `https://arabcoders.github.io/${PROJECT}/CHANGELOG.json?version={version}`

const logs = ref<changelogs>([])
const app_version = ref('')
const app_branch = ref('')
const app_sha = ref('')
const isLoading = ref(true)
const query = ref<string>('')
const toggleFilter = ref<boolean>(false)

watch(toggleFilter, () => {
  if (!toggleFilter.value) {
    query.value = ''
  }
})

const filteredLogs = computed<changelogs>(() => {
  const q = query.value?.toLowerCase()
  if (!q) return logs.value

  return logs.value
    .map(log => {
      // Check if tag matches
      const tagMatches = log.tag.toLowerCase().includes(q)

      // Filter commits that match the query
      const filteredCommits = log.commits?.filter(commit =>
        commit.message.toLowerCase().includes(q) ||
        commit.author.toLowerCase().includes(q) ||
        commit.full_sha.toLowerCase().includes(q)
      ) ?? []

      // Return log only if tag matches OR if there are matching commits
      if (tagMatches || filteredCommits.length > 0) {
        return {
          ...log,
          commits: tagMatches ? log.commits : filteredCommits
        }
      }

      return null
    })
    .filter((log): log is changeset => log !== null)
})

const loadContent = async () => {
  if ('' === app_version.value || logs.value.length > 0) {
    return
  }

  try {
    try {
      const changes = await fetch(REPO_URL.replace('{branch}', app_branch.value).replace('{version}', app_version.value))
      logs.value = await changes.json()
    } catch (e) {
      console.error(e)
      logs.value = await (await request(uri('/CHANGELOG.json'), { method: 'GET' })).json()
    }

    await nextTick()
    logs.value = logs.value.slice(0, 10)
  } catch (e: any) {
    console.error(e)
    toast.error(`Failed to fetch changelog. ${e.message}`)
  } finally {
    isLoading.value = false
  }
}

const isInstalled = (log: changeset) => {
  const installed = String(app_sha.value)

  if (log.full_sha.startsWith(installed)) {
    return true
  }

  for (const commit of log?.commits ?? []) {
    if (commit.full_sha.startsWith(installed)) {
      return true
    }
  }

  return false
}

onMounted(async () => {
  await awaiter(config.isLoaded)
  app_branch.value = config.app.app_branch
  app_version.value = config.app.app_version
  app_sha.value = config.app.app_commit_sha
  loadContent()
})
</script>
