<template>
  <div>
    <header
      class="flex flex-1 flex-shrink-0 items-center justify-between space-x-2 overflow-x-auto overflow-y-hidden px-2 py-2"
    >
      <div
        class="inline-flex flex-1 items-center justify-start space-x-2"
        :style="{
          paddingTop: platform.ui?.appHeader?.paddingTop?.value,
          paddingLeft: platform.ui?.appHeader?.paddingLeft?.value,
        }"
      >
        <HoppButtonSecondary
          class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
          :label="t('app.name')"
          to="/"
        />
      </div>
      <div class="inline-flex flex-1 items-center justify-center space-x-2">
        <button
          class="flex max-w-[15rem] flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 py-1 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
          @click="invokeAction('modals.search.toggle')"
        >
          <span class="inline-flex flex-1 items-center">
            <icon-lucide-search class="svg-icons mr-2" />
            {{ t("app.search") }}
          </span>
          <span class="flex space-x-1">
            <kbd class="shortcut-key">{{ getPlatformSpecialKey() }}</kbd>
            <kbd class="shortcut-key">K</kbd>
          </span>
        </button>
        <HoppButtonSecondary
          v-if="showInstallButton"
          v-tippy="{ theme: 'tooltip' }"
          :title="t('header.install_pwa')"
          :icon="IconDownload"
          class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
          @click="installPWA()"
        />
        <HoppButtonSecondary
          v-tippy="{ theme: 'tooltip', allowHTML: true }"
          :title="`${
            mdAndLarger ? t('support.title') : t('app.options')
          } <kbd>?</kbd>`"
          :icon="IconLifeBuoy"
          class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
          @click="invokeAction('modals.support.toggle')"
        />
      </div>
      <div class="inline-flex flex-1 items-center justify-end space-x-2">
        <div
          v-if="currentUser === null"
          class="inline-flex items-center space-x-2"
        >
          <HoppButtonSecondary
            :icon="IconUploadCloud"
            :label="t('header.save_workspace')"
            class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 hidden border border-green-600/25 bg-green-500/[.15] !text-green-500 hover:border-green-800/50 hover:bg-green-400/10 focus-visible:border-green-800/50 focus-visible:bg-green-400/10 md:flex"
            @click="invokeAction('modals.login.toggle')"
          />
          <HoppButtonPrimary
            :label="t('header.login')"
            @click="invokeAction('modals.login.toggle')"
          />
        </div>
        <div v-else class="inline-flex items-center space-x-2">
          <TeamsMemberStack
            v-if="
              workspace.type === 'team' &&
              selectedTeam &&
              selectedTeam.teamMembers.length > 1
            "
            :team-members="selectedTeam.teamMembers"
            show-count
            class="mx-2"
            @handle-click="handleTeamEdit()"
          />
          <div
            class="flex divide-x divide-green-600/25 rounded border border-green-600/25 bg-green-500/[.15] focus-within:divide-green-800/50 focus-within:border-green-800/50 focus-within:bg-green-400/10 hover:divide-green-800/50 hover:border-green-800/50 hover:bg-green-400/10"
          >
            <HoppButtonSecondary
              v-tippy="{ theme: 'tooltip' }"
              :title="t('team.invite_tooltip')"
              :icon="IconUserPlus"
              class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
              @click="handleInvite()"
            />
            <HoppButtonSecondary
              v-if="
                workspace.type === 'team' &&
                selectedTeam &&
                selectedTeam?.myRole === 'OWNER'
              "
              v-tippy="{ theme: 'tooltip' }"
              :title="t('team.edit')"
              :icon="IconSettings"
              class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
              @click="handleTeamEdit()"
            />
          </div>
          <tippy
            interactive
            trigger="click"
            theme="popover"
            :on-shown="() => accountActions.focus()"
          >
            <HoppButtonSecondary
              v-tippy="{ theme: 'tooltip' }"
              :title="t('workspace.change')"
              :label="mdAndLarger ? workspaceName : ``"
              :icon="workspace.type === 'personal' ? IconUser : IconUsers"
              class="select-wrapper !focus-visible:text-blue-600 !hover:text-blue-600 rounded border border-blue-600/25 bg-blue-500/[.15] py-[0.4375rem] pr-8 !text-blue-500 hover:border-blue-800/50 hover:bg-blue-400/10 focus-visible:border-blue-800/50 focus-visible:bg-blue-400/10"
            />
            <template #content="{ hide }">
              <div
                ref="accountActions"
                class="flex flex-col focus:outline-none"
                tabindex="0"
                @keyup.escape="hide()"
                @click="hide()"
              >
                <WorkspaceSelector />
              </div>
            </template>
          </tippy>
          <span class="px-2">
            <tippy
              interactive
              trigger="click"
              theme="popover"
              :on-shown="() => tippyActions.focus()"
            >
              <HoppSmartPicture
                v-if="currentUser.photoURL"
                v-tippy="{
                  theme: 'tooltip',
                }"
                :url="currentUser.photoURL"
                :alt="
                  currentUser.displayName ||
                  t('profile.default_hopp_displayname')
                "
                :title="
                  currentUser.displayName ||
                  currentUser.email ||
                  t('profile.default_hopp_displayname')
                "
                indicator
                :indicator-styles="
                  network.isOnline ? 'bg-green-500' : 'bg-red-500'
                "
              />
              <HoppSmartPicture
                v-else
                v-tippy="{ theme: 'tooltip' }"
                :title="
                  currentUser.displayName ||
                  currentUser.email ||
                  t('profile.default_hopp_displayname')
                "
                :initial="currentUser.displayName || currentUser.email"
                indicator
                :indicator-styles="
                  network.isOnline ? 'bg-green-500' : 'bg-red-500'
                "
              />
              <template #content="{ hide }">
                <div
                  ref="tippyActions"
                  class="flex flex-col focus:outline-none"
                  tabindex="0"
                  @keyup.p="profile.$el.click()"
                  @keyup.s="settings.$el.click()"
                  @keyup.l="logout.$el.click()"
                  @keyup.escape="hide()"
                >
                  <div class="flex flex-col px-2 text-tiny">
                    <span class="inline-flex truncate font-semibold">
                      {{
                        currentUser.displayName ||
                        t("profile.default_hopp_displayname")
                      }}
                    </span>
                    <span class="inline-flex truncate text-secondaryLight">
                      {{ currentUser.email }}
                    </span>
                  </div>
                  <hr />
                  <HoppSmartItem
                    ref="profile"
                    to="/profile"
                    :icon="IconUser"
                    :label="t('navigation.profile')"
                    :shortcut="['P']"
                    @click="hide()"
                  />
                  <HoppSmartItem
                    ref="settings"
                    to="/settings"
                    :icon="IconSettings"
                    :label="t('navigation.settings')"
                    :shortcut="['S']"
                    @click="hide()"
                  />
                  <FirebaseLogout
                    ref="logout"
                    :shortcut="['L']"
                    @confirm-logout="hide()"
                  />
                </div>
              </template>
            </tippy>
          </span>
        </div>
      </div>
    </header>
    <AppBanner v-if="banner" :banner="banner" />
    <TeamsModal :show="showTeamsModal" @hide-modal="showTeamsModal = false" />
    <TeamsInvite
      v-if="workspace.type === 'team' && workspace.teamID"
      :show="showModalInvite"
      :editing-team-i-d="editingTeamID"
      @hide-modal="displayModalInvite(false)"
    />
    <TeamsEdit
      :show="showModalEdit"
      :editing-team="editingTeamName"
      :editing-team-i-d="editingTeamID"
      @hide-modal="displayModalEdit(false)"
      @invite-team="inviteTeam(editingTeamName, editingTeamID)"
      @refetch-teams="refetchTeams"
    />

    <HoppSmartConfirmModal
      :show="confirmRemove"
      :title="t('confirm.remove_team')"
      @hide-modal="confirmRemove = false"
      @resolve="deleteTeam"
    />
  </div>
</template>

<script setup lang="ts">
import { useI18n } from "@composables/i18n"
import { useReadonlyStream } from "@composables/stream"
import { defineActionHandler, invokeAction } from "@helpers/actions"
import { WorkspaceService } from "~/services/workspace.service"
import { useService } from "dioc/vue"
import { installPWA, pwaDefferedPrompt } from "@modules/pwa"
import { breakpointsTailwind, useBreakpoints, useNetwork } from "@vueuse/core"
import { computed, reactive, ref, watch } from "vue"
import { useToast } from "~/composables/toast"
import { GetMyTeamsQuery, TeamMemberRole } from "~/helpers/backend/graphql"
import { getPlatformSpecialKey } from "~/helpers/platformutils"
import { platform } from "~/platform"
import IconDownload from "~icons/lucide/download"
import IconLifeBuoy from "~icons/lucide/life-buoy"
import IconSettings from "~icons/lucide/settings"
import IconUploadCloud from "~icons/lucide/upload-cloud"
import IconUser from "~icons/lucide/user"
import IconUserPlus from "~icons/lucide/user-plus"
import IconUsers from "~icons/lucide/users"
import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither"
import { deleteTeam as backendDeleteTeam } from "~/helpers/backend/mutations/Team"
import { BannerService } from "~/services/banner.service"

const t = useI18n()
const toast = useToast()

/**
 * Once the PWA code is initialized, this holds a method
 * that can be called to show the user the installation
 * prompt.
 */

const showInstallButton = computed(() => !!pwaDefferedPrompt.value)

const showTeamsModal = ref(false)

const breakpoints = useBreakpoints(breakpointsTailwind)
const mdAndLarger = breakpoints.greater("md")

const { content: banner } = useService(BannerService)
const network = reactive(useNetwork())

watch(network, () => {
  if (network.isOnline) {
    banner.value = null
    return
  }
  banner.value = {
    type: "info",
    text: t("helpers.offline"),
    alternateText: t("helpers.offline_short"),
  }
})

const currentUser = useReadonlyStream(
  platform.auth.getProbableUserStream(),
  platform.auth.getProbableUser()
)

const confirmRemove = ref(false)
const teamID = ref<string | null>(null)

const selectedTeam = ref<GetMyTeamsQuery["myTeams"][number] | undefined>()

// TeamList-Adapter
const workspaceService = useService(WorkspaceService)
const teamListAdapter = workspaceService.acquireTeamListAdapter(null)
const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)

const workspace = workspaceService.currentWorkspace

const workspaceName = computed(() =>
  workspace.value.type === "personal"
    ? t("workspace.personal")
    : workspace.value.teamName
)

const refetchTeams = () => {
  teamListAdapter.fetchList()
}

watch(
  () => myTeams.value,
  (newTeams) => {
    const space = workspace.value

    if (newTeams && space.type === "team" && space.teamID) {
      const team = newTeams.find((team) => team.id === space.teamID)
      if (team) {
        selectedTeam.value = team
        // Update the workspace name if it's not the same as the updated team name
        if (team.name !== space.teamName) {
          workspaceService.updateWorkspaceTeamName(team.name)
        }
      }
    }
  }
)

watch(
  () => workspace.value,
  (newWorkspace) => {
    if (newWorkspace.type === "team") {
      const team = myTeams.value?.find((t) => t.id === newWorkspace.teamID)
      if (team) {
        selectedTeam.value = team
      }
    }
  }
)

const showModalInvite = ref(false)
const showModalEdit = ref(false)

const editingTeamName = ref<{ name: string }>({ name: "" })
const editingTeamID = ref("")

const displayModalInvite = (show: boolean) => {
  showModalInvite.value = show
}

const displayModalEdit = (show: boolean) => {
  showModalEdit.value = show
  teamListAdapter.fetchList()
}

const inviteTeam = (team: { name: string }, teamID: string) => {
  editingTeamName.value = team
  editingTeamID.value = teamID
  displayModalInvite(true)
}

// Show the workspace selected team invite modal if the user is an owner of the team else show the default invite modal
const handleInvite = () => {
  if (
    workspace.value.type === "team" &&
    workspace.value.teamID &&
    selectedTeam.value?.myRole === "OWNER"
  ) {
    editingTeamID.value = workspace.value.teamID
    displayModalInvite(true)
  } else {
    showTeamsModal.value = true
  }
}

// Show the workspace selected team edit modal if the user is an owner of the team
const handleTeamEdit = () => {
  if (
    workspace.value.type === "team" &&
    workspace.value.teamID &&
    selectedTeam.value?.myRole === "OWNER"
  ) {
    editingTeamID.value = workspace.value.teamID
    editingTeamName.value = { name: selectedTeam.value.name }
    displayModalEdit(true)
  } else {
    noPermission()
  }
}

const deleteTeam = () => {
  if (!teamID.value) return
  pipe(
    backendDeleteTeam(teamID.value),
    TE.match(
      (err) => {
        // TODO: Better errors ? We know the possible errors now
        toast.error(`${t("error.something_went_wrong")}`)
        console.error(err)
      },
      () => {
        invokeAction("workspace.switch.personal")
        toast.success(`${t("team.deleted")}`)
      }
    )
  )() // Tasks (and TEs) are lazy, so call the function returned
}

// Template refs
const tippyActions = ref<any | null>(null)
const profile = ref<any | null>(null)
const settings = ref<any | null>(null)
const logout = ref<any | null>(null)
const accountActions = ref<any | null>(null)

defineActionHandler("modals.team.edit", handleTeamEdit)

defineActionHandler("modals.team.invite", () => {
  if (
    selectedTeam.value?.myRole === "OWNER" ||
    selectedTeam.value?.myRole === "EDITOR"
  ) {
    inviteTeam({ name: selectedTeam.value.name }, selectedTeam.value.id)
  } else {
    noPermission()
  }
})

defineActionHandler(
  "user.login",
  () => {
    invokeAction("modals.login.toggle")
  },
  computed(() => !currentUser.value)
)

defineActionHandler("modals.team.delete", ({ teamId }) => {
  if (selectedTeam.value?.myRole !== TeamMemberRole.Owner) return noPermission()
  teamID.value = teamId
  confirmRemove.value = true
})

const noPermission = () => {
  toast.error(`${t("profile.no_permission")}`)
}
</script>
