<template>
    <div class="flex justify-center pt-2">
        <div class="flex w-[1216px] flex-col items-center">
            <div class="flex w-full justify-between py-2 items-center">
                <button id="create_new_acct_btn" class="flex rounded-full bg-primary text-[#ffffff] flex justify-center
                    items-center px-6 py-[10px]" @click="onCreateNewClick">
                    {{ i18next.t("AcctMgmt.CreateNew") }}
                </button>
                <SearchBar @on-search-account-button-click="onSearchAccountButtonClick"/>
            </div>
            <div id="acct_mgmt_data_grid" class="flex w-full overflow-y-auto h-[570px]" @scroll="handleScroll">
                <DataTable :value="accountSearchResults" dataKey="username" tableClass="w-full mt-4 text-sm relative table-fixed"
                    :rowClass="getRowClass"
                >
                    <Column field="username" :header="i18next.t('AcctMgmt.Account')" bodyClass="font-medium"  sortable>
                        <template #body="slotProps">
                            <div class="row-container flex-w-full-hoverable w-full flex" @mouseenter="handleRowMouseOver(slotProps.data.username)"
                                @mouseout="handleRowMouseOut(slotProps.data.username)">
                                <div @dblclick="onAcctDoubleClick(slotProps.data.username)" class="account-cell cursor-pointer flex">
                                    {{ slotProps.data.username }}
                                </div>
                                <span id="just_create_badge" class="flex ml-4"
                                    v-if="isOneAccountJustCreate && slotProps.data.username === justCreateUsername">
                                    <img src="@/assets/icon-new.svg" alt="New">
                                </span>
                            </div>
                        </template>
                    </Column>
                    <Column field="name" :header="i18next.t('AcctMgmt.FullName')" bodyClass="text-neutral-500" sortable>
                        <template #body="slotProps">
                            <div class="row-container flex-w-full-hoverable w-full" @mouseenter="handleRowMouseOver(slotProps.data.username)"
                                @mouseout="handleRowMouseOut(slotProps.data.username)">
                                <div class="fullname-cell">
                                    {{ slotProps.data.name }}
                                </div>
                            </div>
                        </template>
                    </Column>
                    <Column field="is_admin" :header="i18next.t('AcctMgmt.AdminRights')" bodyClass="text-neutral-500 flex justify-center"
                        headerClass="header-center">
                        <template #body="slotProps">
                            <div class="row-container flex-w-full-hoverable flex w-full justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)"
                                @mouseout="handleRowMouseOut(slotProps.data.username)">
                                <img v-if="slotProps.data.is_admin" src="@/assets/radioOn.svg" alt="Radio On" class="btn-admin cursor-pointer flex justify-center"
                                    @click="onAdminInputClick(slotProps.data, false)"
                                />
                                <img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="btn-admin cursor-pointer flex justify-center"
                                    @click="onAdminInputClick(slotProps.data, true)"
                                />
                            </div>   
                        </template>
                    </Column>
                    <Column field="is_active" :header="i18next.t('AcctMgmt.AccountActivation')" bodyClass="text-neutral-500"
                        headerClass="header-center">
                        <template #body="slotProps">
                            <div class="row-container flex-w-full-hoverable w-full" @mouseenter="handleRowMouseOver(slotProps.data.username)"
                                @mouseout="handleRowMouseOut(slotProps.data.username)">
                                <div class="w-full flex justify-center">
                                    <img v-if="slotProps.data.is_active" src="@/assets/radioOn.svg" alt="Radio On" class="btn-activate cursor-pointer flex"
                                        @click="setIsActiveInput(slotProps.data, false)"/>
                                    <img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="btn-activate cursor-pointer flex"
                                        @click="setIsActiveInput(slotProps.data, true)"/>
                                </div> 
                            </div>                                  
                        </template>
                    </Column>
                    <Column :header="i18next.t('AcctMgmt.Detail')" bodyClass="text-neutral-500" headerClass="header-center">
                        <template #body="slotProps">
                            <div class="row-container flex-w-full-hoverable w-full flex justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)"
                                @mouseout="handleRowMouseOut(slotProps.data.username)">
                                <img :src="slotProps.data.isDetailHovered ? iconDetailOn : iconDetailOff" alt="Detail" class="btn-detail cursor-pointer" @click="onDetailBtnClick(slotProps.data.username)"
                                    @mouseover="handleDetailMouseOver(slotProps.data.username)"
                                    @mouseout="handleDetailMouseOut(slotProps.data.username)"
                                />
                            </div>
                        </template>
                    </Column>
                    <Column :header="i18next.t('AcctMgmt.Edit')" bodyClass="text-neutral-500" headerClass="header-center">
                        <template #body="slotProps">
                            <div class="row-container flex-w-full-hoverable w-full flex justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)">
                                <img :src="slotProps.data.isEditHovered ? iconEditOn : iconEditOff" alt="Edit" class="btn-edit cursor-pointer"
                                    @click="onEditButtonClick(slotProps.data.username)"
                                    @mouseover="handleEditMouseOver(slotProps.data.username)"
                                    @mouseout="handleEditMouseOut(slotProps.data.username)"
                                />
                            </div>                            
                        </template>
                    </Column>
                    <Column :header="i18next.t('AcctMgmt.Delete')" bodyClass="text-neutral-500 flex justify-center" headerClass="header-center">
                        <template #body="slotProps">
                            <div class="row-container flex-w-full-hoverable w-full flex justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)">
                                <img :src="slotProps.data.isDeleteHovered ? iconDeleteRed : iconDeleteGray"
                                    :alt="slotProps.data.isDeleteHovered ? 'hovered' : 'not-hovered'"
                                    class="delete-account cursor-pointer flex"
                                    @mouseover="handleDeleteMouseOver(slotProps.data.username)"
                                    @mouseout="handleDeleteMouseOut(slotProps.data.username)"
                                    @click="onDeleteBtnClick(slotProps.data.username)"
                                >
                            </div>
                        </template>
                    </Column>
                </DataTable>
            </div>
        </div>
    </div>
</template>

<script>
import { ref, computed, onMounted, watch, } from 'vue';
import { storeToRefs, mapState, mapActions, } from 'pinia';
import LoadingStore from '@/stores/loading.js';
import { useModalStore } from '@/stores/modal.js';
import useAcctMgmtStore from '@/stores/acctMgmt.ts';
import piniaLoginStore from '@/stores/login.ts';
import SearchBar from '../../../components/AccountMenu/SearchBar.vue';
import i18next from '@/i18n/i18n.js';
import { useToast } from 'vue-toast-notification';
import {
    MODAL_CREATE_NEW,
    MODAL_ACCT_EDIT,
    MODAL_ACCT_INFO,
    MODAL_DELETE,
    ONCE_RENDER_NUM_OF_DATA,
  } from "@/constants/constants.js";
  import iconDeleteGray from '@/assets/icon-delete-gray.svg';
  import iconDeleteRed from '@/assets/icon-delete-red.svg';
  import iconEditOff from '@/assets/icon-edit-off.svg';
  import iconEditOn from '@/assets/icon-edit-on.svg';
  import iconDetailOn from '@/assets/icon-detail-on.svg';
  import iconDetailOff from '@/assets/icon-detail-card.svg';

// 這是製作假資料，在正式環境不會用到
function repeatAccountList(accountList, N) {
    const repeatedList = [];

    for (let i = 0; i < N; i++) {
        accountList.forEach(account => {
            const newAccount = { ...account, id: account.id + i };
            repeatedList.push(newAccount);
        });
    }

    return repeatedList;
}

// 這是製作假資料，在正式環境不會用到
// const repeatedAccountList = repeatAccountList(accountList, 20);

export default {
    setup() {
        const toast = useToast();
        const acctMgmtStore = useAcctMgmtStore();
        const loadingStore = LoadingStore();
        const modalStore = useModalStore();
        const { isLoading } = storeToRefs(loadingStore);
        const loginStore = piniaLoginStore();
        const infiniteStart = ref(0);

        const shouldUpdateList = computed(() => acctMgmtStore.shouldUpdateList);
        
        const allAccountResponsive = computed(() => acctMgmtStore.allUserAccoutList);
        const infiniteAcctData = computed(() => allAccountResponsive.value.slice(0, infiniteStart.value + ONCE_RENDER_NUM_OF_DATA));
        const loginUserData = ref(null);

        const isOneAccountJustCreate = computed(() => acctMgmtStore.isOneAccountJustCreate);
        const justCreateUsername = computed(() => acctMgmtStore.justCreateUsername);

        const inputQuery = ref('');

        const fetchLoginUserData = async () => {
            await loginStore.getUserData();
            loginUserData.value = loginStore.userData;
        };

        const moveJustCreateUserToFirstRow = () => {
            if(infiniteAcctData.value && infiniteAcctData.value.length){
                const index = acctMgmtStore.allUserAccoutList.findIndex(user => user.username === acctMgmtStore.justCreateUsername);
                if (index !== -1) {
                    // 移除匹配的對象(剛剛新增的使用者)並將其插入到陣列的第一位
                    const [justCreateUser] = acctMgmtStore.allUserAccoutList[index];
                    infiniteAcctData.value.unshift(justCreateUser);
                }
            }
        };

        const accountSearchResults = computed(() => {
            if(!inputQuery.value) {
                return infiniteAcctData.value;
            }
            return acctMgmtStore.allUserAccoutList.filter (user => user.username.includes(inputQuery.value));
        });

        const onCreateNewClick = () => {
            acctMgmtStore.clearCurrentViewingUser();
            modalStore.openModal(MODAL_CREATE_NEW);
        };

        
        const onAcctDoubleClick = (username) => {
            acctMgmtStore.setCurrentViewingUser(username);
            modalStore.openModal(MODAL_ACCT_INFO);
        }

        const handleDeleteMouseOver = (username) => {
            acctMgmtStore.changeIsDeleteHoveredByUser(username, true);
        };

        const handleDeleteMouseOut = (username) => {
            acctMgmtStore.changeIsDeleteHoveredByUser(username, false);
        };

        const handleRowMouseOver = (username) => {
            acctMgmtStore.changeIsRowHoveredByUser(username, true);
        };

        const handleRowMouseOut = (username) => {
            acctMgmtStore.changeIsRowHoveredByUser(username, false);
        };


        const handleEditMouseOver = (username) => {
            acctMgmtStore.changeIsEditHoveredByUser(username, true);
        };

        const handleEditMouseOut = (username) => {
            acctMgmtStore.changeIsEditHoveredByUser(username, false);
        };

        const handleDetailMouseOver = (username) => {
            acctMgmtStore.changeIsDetailHoveredByUser(username, true);
        };

        const handleDetailMouseOut = (username) => {
            acctMgmtStore.changeIsDetailHoveredByUser(username, false);
        };
        
        const onEditButtonClick = userNameToEdit => {
            acctMgmtStore.setCurrentViewingUser(userNameToEdit);
            modalStore.openModal(MODAL_ACCT_EDIT);
        }

        const onDeleteBtnClick = (usernameToDelete) => {
            acctMgmtStore.setCurrentViewingUser(usernameToDelete);
            modalStore.openModal(MODAL_DELETE);
        };

        const getRowClass = (curData) => {
            return curData?.isRowHovered ? 'bg-[#F1F5F9]' : '';
        };

        watch(shouldUpdateList, async(newShouldUpdateList) => {
            if (newShouldUpdateList) {
                await acctMgmtStore.getAllUserAccounts();
                acctMgmtStore.setShouldUpdateList(false);

                // 當夾帶有infiniteStart.value，就表示依然考慮到無限捲動的需求
                infiniteAcctData.value = allAccountResponsive.value.slice(0, infiniteStart.value + ONCE_RENDER_NUM_OF_DATA);
                moveJustCreateUserToFirstRow();
            }
        });

        const onSearchAccountButtonClick = (inputQueryString) => {
            inputQuery.value = inputQueryString;
        };
        
        const setIsActiveInput = async(userData, inputIsActiveToSet) => {
            const userDataToReplace = {
                username: userData.username,
                name: userData.name,
                is_active: inputIsActiveToSet,
            };
            await acctMgmtStore.editAccount(userData.username, userDataToReplace);
            acctMgmtStore.updateSingleAccountPiniaState(userDataToReplace);
            toast.success(i18next.t("AcctMgmt.MsgAccountEdited"));
        }

        const onAdminInputClick = async(userData, inputIsAdminOn) => {
            const ADMIN_ROLE_NAME = 'admin';
            switch(inputIsAdminOn) {
                case true:
                    await acctMgmtStore.addRoleToUser(userData.username, ADMIN_ROLE_NAME);
                    break;
                case false:
                    await acctMgmtStore.deleteRoleToUser(userData.username, ADMIN_ROLE_NAME);
                    break;
                default:
                    break;
            }
            const userDataToReplace = {
                username: userData.username,
                name: userData.name,
                is_admin: inputIsAdminOn,
            };
            
            acctMgmtStore.updateSingleAccountPiniaState(userDataToReplace);
            toast.success(i18next.t("AcctMgmt.MsgAccountEdited"));
        }

        onMounted(async () => { 
            await fetchLoginUserData();
            await acctMgmtStore.getAllUserAccounts();
        });

        /**
         * 無限滾動: 監聽 scroll 有沒有滾到底部
         * @param {element} event 滾動傳入的事件
            
            scrollTop，表示容器的垂直滾動位置。具體來說，它是以像素為單位的數值，
            表示當前內容視窗（可見區域）的頂部距離整個可滾動內容的頂部的距離。
            簡單來說，scrollTop 指的是滾動條的位置：當滾動條在最上面時，scrollTop 為 0；
            當滾動條向下移動時，scrollTop 會增加。
            可是作為：我們目前已經滾動了多少。
            
            clientHeight：表示容器的可見高度（不包括滾動條的高度）。它是以像素為單位的數值，
            表示容器內部的可見區域的高度。
            與 offsetHeight 不同的是，clientHeight 不包含邊框、內邊距和滾動條的高度，只計算內容區域的高度。
            
            scrollHeight：表示容器內部的總內容高度。它是以像素為單位的數值，
            包括看不見的（需要滾動才能看到的）部分。
            簡單來說，scrollHeight 是整個可滾動內容的總高度，包括可見區域和需要滾動才能看到的部分。
         */

        const handleScroll = (event) => {
            const container = event.target;
            const smallValue = 3;

            const isOverScrollHeight = container.scrollTop + container.clientHeight >= container.scrollHeight - smallValue;
            if(isOverScrollHeight){
                fetchMoreDataVue3();
            }
        };
        
        const fetchMoreDataVue3 = () => {            
            if(infiniteAcctData.value.length < acctMgmtStore.allUserAccoutList.length) {
                infiniteStart.value += ONCE_RENDER_NUM_OF_DATA;
            }  
        };

        return {
            accountSearchResults,
            isLoading,
            modalStore,
            loginUserData,
            infiniteAcctData,
            isOneAccountJustCreate,
            justCreateUsername,
            onEditButtonClick,
            onCreateNewClick,
            onAcctDoubleClick,
            onSearchAccountButtonClick,
            handleScroll,
            getRowClass,
            onDeleteBtnClick,
            onAdminInputClick,
            handleDeleteMouseOver,
            handleDeleteMouseOut,
            handleRowMouseOver,
            handleRowMouseOut,
            handleEditMouseOver,
            handleEditMouseOut,
            handleDetailMouseOver,
            handleDetailMouseOut,
            setIsActiveInput,
            iconDeleteGray,
            iconDeleteRed,
            iconEditOff,
            iconEditOn,
            iconDetailOn,
            iconDetailOff,
        };
    },
    data() {
        return {
            i18next: i18next,
            infiniteAcctDataVue2: [],
            infiniteStart: 0,
            isInfiniteFinish: true,
            isInfinitMaxItemsMet: false,
        };
    },
    components: {
        SearchBar,
    },
    computed: {
        ...mapState(useAcctMgmtStore, ['allUserAccoutList']),
    },
    methods: {
        /**
         * 無限滾動: 監聽 scroll 有沒有滾到底部
         * @param {element} event 滾動傳入的事件
         */
        handleScrollVue2(event) {
            if(this.infinitMaxItems || this.infiniteAcctDataVue2.length < ONCE_RENDER_NUM_OF_DATA || this.isInfiniteFinish === false) {
                return;
            }

            const container = event.target;
            const smallValue = 4;

            const overScrollHeight = container.scrollTop + container.clientHeight >= container.scrollHeight - smallValue;

            if(overScrollHeight){
                this.fetchMoreDataVue2();
            }
        },
        /**
         * 無限滾動: 滾到底後，要載入數據
         */
        async fetchMoreDataVue2() {
            this.isLoading = true;
            this.infiniteFinish = false;
               this.infiniteStart += ONCE_RENDER_NUM_OF_DATA;
            this.infiniteAcctDataVue2 = await [...this.infiniteAcctDataVue2, ...this.allUserAccoutList.slice(
                this.infiniteStart, this.infiniteStart + ONCE_RENDER_NUM_OF_DATA)];
            this.isInfiniteFinish = true;
            this.isLoading = false;

        },
        onDetailBtnClick(dataKey){
            this.openModal(MODAL_ACCT_INFO);
            this.setCurrentViewingUser(dataKey);
        },
        onEditBtnClickVue2(clickedUserName){
            this.setCurrentViewingUser(clickedUserName);
            this.openModal(MODAL_ACCT_EDIT);                       
        },
        ...mapActions(useModalStore, ['openModal']),
        ...mapActions(useAcctMgmtStore, [
            'setCurrentViewingUser',
            'getAllUserAccounts',
        ]),
    },
    created() {
    },
};
</script>
<style>
/*為了讓 radio 按鈕可以置中，所以讓欄位的文字也置中 */
.header-center .p-column-header-content{
    justify-content: center;
}
</style>