<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { useMapGetter, useStore } from 'dashboard/composables/store.js';
import { useRouter, useRoute } from 'vue-router';
import { useTrack } from 'dashboard/composables';
import { useI18n } from 'vue-i18n';
import { useCamelCase } from 'dashboard/composables/useTransformKeys';
import { generateURLParams, parseURLParams } from '../helpers/searchHelper';
import {
  ROLES,
  CONVERSATION_PERMISSIONS,
  CONTACT_PERMISSIONS,
  PORTAL_PERMISSIONS,
} from 'dashboard/constants/permissions.js';
import { usePolicy } from 'dashboard/composables/usePolicy';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';

import Policy from 'dashboard/components/policy.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
import SearchHeader from './SearchHeader.vue';
import SearchTabs from './SearchTabs.vue';
import SearchResultConversationsList from './SearchResultConversationsList.vue';
import SearchResultMessagesList from './SearchResultMessagesList.vue';
import SearchResultContactsList from './SearchResultContactsList.vue';
import SearchResultArticlesList from './SearchResultArticlesList.vue';

const router = useRouter();
const route = useRoute();
const store = useStore();
const { t } = useI18n();

const PER_PAGE = 15; // Results per page
const selectedTab = ref(route.params.tab || 'all');
const query = ref(route.query.q || '');
const pages = ref({
  contacts: 1,
  conversations: 1,
  messages: 1,
  articles: 1,
});

const contactRecords = useMapGetter('conversationSearch/getContactRecords');
const conversationRecords = useMapGetter(
  'conversationSearch/getConversationRecords'
);
const messageRecords = useMapGetter('conversationSearch/getMessageRecords');
const articleRecords = useMapGetter('conversationSearch/getArticleRecords');
const uiFlags = useMapGetter('conversationSearch/getUIFlags');

const addTypeToRecords = (records, type) =>
  records.value.map(item => ({ ...useCamelCase(item, { deep: true }), type }));

const mappedContacts = computed(() =>
  addTypeToRecords(contactRecords, 'contact')
);
const mappedConversations = computed(() =>
  addTypeToRecords(conversationRecords, 'conversation')
);
const mappedMessages = computed(() =>
  addTypeToRecords(messageRecords, 'message')
);
const mappedArticles = computed(() =>
  addTypeToRecords(articleRecords, 'article')
);

const isSelectedTabAll = computed(() => selectedTab.value === 'all');

const searchResultSectionClass = computed(() => ({
  'mt-4': isSelectedTabAll.value,
  'mt-0.5': !isSelectedTabAll.value,
}));

const sliceRecordsIfAllTab = items =>
  isSelectedTabAll.value ? items.value.slice(0, 5) : items.value;

const contacts = computed(() => sliceRecordsIfAllTab(mappedContacts));
const conversations = computed(() => sliceRecordsIfAllTab(mappedConversations));
const messages = computed(() => sliceRecordsIfAllTab(mappedMessages));
const articles = computed(() => sliceRecordsIfAllTab(mappedArticles));

const filterByTab = tab =>
  computed(() => selectedTab.value === tab || isSelectedTabAll.value);

const filterContacts = filterByTab('contacts');
const filterConversations = filterByTab('conversations');
const filterMessages = filterByTab('messages');
const filterArticles = filterByTab('articles');

const { shouldShow, isFeatureFlagEnabled } = usePolicy();

const TABS_CONFIG = {
  all: {
    permissions: [
      CONTACT_PERMISSIONS,
      ...ROLES,
      ...CONVERSATION_PERMISSIONS,
      PORTAL_PERMISSIONS,
    ],
    count: () => null, // No count for all tab
  },
  contacts: {
    permissions: [...ROLES, CONTACT_PERMISSIONS],
    count: () => mappedContacts.value.length,
  },
  conversations: {
    permissions: [...ROLES, ...CONVERSATION_PERMISSIONS],
    count: () => mappedConversations.value.length,
  },
  messages: {
    permissions: [...ROLES, ...CONVERSATION_PERMISSIONS],
    count: () => mappedMessages.value.length,
  },
  articles: {
    permissions: [...ROLES, PORTAL_PERMISSIONS],
    featureFlag: FEATURE_FLAGS.HELP_CENTER,
    count: () => mappedArticles.value.length,
  },
};

const tabs = computed(() => {
  return Object.entries(TABS_CONFIG)
    .map(([key, config]) => ({
      key,
      name: t(`SEARCH.TABS.${key.toUpperCase()}`),
      count: config.count(),
      showBadge: key !== 'all',
      permissions: config.permissions,
      featureFlag: config.featureFlag,
    }))
    .filter(config => {
      // why the double check, glad you asked.
      // Some features are marked as premium features, that means
      // the feature will be visible, but a Paywall will be shown instead
      // this works for pages and routes, but fails for UI elements like search here
      // so we explicitly check if the feature is enabled
      return (
        shouldShow(config.featureFlag, config.permissions, null) &&
        isFeatureFlagEnabled(config.featureFlag)
      );
    });
});

const totalSearchResultsCount = computed(() => {
  const permissionCounts = [
    {
      permissions: [...ROLES, CONTACT_PERMISSIONS],
      count: () => contacts.value.length,
    },
    {
      permissions: [...ROLES, ...CONVERSATION_PERMISSIONS],
      count: () => conversations.value.length + messages.value.length,
    },
    {
      permissions: [...ROLES, PORTAL_PERMISSIONS],
      featureFlag: FEATURE_FLAGS.HELP_CENTER,
      count: () => articles.value.length,
    },
  ];

  return permissionCounts
    .filter(config => {
      // why the double check, glad you asked.
      // Some features are marked as premium features, that means
      // the feature will be visible, but a Paywall will be shown instead
      // this works for pages and routes, but fails for UI elements like search here
      // so we explicitly check if the feature is enabled
      return (
        shouldShow(config.featureFlag, config.permissions, null) &&
        isFeatureFlagEnabled(config.featureFlag)
      );
    })
    .map(config => {
      return config.count();
    })
    .reduce((sum, count) => sum + count, 0);
});

const activeTabIndex = computed(() => {
  const index = tabs.value.findIndex(tab => tab.key === selectedTab.value);
  return index >= 0 ? index : 0;
});

const isFetchingAny = computed(() => {
  const { contact, message, conversation, article, isFetching } = uiFlags.value;
  return (
    isFetching ||
    contact.isFetching ||
    message.isFetching ||
    conversation.isFetching ||
    article.isFetching
  );
});

const showEmptySearchResults = computed(
  () =>
    totalSearchResultsCount.value === 0 &&
    uiFlags.value.isSearchCompleted &&
    isSelectedTabAll.value &&
    !isFetchingAny.value &&
    query.value
);

const showResultsSection = computed(
  () =>
    (uiFlags.value.isSearchCompleted && totalSearchResultsCount.value !== 0) ||
    isFetchingAny.value ||
    (!isSelectedTabAll.value && query.value && !isFetchingAny.value)
);

const showLoadMore = computed(() => {
  if (!query.value || isFetchingAny.value || selectedTab.value === 'all')
    return false;

  const records = {
    contacts: mappedContacts.value,
    conversations: mappedConversations.value,
    messages: mappedMessages.value,
    articles: mappedArticles.value,
  }[selectedTab.value];

  return (
    records?.length > 0 &&
    records.length === pages.value[selectedTab.value] * PER_PAGE
  );
});

const showViewMore = computed(() => ({
  // Hide view more button if the number of records is less than 5
  contacts: mappedContacts.value?.length > 5 && isSelectedTabAll.value,
  conversations:
    mappedConversations.value?.length > 5 && isSelectedTabAll.value,
  messages: mappedMessages.value?.length > 5 && isSelectedTabAll.value,
  articles: mappedArticles.value?.length > 5 && isSelectedTabAll.value,
}));

const filters = ref({
  from: null,
  in: null,
  dateRange: { type: null, from: null, to: null },
});

const clearSearchResult = () => {
  pages.value = { contacts: 1, conversations: 1, messages: 1, articles: 1 };
  store.dispatch('conversationSearch/clearSearchResults');
};

const buildSearchPayload = (basePayload = {}, searchType = 'message') => {
  const payload = { ...basePayload };

  // Only include filters if advanced search is enabled
  if (isFeatureFlagEnabled(FEATURE_FLAGS.ADVANCED_SEARCH)) {
    // Date filters apply to all search types
    if (filters.value.dateRange.from) {
      payload.since = filters.value.dateRange.from;
    }
    if (filters.value.dateRange.to) {
      payload.until = filters.value.dateRange.to;
    }

    // Only messages support 'from' and 'inboxId' filters
    if (searchType === 'message') {
      if (filters.value.from) payload.from = filters.value.from;
      if (filters.value.in) payload.inboxId = filters.value.in;
    }
  }

  return payload;
};

const updateURL = () => {
  const params = {
    accountId: route.params.accountId,
    ...(selectedTab.value !== 'all' && { tab: selectedTab.value }),
  };

  const queryParams = {
    ...(query.value?.trim() && { q: query.value.trim() }),
    ...generateURLParams(
      filters.value,
      isFeatureFlagEnabled(FEATURE_FLAGS.ADVANCED_SEARCH)
    ),
  };

  router.replace({ name: 'search', params, query: queryParams });
};

const onSearch = q => {
  query.value = q;
  clearSearchResult();
  updateURL();
  if (!q) return;
  useTrack(CONVERSATION_EVENTS.SEARCH_CONVERSATION);

  const searchPayload = buildSearchPayload({ q, page: 1 });
  store.dispatch('conversationSearch/fullSearch', searchPayload);
};

const onFilterChange = () => {
  onSearch(query.value);
};

const onBack = () => {
  if (window.history.length > 2) {
    router.go(-1);
  } else {
    router.push({ name: 'home' });
  }
  clearSearchResult();
};

const loadMore = () => {
  const SEARCH_ACTIONS = {
    contacts: 'conversationSearch/contactSearch',
    conversations: 'conversationSearch/conversationSearch',
    messages: 'conversationSearch/messageSearch',
    articles: 'conversationSearch/articleSearch',
  };

  if (uiFlags.value.isFetching || selectedTab.value === 'all') return;

  const tab = selectedTab.value;
  pages.value[tab] += 1;

  const payload = buildSearchPayload(
    { q: query.value, page: pages.value[tab] },
    tab
  );

  store.dispatch(SEARCH_ACTIONS[tab], payload);
};

const onTabChange = tab => {
  selectedTab.value = tab;
  updateURL();
};

onMounted(() => {
  store.dispatch('conversationSearch/clearSearchResults');
  store.dispatch('agents/get');

  const parsedFilters = parseURLParams(
    route.query,
    isFeatureFlagEnabled(FEATURE_FLAGS.ADVANCED_SEARCH)
  );
  filters.value = parsedFilters;

  // Auto-execute search if query parameter exists
  if (route.query.q) {
    onSearch(route.query.q);
  }
});

onUnmounted(() => {
  query.value = '';
  store.dispatch('conversationSearch/clearSearchResults');
});
</script>

<template>
  <div class="flex flex-col w-full h-full bg-n-surface-1">
    <div class="flex w-full p-4">
      <NextButton
        :label="t('GENERAL_SETTINGS.BACK')"
        icon="i-lucide-chevron-left"
        faded
        primary
        sm
        @click="onBack"
      />
    </div>
    <section class="flex flex-col flex-grow w-full h-full overflow-hidden">
      <div class="w-full max-w-5xl mx-auto z-30">
        <div class="flex flex-col w-full px-4">
          <SearchHeader
            v-model:filters="filters"
            :initial-query="query"
            @search="onSearch"
            @filter-change="onFilterChange"
          />
          <SearchTabs
            v-if="query"
            :tabs="tabs"
            :selected-tab="activeTabIndex"
            @tab-change="onTabChange"
          />
        </div>
      </div>
      <div class="flex-grow w-full h-full overflow-y-auto">
        <div class="w-full max-w-5xl mx-auto px-4 pb-6">
          <div v-if="showResultsSection">
            <Policy
              :permissions="[...ROLES, CONTACT_PERMISSIONS]"
              class="flex flex-col justify-center"
            >
              <SearchResultContactsList
                v-if="filterContacts"
                :is-fetching="uiFlags.contact.isFetching"
                :contacts="contacts"
                :query="query"
                :show-title="isSelectedTabAll"
                class="mt-0.5"
              />
              <NextButton
                v-if="showViewMore.contacts"
                :label="t(`SEARCH.VIEW_MORE`)"
                icon="i-lucide-eye"
                slate
                sm
                outline
                @click="selectedTab = 'contacts'"
              />
            </Policy>

            <Policy
              :permissions="[...ROLES, ...CONVERSATION_PERMISSIONS]"
              class="flex flex-col justify-center"
            >
              <SearchResultMessagesList
                v-if="filterMessages"
                :is-fetching="uiFlags.message.isFetching"
                :messages="messages"
                :query="query"
                :show-title="isSelectedTabAll"
                :class="searchResultSectionClass"
              />
              <NextButton
                v-if="showViewMore.messages"
                :label="t(`SEARCH.VIEW_MORE`)"
                icon="i-lucide-eye"
                slate
                sm
                outline
                @click="selectedTab = 'messages'"
              />
            </Policy>

            <Policy
              :permissions="[...ROLES, ...CONVERSATION_PERMISSIONS]"
              class="flex flex-col justify-center"
            >
              <SearchResultConversationsList
                v-if="filterConversations"
                :is-fetching="uiFlags.conversation.isFetching"
                :conversations="conversations"
                :query="query"
                :show-title="isSelectedTabAll"
                :class="searchResultSectionClass"
              />
              <NextButton
                v-if="showViewMore.conversations"
                :label="t(`SEARCH.VIEW_MORE`)"
                icon="i-lucide-eye"
                slate
                sm
                outline
                @click="selectedTab = 'conversations'"
              />
            </Policy>

            <Policy
              v-if="isFeatureFlagEnabled(FEATURE_FLAGS.HELP_CENTER)"
              :permissions="[...ROLES, PORTAL_PERMISSIONS]"
              :feature-flag="FEATURE_FLAGS.HELP_CENTER"
              class="flex flex-col justify-center"
            >
              <SearchResultArticlesList
                v-if="filterArticles"
                :is-fetching="uiFlags.article.isFetching"
                :articles="articles"
                :query="query"
                :show-title="isSelectedTabAll"
                :class="searchResultSectionClass"
              />
              <NextButton
                v-if="showViewMore.articles"
                :label="t(`SEARCH.VIEW_MORE`)"
                icon="i-lucide-eye"
                slate
                sm
                outline
                @click="selectedTab = 'articles'"
              />
            </Policy>

            <div v-if="showLoadMore" class="flex justify-center mt-3 mb-6">
              <NextButton
                v-if="!isSelectedTabAll"
                :label="t(`SEARCH.LOAD_MORE`)"
                icon="i-lucide-cloud-download"
                slate
                sm
                faded
                @click="loadMore"
              />
            </div>
          </div>
          <div
            v-else-if="showEmptySearchResults"
            class="flex flex-col items-center justify-center px-4 py-6 mt-8 rounded-md"
          >
            <fluent-icon icon="info" size="16px" class="text-n-slate-11" />
            <p class="m-2 text-center text-n-slate-11">
              {{ t('SEARCH.EMPTY_STATE_FULL', { query }) }}
            </p>
          </div>
          <div
            v-else-if="!query"
            class="flex flex-col items-center justify-center px-4 py-6 mt-8 text-center rounded-md"
          >
            <p class="text-center margin-bottom-0">
              <fluent-icon icon="search" size="24px" class="text-n-slate-11" />
            </p>
            <p class="m-2 text-center text-n-slate-11">
              {{ t('SEARCH.EMPTY_STATE_DEFAULT') }}
            </p>
          </div>
        </div>
      </div>
    </section>
  </div>
</template>
