import { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
import { MainStateManager } from "../../MainStateManager";
import { ElementsOfFormFactory } from "../../Page/ElementsOfFormFactory";
import { IMainStateFactory } from "../../Types";
import { SimpleCodeFactory } from "./SimpleCodeFactory";
import { SIMPLECODE } from "amisa-paths";
import { useAxios } from "../../AmisaAuth/Models/StorageManager/TokenInfo";

export interface ISimpleCodeListViewRow {
    name: string;
    id: number;
    code: number;
}

interface ISearchParameter {
    currentPage: number;
    itemsPerPage: number,
    totalItems?: number,
    totalPages: number,
    needTotalCount?: boolean,
    showAll?: boolean,
    code?: number;
    filter?: string;
}

export class SimpleCodeListViewFactory {
    #urls: SIMPLECODE;
    #apiAxios: AxiosInstance;
    public mainStateManager: MainStateManager;
    public elementsOfForm;
    public forceUpdate = () => { };

    public get any() {
        return this as any;
    }
    public selectedRowId: number | null = null;
    public waitForLoad: boolean = false;
    public currentFilterWaitForLoad: string | null = '';

    public refFilterInput?: React.RefObject<HTMLInputElement>;
    public selectedRowRef?: React.RefObject<HTMLTableRowElement>;

    constructor(
        public mainStateFactory: IMainStateFactory,
        public selfSimpleCode: SimpleCodeFactory,
        public onlyLastLevel: boolean,
        public closeModal: () => void
    ) {
        this.mainStateManager = this.mainStateFactory.mainStateManager;
        this.#urls = selfSimpleCode.urls;
        this.#apiAxios = selfSimpleCode.apiAxios;

        this.elementsOfForm = new ElementsOfFormFactory(this.mainStateFactory);

        this.code = this.selfSimpleCode.code;
    }
    public rows: ISimpleCodeListViewRow[] = [];
    public filter: string = '';
    public code: number = 0;
    public searchParameter: ISearchParameter = { currentPage: 1, itemsPerPage: 20, totalPages: 0 };

    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]);
        }
    }

    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 = (): ISimpleCodeListViewRow | undefined => {
        return this.rows.find(
            (i) => i.id > 0 && i.id === this.selectedRowId
        );
    };
    currentRow = (): ISimpleCodeListViewRow | undefined => {
        return this.rows.find(
            (i) => i.id > 0 && i.id === this.selectedRowId
        );
    };

    setCurrentPage = (page: number): void => {
        this.searchParameter.currentPage = page;
        this.searchListView();
    };

    selectThisRow = (row: ISimpleCodeListViewRow): void => {
        this.selectedRowId = row.id;
        this.forceUpdate();
    };
    private _selectCurrentRowByCode = (): void => {
        if (this.rows && this.rows.length) {
            if (this.code === 0) {
                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.#urls.excel) {
            this.downloadFile(this.#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.#apiAxios
            .post(path, searchParametr)
            .then((response: AxiosResponse) => {
                afterSuccess(response);
                this.forceUpdate()
            })
            .catch((error: AxiosError) => {
                console.error(error);
                this.forceUpdate()
            });
    };

    searchListView = (): void => {
        this.waitForLoad = true;
        this.forceUpdate();
        const searchParameter: ISearchParameter = { ...this.searchParameter };
        if (this.filter !== '') {
            searchParameter.filter = this.filter;
            searchParameter.code = 0;
            searchParameter.currentPage = 1;
        } else {
            searchParameter.code = this.code;
            searchParameter.filter = '';
        }

        this.#apiAxios.get(this.#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.waitForLoad = false;

                this.forceUpdate();
            })
            .catch((error: AxiosError): void => {
                console.error(error);
                this.rows = [];
                this.forceUpdate();
            });
    };

    acceptCurrentRow = () => {
        const currentRow = this.currentRow();
        if (currentRow) {
            this.closeModal();
            this.selfSimpleCode.focusToElement();
            this.selfSimpleCode.onChangeHandlerCode(currentRow.code.toString());
            this.selfSimpleCode.getCodeData();
        }
    }

    cancelForm = () => {
        this.closeModal();
        this.selfSimpleCode.focusToElement();
    }
}