import { AxiosError, AxiosInstance, AxiosResponse } from "axios";
import { MainStateManager } from "../../MainStateManager";
import { ElementsOfFormFactory } from "../../Page/ElementsOfFormFactory";
import { IMainStateFactory } from "../../Types";
import { TREECODE } from "amisa-paths";
import { useAxios } from "../../AmisaAuth/Models/StorageManager/TokenInfo";
import { StructureCoding } from "../../StructureCoding";

export interface IStructuralCodeListViewRow {
    name: string;
    id: number;
    code: string;
}

interface ISearchParameter {
    currentPage: number;
    itemsPerPage: number,
    totalItems?: number,
    totalPages: number,
    needTotalCount?: boolean,
    showAll?: boolean,
    code?: string;
    filter?: string;
}

export interface IStructuralCodeFactoryForListView {
    urls: TREECODE;
    apiAxios: AxiosInstance;
    onlyLastLevel: boolean
    required: boolean;
    coding: StructureCoding,
    code: string;
    focusToElement: () => void;
    onChangeHandlerCode: (code: string) => void;
    getCodeData: () => void;
}

export class StructuralCodeListViewFactory {
    public mainStateManager: MainStateManager;
    public forceUpdate = () => { };
    public elementsOfForm;
    public get any() {
        return this as any;
    }
    public selectedRowId: number | null = null;
    public currentFilterWaitForLoad: string | null = '';

    public refFilterInput?: React.RefObject<HTMLInputElement>;
    public selectedRowRef?: React.RefObject<HTMLTableRowElement>;

    public rows: IStructuralCodeListViewRow[] = [];
    public filter: string;
    public code: string = '';
    public searchParameter: ISearchParameter = { currentPage: 1, itemsPerPage: 20, totalPages: 0 };

    constructor(
        public mainStateFactory: IMainStateFactory,
        public selfStructuralCode: IStructuralCodeFactoryForListView,
        public onlyLastLevel: boolean,
        initialFilterValue?: string,
    ) {
        this.mainStateManager = this.mainStateFactory.mainStateManager;
        this.elementsOfForm = new ElementsOfFormFactory(this.mainStateFactory);
        this.code = this.selfStructuralCode.code;
        this.filter = initialFilterValue || '';
    }
    public previousRow = () => {
        this.selectPreviousRow();
    }
    public nextRow = () => {
        this.selectNextRow();
    }

    selectPreviousRow = (): void => {
        for (let index = 0; index < this.rows.length; index++) {
            const row = this.rows[index];

            if (row.id === this.selectedRowId && index > 0) {
                this.selectThisRow(this.rows[index - 1]);
                return;
            }
        }
        if (this.rows && this.rows.length > 0) {
            this.selectThisRow(this.rows[this.rows.length - 1]);
        }
    }

    selectNextRow = (): void => {
        for (let index = 0; index < this.rows.length; index++) {
            const row = this.rows[index];

            if (row.id === this.selectedRowId && index < this.rows.length - 1) {
                this.selectThisRow(this.rows[index + 1]);
                return;
            }
        }

        if (this.rows && this.rows.length > 0) {
            this.selectThisRow(this.rows[0]);
        }
    }
    public previousPage = () => {
        this.selectByPageup();
    }
    public nextPage = () => {
        this.selectByPagedown();
    }
    selectByPageup(): void {
        const selectedRow = this.rows.find((i) => i.id === this.selectedRowId);
        if (selectedRow) {
            const selectedRowIndex = this.rows.indexOf(selectedRow);

            if (selectedRowIndex - 10 < 0) {
                this.selectThisRow(this.rows[0]);
                return;
            } else {
                this.selectThisRow(this.rows[selectedRowIndex - 10]);
                return;
            }
        }
    }

    selectByPagedown(): void {
        const selectedRow = this.rows.find((i) => i.id === this.selectedRowId);
        if (selectedRow) {
            const selectedRowIndex = this.rows.indexOf(selectedRow);

            if (selectedRowIndex + 10 <= this.rows.length - 1) {
                this.selectThisRow(this.rows[selectedRowIndex + 10]);
                return;
            } else if (
                this.rows.length + 1 > selectedRowIndex &&
                this.rows.length - 1 < selectedRowIndex + 10
            ) {
                this.selectThisRow(this.rows[this.rows.length - 1]);
                return;
            }
        }

        if (this.rows.length >= 10) {
            this.selectThisRow(this.rows[10]);
            return;
        } else if (this.rows.length > 0 && this.rows.length < 10) {
            this.selectThisRow(this.rows[this.rows.length]);
            return;
        }
    }

    selectFirst(): void {
        if (this.rows.length > 0) {
            this.selectThisRow(this.rows[0]);
        }
    }
    selectLast(): void {
        if (this.rows.length > 0) {
            this.selectThisRow(this.rows[this.rows.length - 1]);
        }
    }

    selectedRow = (): IStructuralCodeListViewRow | undefined => {
        return this.rows.find(
            (i) => i.id > 0 && i.id === this.selectedRowId
        );
    };
    currentRow = (): IStructuralCodeListViewRow | undefined => {
        return this.rows.find(
            (i) => i.id > 0 && i.id === this.selectedRowId
        );
    };

    setCurrentPage = (page: number): void => {
        this.searchParameter.currentPage = page;
        this.code = '';
        this.searchListView();
    };

    selectThisRow = (row: IStructuralCodeListViewRow): void => {
        this.selectedRowId = row.id;
        this.forceUpdate();
    };
    private _selectCurrentRowByCode = (): void => {
        if (this.rows && this.rows.length) {
            if (this.code === '' && this.rows && this.rows.length) {
                this.selectedRowId = this.rows[0].id;
            } else {
                const findRow = this.rows.find((i) => i.code === this.code);
                if (findRow) {
                    this.selectedRowId = findRow.id;
                }
            }
        }
    };


    public exportToExcel = () => {
        if (this.selfStructuralCode.urls.excel) {
            this.downloadFile(this.selfStructuralCode.urls.excel, this.searchParameter, this.afterExportToExcelSuccess);
        }
    }

    private afterExportToExcelSuccess = (_response: any) => {
        // UtilityFile.blobExcel(response.data);
    }

    downloadFile = <P>(
        path: string,
        searchParametr: P,
        afterSuccess: (response: AxiosResponse) => void
    ) => {
        // this.pageData.Eventing.trigger('form.waitLoading');
        // const header: AxiosRequestConfig = { responseType: 'arraybuffer', headers: { Authorization: `bearer ${this.mainStateManager.Usering.accessToken}` } };

        this.selfStructuralCode.apiAxios
            .post(path, searchParametr)
            .then((response: AxiosResponse) => {
                afterSuccess(response);
                this.forceUpdate()
            })
            .catch((error: AxiosError) => {
                console.error(error);
                this.forceUpdate();
            });
    };

    searchListView = (): void => {
        this.elementsOfForm.showWaitingFormSpinner();
        this.forceUpdate();
        const searchParameter: ISearchParameter = { ...this.elementsOfForm.searchParameter, ...this.searchParameter };
        if (this.filter !== '') {
            // searchParameter.filter = this.filter;
            searchParameter.code = '';
            // searchParameter.currentPage = 1;
        } else {
            searchParameter.code = this.code;
            // searchParameter.filter = '';
        }

        this.selfStructuralCode.apiAxios.get(this.selfStructuralCode.urls.search, { params: searchParameter })
            .then((response: AxiosResponse): void => {
                this.searchParameter = {
                    ...this.searchParameter,
                    totalItems: response.data.searchParameter.totalItems,
                    itemsPerPage: response.data.searchParameter.itemsPerPage,
                    currentPage: response.data.searchParameter.currentPage,
                    totalPages: response.data.searchParameter.totalPages,
                    needTotalCount: response.data.searchParameter.needTotalCount,
                    showAll: response.data.searchParameter.showAll,
                };
                this.rows = response.data.rows;
                this._selectCurrentRowByCode();

                this.elementsOfForm.closeWaitingFormSpinner();
                this.forceUpdate();
            })
            .catch((error: AxiosError): void => {
                this.elementsOfForm.closeWaitingFormSpinner();
                this.rows = [];
                this.elementsOfForm.showErrorMessageBox(error);
                this.forceUpdate();
            });
    };

    public accept = () => {
        this.acceptCurrentRow();
    }

    acceptCurrentRow = () => {
        const currentRow = this.currentRow();
        if (currentRow) {
            this.mainStateFactory.elementsOfForm.closeModal();
            this.selfStructuralCode.focusToElement();
            this.selfStructuralCode.onChangeHandlerCode(currentRow.code);
            this.selfStructuralCode.getCodeData();
        }
    }

    public close = () => {
        this.mainStateFactory.elementsOfForm.closeModal();
        this.selfStructuralCode.focusToElement();
    }

    cancelForm = () => {
        this.mainStateFactory.elementsOfForm.closeModal();
        this.selfStructuralCode.focusToElement();
    }
}