<template>
  <div class="module-filter">
    <div
      class="module-filter__filter-selection"
      v-if="$flavor.showModuleFilter"
    >
      <Dropdown
        class="module-filter__dropdown"
        :selected-item="selectedLevel"
        :items="moduleLevels"
        @update:selectedItem="updateLevel"
      />

      <Dropdown
        class="module-filter__dropdown"
        :selected-item="selectedCategory"
        :items="moduleCategories"
        @update:selectedItem="(newItem) => (selectedCategory = newItem)"
      />

      <language-switcher class="module-filter__language-switcher" v-if="$flavor.showLanguageFilter"/>
    </div>
    <info-message
      class="module-filter__no-modules-text"
      v-if="modules.length > 1 && filteredModules.length === 0"
      >Für die ausgewählten Filtereinstellungen sind keine {{ $flavor.textModules }} vorhanden
    </info-message>
    <div class="topic__modules">
      <module-teaser
        v-for="module in filteredModules"
        v-bind="module"
        :key="module.slug"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import ModuleTeaser from '@/components/modules/ModuleTeaser.vue';
import { useQuery, useMutation } from '@vue/apollo-composable';
import Dropdown from '@/components/ui/Dropdown.vue';
import LanguageSwitcher from '@/components/LanguageSwitcher.vue';
import { graphql } from '@/__generated__';
import { ModuleCategoryNode, ModuleLevelNode, ModuleNode, PrivateUserNode } from '@/__generated__/graphql';
import InfoMessage from '@/components/ui/InfoMessage.vue';

const props = defineProps<{
  modules: ModuleNode[];
  me: PrivateUserNode;
}>();

const initialCategory = {
  name: 'Alle Lernfelder',
  id: null,
  filterAttributeType: 'ALL',
};

const initialLevel: ModuleLevelNode = {
  name: 'Alle Lehrjahre',
  id: '',
  filterAttributeType: 'ALL',
};

// const ModuleLevelFragment = graphql(` //todo: use fragment as type
graphql(`
  fragment ModuleLevelFragment on ModuleLevelNode {
    name
    id
    filterAttributeType
  }
`);

const { result: moduleFilterResult } = useQuery(
  graphql(`
    query ModuleFilterQuery {
      moduleLevels {
        ...ModuleLevelFragment
      }
      moduleCategories {
        name
        id
        filterAttributeType
      }
      me {
        language @client
      }
    }
  `)
);

const selectedLevel = ref<ModuleLevelNode>(initialLevel);
const selectedCategory = ref(initialCategory);

selectedLevel.value = loadDefaultLevel(props.me);

const moduleLevels = computed(() => moduleFilterResult.value?.moduleLevels || []);
const moduleCategories = computed(() => moduleFilterResult.value?.moduleCategories || []);
const language = computed(() => moduleFilterResult.value?.me.language || 'de');
const filteredModules = computed(
  () =>
    props.modules?.filter((module) =>
      filterModule(module, selectedLevel.value, selectedCategory.value, language.value)
    ) || []
);

function loadDefaultLevel(me: PrivateUserNode) {
  return me?.lastModuleLevel || initialLevel;
}

function filterModule(
  module: ModuleNode,
  selectedLevel: ModuleLevelNode,
  selectedCategory: ModuleCategoryNode,
  selectedLanguage: string
) {
  let filterExpression = true;

  filterExpression =
    filterByLevel(module, selectedLevel) &&
    filterByCategory(module, selectedCategory) &&
    filterByLanguage(module, selectedLanguage);
  return filterExpression;
}

const updateLevel = (level: ModuleLevelNode) => {
  selectedLevel.value = level;
  updateLastModuleLevelUser(level);
};

const filterByLevel = (module: ModuleNode, level: ModuleLevelNode) => {
  return level.filterAttributeType === 'ALL' || module.level?.id === level.id || !module.level;
};

const filterByCategory = (module: ModuleNode, category: ModuleCategoryNode) => {
  return category.filterAttributeType === 'ALL' || module.category?.id === category.id || !module.category;
};

const filterByLanguage = (module: ModuleNode, language: string) => {
  return module.language === language;
};

const { mutate: updateLastModuleLevel } = useMutation(
  graphql(`
    mutation UpdateLastModuleLevelMutation($input: UpdateLastModuleLevelInput!) {
      updateLastModuleLevel(input: $input) {
        clientMutationId
        user {
          username
          id
          lastModuleLevel {
            ...ModuleLevelFragment
          }
        }
      }
    }
  `)
  // todo: this is not needed anymore, but I learned a lot with it, I need to move this somewhere for me after vacation,
  // please leave this for me to clean up
  // - Ramon, 31.08.2023
  //
  // {
  //   update: (
  //     cache,
  //     {
  //       data: {
  //         updateLastModuleLevel: { user },
  //       },
  //     }
  //   ) => {
  //     console.log(user);
  //     const moduleLevel = cache.readFragment({
  //       id: cache.identify(user.lastModuleLevel),
  //       fragment: ModuleLevelFragment,
  //       // fragmentName: 'ModuleLevelFragment',
  //     });
  //     console.log(moduleLevel);
  //     // const id = cache.identify(user);
  //     // console.log(id);
  //     const meLastModuleLevelFragment = graphql(`
  //       fragment MeLastModuleLevelFragment on PrivateUserNode {
  //         id
  //         firstName
  //         lastModuleLevel {
  //           ...ModuleLevelFragment
  //         }
  //       }
  //     `);
  //     console.log(meLastModuleLevelFragment);
  //     const written = cache.writeFragment({
  //       id: cache.identify(user),
  //       fragment: meLastModuleLevelFragment,
  //       data: { id: user.id, firstName: 'hans', lastModuleLevel: moduleLevel },
  //       fragmentName: 'MeLastModuleLevelFragment',
  //     });
  //     console.log(written);
  //   },
  // }
);

const updateLastModuleLevelUser = (moduleLevel: ModuleLevelNode) => {
  updateLastModuleLevel({
    input: {
      id: moduleLevel.id,
    },
  });
};
</script>

<style scoped lang="scss">
@import 'styles/helpers';

.module-filter {
  &__filter-selection {
    display: flex;
    flex-direction: column;
    @include desktop {
      flex-direction: row;
    }
    justify-content: flex-start;
    column-gap: $medium-spacing;
    margin-bottom: $medium-spacing;
  }

  &__dropdown {
    @include desktop {
      width: 260px;
    }
  }

  &__language-switcher {
    margin-left: auto;
  }
}

.topic {
  &__modules {
    margin-top: 40px;
    display: flex;
    flex-wrap: wrap;
    @supports (display: grid) {
      display: grid;
    }
    grid-column-gap: $large-spacing;
    grid-row-gap: $large-spacing;

    @include desktop {
      grid-template-columns: repeat(3, minmax(auto, 380px));
    }
  }
}
</style>
