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 { WarehouseItemReservationDetail } from '../entities/input/warehouseItemReservationDetail';
import { WarehouseItemReservationUpdate } from '../entities/input/warehouseItemReservationUpdate';
import { WarehouseItemReservationDetailOutput } from '../entities/output/warehouseItemReservationDetailOutput';
import { WarehouseItemReservationUpdateOutput } from '../entities/output/warehouseItemReservationUpdateOutput';
import { CreateReservationUpdate, LoadReservationDetail } from './reservation-update.action';

export interface ReservationUpdateStateModel {
    loadingWarehouseItemReservationDetail: boolean;
    loadingReservationUpdate: boolean;
    warehouseItemReservationDetail: WarehouseItemReservationDetailOutput;
    reservationUpdate: WarehouseItemReservationUpdateOutput;
}

const initialStateModel: ReservationUpdateStateModel = {
    loadingWarehouseItemReservationDetail: false,
    loadingReservationUpdate: false,
    warehouseItemReservationDetail: null,
    reservationUpdate: null
};

@State<ReservationUpdateStateModel>({
    name: 'reservationUpdate',
    defaults: initialStateModel
})
export class ReservationUpdateState {
    @Selector()
    static getReservationDetail(state: ReservationUpdateStateModel) {
        return state.warehouseItemReservationDetail;
    }

    @Selector()
    static getReservationUpdate(state: ReservationUpdateStateModel) {
        return state.reservationUpdate;
    }

    @Selector()
    static isLoading(state: ReservationUpdateStateModel) {
        return state.loadingReservationUpdate;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }

    /**
     * Load reservation detail
     *
     * @param {StateContext<ReservationUpdateStateModel>} ctx
     * @param {LoadReservationDetail} action
     * @returns {Observable<any>}
     */
    @Action(LoadReservationDetail)
    loadReservationDetail(ctx: StateContext<ReservationUpdateStateModel>, action: LoadReservationDetail) {
        ctx.patchState({
            loadingWarehouseItemReservationDetail: true
        });

        if (action.id) {
            return this.webApiService.call(
                new WarehouseItemReservationDetail(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.id),
                () => new WarehouseItemReservationDetailOutput(),
                wsMaterial
            ).pipe(
                tap((response: WarehouseItemReservationDetailOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            loadingWarehouseItemReservationDetail: false,
                            warehouseItemReservationDetail: response[0]
                        });
                    } else {
                        ctx.patchState({
                            loadingWarehouseItemReservationDetail: false,
                            warehouseItemReservationDetail: initialStateModel.warehouseItemReservationDetail
                        });
                        throw new Error('Nepodařilo se nalézt detail rezervace');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingWarehouseItemReservationDetail: false,
                        warehouseItemReservationDetail: initialStateModel.warehouseItemReservationDetail
                    });

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

    /**
     * It create request for rent insert
     *
     * @param {StateContext<WarehouseUpdateStateModel>} ctx
     * @param {CreateReservationUpdate} action
     * @returns {Observable<any>}
     */
    @Action(CreateReservationUpdate)
    createReservationUpdate(ctx: StateContext<ReservationUpdateStateModel>, action: CreateReservationUpdate) {
        ctx.patchState({
            loadingReservationUpdate: true
        });

        return this.webApiService.call(
            new WarehouseItemReservationUpdate(
                APP_ID, ApplicationSettings.getString(USER_TOKEN), action.id, action.idWarehouse, action.person,
                action.phone, action.email, action.estEndDate ? action.estEndDate : undefined),
            () => new WarehouseItemReservationUpdateOutput(),
            wsMaterial
        ).pipe(
            tap((response: WarehouseItemReservationUpdateOutput) => {
                ctx.patchState({
                    loadingReservationUpdate: false,
                    reservationUpdate: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingReservationUpdate: false,
                    reservationUpdate: initialStateModel.reservationUpdate
                });
                throw e;
            })
        );
    }
}
