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, USER_UNIT_ID } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { StockTakingInsert } from '../entities/input/stockTakingInsert';
import { WarehouseAll } from '../entities/input/warehouseAll';
import { StockTakingInsertOutput } from '../entities/output/stockTakingInsertOutput';
import { WarehouseAllOutput } from '../entities/output/warehouseAllOutput';
import { CreateStockTakingInsert, LoadWarehouseAll } from './inventory-new.action';

export interface InventoryNewStateModel {
    loadingStockTakingInsert: boolean;
    loadingWarehouseAll: boolean;
    stockTakingInsert: StockTakingInsertOutput;
    warehouses: WarehouseAllOutput[];
}

const initialStateModel: InventoryNewStateModel = {
    loadingStockTakingInsert: false,
    loadingWarehouseAll: false,
    stockTakingInsert: null,
    warehouses: []
};

@State<InventoryNewStateModel>({
    name: 'inventoryNew',
    defaults: initialStateModel
})
export class InventoryNewState {
    @Selector()
    static getStockTaking(state: InventoryNewStateModel) {
        return state.stockTakingInsert;
    }

    @Selector()
    static getWarehouses(state: InventoryNewStateModel) {
        return state.warehouses;
    }

    @Selector()
    static isLoading(state: InventoryNewStateModel) {
        return state.loadingStockTakingInsert || state.loadingWarehouseAll;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }

    /**
     * create StockTaking Warehouse Item Insert
     *
     * @param {StateContext<InventoryNewStateModel>} ctx
     * @param {CreateStockTakingInsert} action
     * @returns {Observable<any>}
     */
    @Action(CreateStockTakingInsert)
    createStockTakingInsert(ctx: StateContext<InventoryNewStateModel>, action: CreateStockTakingInsert) {
        ctx.patchState({
            loadingStockTakingInsert: true
        });

        return this.webApiService.call(
            new StockTakingInsert(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.warehouseList, ApplicationSettings.getNumber(USER_UNIT_ID), action.date, action.stockTakingTypeId, action.note),
            () => new StockTakingInsertOutput(),
            wsMaterial
        ).pipe(
            tap((response: StockTakingInsertOutput[]) => {
                if (response.length === 1) {
                    ctx.patchState({
                        loadingStockTakingInsert: false,
                        stockTakingInsert: response[0]
                    });
                } else {
                    ctx.patchState({
                        loadingStockTakingInsert: false,
                        stockTakingInsert: initialStateModel.stockTakingInsert
                    });
                    throw new Error('Nepodařilo se vložit novou inventuru.');
                }
            }),
            catchError(e => {
                ctx.patchState({
                    loadingStockTakingInsert: false,
                    stockTakingInsert: initialStateModel.stockTakingInsert
                });

                throw e;
            })
        );

    }

    /**
     * Load warehouses
     *
     * @param {StateContext<InventoryNewStateModel>} ctx
     * @param {LoadWarehouseAll} action
     * @returns {Observable<any>}
     */
    @Action(LoadWarehouseAll)
    loadWarehouseAll(ctx: StateContext<InventoryNewStateModel>, action: LoadWarehouseAll) {
        ctx.patchState({
            loadingWarehouseAll: true
        });

        return this.webApiService.call(
            new WarehouseAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), ApplicationSettings.getNumber(USER_UNIT_ID)),
            () => new WarehouseAllOutput(),
            wsMaterial
        ).pipe(
            tap((response: WarehouseAllOutput[]) => {
                ctx.patchState({
                    loadingWarehouseAll: false,
                    warehouses: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingWarehouseAll: false,
                    warehouses: initialStateModel.warehouses
                });

                throw e;
            })
        );
    }
}
