import { ApplicationSettings } from '@nativescript/core';
import { Action, Selector, State, StateContext } from '@ngxs/store';
import { catchError, tap } from 'rxjs/operators';
import { APP_ID, wsMaterial } from '~/constants/api.constants';
import { USER_TOKEN } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { StockTakingWarehouseItemInsert } from '../entities/input/stockTakingWarehouseItemInsert';
import { WarehouseItemAllStockTaking } from '../entities/input/warehouseItemAllStockTaking';
import { StockTakingWarehouseItemInsertOutput } from '../entities/output/stockTakingWarehouseItemInsertOutput';
import { WarehouseItemAllStockTakingOutput } from '../entities/output/warehouseItemAllStockTakingOutput';
import {
    CreateStockTakingWarehouseItemInsert,
    LoadWarehouseItemAllStockTaking
} from './inventory-waiting-confirm.action';

export interface InventoryWaitingConfirmStateModel {
    loadingStockTakingWarehouseItemInsert: boolean;
    loadingWarehouseItemAllStockTaking: boolean;
    stockTakingWarehouseItemInsert: StockTakingWarehouseItemInsertOutput;
    warehouseItemAllStockTaking: WarehouseItemAllStockTakingOutput[];
}

const initialStateModel: InventoryWaitingConfirmStateModel = {
    loadingStockTakingWarehouseItemInsert: false,
    loadingWarehouseItemAllStockTaking: false,
    stockTakingWarehouseItemInsert: null,
    warehouseItemAllStockTaking: []
};

@State<InventoryWaitingConfirmStateModel>({
    name: 'inventoryWaitingConfirm',
    defaults: initialStateModel
})
export class InventoryWaitingConfirmState {
    @Selector()
    static getWarehouseItemAllStockTaking(state: InventoryWaitingConfirmStateModel) {
        return state.warehouseItemAllStockTaking;
    }

    @Selector()
    static getStockTakingWarehouseItemInsert(state: InventoryWaitingConfirmStateModel) {
        return state.stockTakingWarehouseItemInsert;
    }

    @Selector()
    static isLoading(state: InventoryWaitingConfirmStateModel) {
        return state.loadingStockTakingWarehouseItemInsert || state.loadingWarehouseItemAllStockTaking;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }

    /**
     * Load all stock taking items
     *
     * @param {StateContext<InventoryWaitingConfirmStateModel>} ctx
     * @param {LoadWarehouseItemAllStockTaking} action
     * @returns {Observable<any>}
     */
    @Action(LoadWarehouseItemAllStockTaking)
    loadWarehouseItemAllStockTaking(ctx: StateContext<InventoryWaitingConfirmStateModel>, action: LoadWarehouseItemAllStockTaking) {
        ctx.patchState({
            loadingWarehouseItemAllStockTaking: true
        });

        return this.webApiService.call(
            new WarehouseItemAllStockTaking(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.idStockTaking, action.idWarehouse),
            () => new WarehouseItemAllStockTakingOutput(),
            wsMaterial
        ).pipe(
            tap((response: WarehouseItemAllStockTakingOutput[]) => {
                ctx.patchState({
                    loadingWarehouseItemAllStockTaking: false,
                    warehouseItemAllStockTaking: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingWarehouseItemAllStockTaking: false,
                    warehouseItemAllStockTaking: initialStateModel.warehouseItemAllStockTaking
                });

                throw e;
            })
        );

    }

    /**
     * create StockTaking Warehouse Item Insert
     *
     * @param {StateContext<InventoryWaitingConfirmStateModel>} ctx
     * @param {CreateStockTakingWarehouseItemInsert} action
     * @returns {Observable<any>}
     */
    @Action(CreateStockTakingWarehouseItemInsert)
    createStockTakingWarehouseItemInsert(ctx: StateContext<InventoryWaitingConfirmStateModel>, action: CreateStockTakingWarehouseItemInsert) {
        ctx.patchState({
            loadingStockTakingWarehouseItemInsert: true
        });

        if (action.inventoryId) {
            return this.webApiService.call(
                new StockTakingWarehouseItemInsert(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.inventoryId, action.items),
                () => new StockTakingWarehouseItemInsertOutput(),
                wsMaterial
            ).pipe(
                tap((response: StockTakingWarehouseItemInsertOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            loadingStockTakingWarehouseItemInsert: false,
                            stockTakingWarehouseItemInsert: response[0]
                        });
                    } else {
                        ctx.patchState({
                            loadingStockTakingWarehouseItemInsert: false,
                            stockTakingWarehouseItemInsert: initialStateModel.stockTakingWarehouseItemInsert
                        });
                        throw new Error('Nepodařilo se vložit inventarizovanou položku.');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingStockTakingWarehouseItemInsert: false,
                        stockTakingWarehouseItemInsert: initialStateModel.stockTakingWarehouseItemInsert
                    });

                    throw e;
                })
            );
        } else {
            ctx.patchState({
                loadingStockTakingWarehouseItemInsert: false
            });
        }
    }
}
