import { Action, Selector, State, StateContext } from '@ngxs/store';
import { tap, catchError } from 'rxjs/operators';
import { wsEvents, wsOrganizationUnit, APP_ID } from '~/constants/api.constants';
import { USER_TOKEN } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { PersonAll } from '~/pages/search-person/entities/input/personAll';
import { GenParticipantSearchPerson, GenParticipantInsert, GenEventUpdateParticipant, GenEventRemoveParticipant, LoadGenEventNewParticipationQualificationTypes, LoadGenEventNewParticipationFunctionTypes, GenEventParticipantResetSearch, GenEventUpdateParticipantStatisticAutoComputed } from './gen-event-participant.actions';
import { ApplicationSettings as AppSettings } from '@nativescript/core';

import { FeedbackType } from 'nativescript-feedback';
import { feedbackMessage } from '~/pages/material/utils/feedback-messages';
import { EventGeneralUpdateStatisticAutoComputed, GenEventPersonOutput, ParticipantGeneralDelete, ParticipantGeneralInsert, ParticipantGeneralUpdate, ParticipantGenInsertOutput } from '../../entities/gen-event-participant.types';
import { GenEventDetailStateModel } from './gen-event-detail.state';
import { errorFeedbackOperator } from './gen-event-new.state';
import { GenEventRemoveParticipantFromList, GenEventUpdateParticipantList } from './gen-event-detail.actions';
import { QualificationTypeAll } from './../../../search-person/entities/input/qualificationTypeAll';
import { QualificationTypeAllOutput } from './../../../search-person/entities/output/qualificationTypeAllOutput';
import { FunctionTypeAll } from '~/pages/search-person/entities/input/functionTypeAll';
import { FunctionTypeAllOutput } from '~/pages/search-person/entities/output/functionTypeAllOutput';

export interface GenEventParticipantStateModel {
    newParticipant: ParticipantGenInsertOutput,
    personList: GenEventPersonOutput[],
    qualifications: QualificationTypeAllOutput[],
    functions: FunctionTypeAllOutput[],
}


const initialStateModel: GenEventParticipantStateModel = {
    personList: [],
    newParticipant: null,
    qualifications: [],
    functions: [],
};

@State<GenEventParticipantStateModel>({
    name: 'GenEventParticipant',
    defaults: initialStateModel
})

export class GenEventParticipantState {
    @Selector()
    static getPersonList(state: GenEventParticipantStateModel) {
        return state.personList;
    }
    @Selector()
    static getNewParticipant(state: GenEventParticipantStateModel) {
        return state.newParticipant;
    }
    @Selector()
    static getQualifications(state: GenEventParticipantStateModel) {
        return state.qualifications;
    }
    @Selector()
    static getFunctions(state: GenEventParticipantStateModel) {
        return state.functions;
    }


    constructor(
        private webApiService: WebApiService
    ) {
    }


    @Action(GenParticipantSearchPerson)
    searchPerson(ctx: StateContext<GenEventParticipantStateModel>,
        { payload }: GenParticipantSearchPerson) {
        const tk = AppSettings.getString(USER_TOKEN)
        const input = new PersonAll(APP_ID, tk);
        input[payload.criteria] = payload.text;
        input.ID_FunctionType = parseInt(payload.functionId) || undefined;
        input.ID_QualificationType = parseInt(payload.qualificationId) || undefined;
        input.OnlyDirectMember = payload.onlyDirectUnits || undefined;
        input.RegistrationNumber = payload.unitRegistrationNumber || undefined;

        return this.webApiService.call(input,
            () => new GenEventPersonOutput(),
            wsOrganizationUnit
        ).pipe(
            tap((personList: GenEventPersonOutput[]) => {
                ctx.patchState({
                    personList
                });
            }),
            catchError(e => {
                ctx.patchState({
                    personList: initialStateModel.personList
                });

                throw e;
            })
        );
    }
    @Action(LoadGenEventNewParticipationQualificationTypes)
    loadQualificationTypes(ctx: StateContext<GenEventParticipantStateModel>) {
        const tk = AppSettings.getString(USER_TOKEN)
        const input = new QualificationTypeAll(tk);
        return this.webApiService.call(input,
            () => new QualificationTypeAllOutput(),
            wsOrganizationUnit
        ).pipe(
            tap((qualifications: QualificationTypeAllOutput[]) => {
                ctx.patchState({
                    qualifications
                });
            }),
            catchError(e => {
                ctx.patchState({
                    qualifications: initialStateModel.qualifications
                });

                throw e;
            })
        );
    }
    @Action(LoadGenEventNewParticipationFunctionTypes)
    loadFunctionTypes(ctx: StateContext<GenEventParticipantStateModel>) {
        const tk = AppSettings.getString(USER_TOKEN)
        const input = new FunctionTypeAll(tk);
        return this.webApiService.call(input,
            () => new FunctionTypeAllOutput(),
            wsOrganizationUnit
        ).pipe(
            tap((functions: FunctionTypeAllOutput[]) => {
                ctx.patchState({
                    functions
                });
            }),
            catchError(e => {
                ctx.patchState({
                    functions: initialStateModel.functions
                });

                throw e;
            })
        );
    }

    @Action(GenParticipantInsert)
    insertParticipant(ctx: StateContext<GenEventParticipantStateModel>, { payload }: GenParticipantInsert) {
        const tk = AppSettings.getString(USER_TOKEN)
        const { personId, newParticip, genId } = payload
        const input = new ParticipantGeneralInsert(tk, genId);
        if (personId) {
            input.ID_Person = personId
        } else if (newParticip) {
            const { firstName, lastName, nickName, note, degrees } = newParticip
            input.Person = {
                FirstName: firstName, LastName: lastName, NickName: nickName,
                Note: note, Degrees: degrees.map(p => p.ID)
            }

        }

        ctx.patchState({ newParticipant: null })
        return this.webApiService.call(input,
            () => new ParticipantGenInsertOutput(),
            wsEvents
        ).pipe(
            tap((response: ParticipantGenInsertOutput[]) => {
                if (response.length === 1) {
                    ctx.patchState({ newParticipant: response[0], personList: [] })
                    feedbackMessage(FeedbackType.Success, 'Účastník akce přidán', 'Účastník akce byl úspěšně přidán')
                    return "Účastník akce byl úspěšně přidán"
                }
                feedbackMessage(FeedbackType.Error, 'Účastník akce nebyl přidán', 'Nepodařilo se přidat učastníka akce')
                throw "Nepodařilo se přidat učastníka akce"

            }),
            catchError(e => {
                feedbackMessage(FeedbackType.Error, 'Účastník akce nebyl přidán', 'Nepodařilo se přidat učastníka akce')
                throw e;
            })
        );

    }
    @Action(GenEventParticipantResetSearch)
    resetSearch(ctx: StateContext<GenEventParticipantStateModel>) {
        ctx.patchState({ personList: [] })
    }

    @Action(GenEventRemoveParticipant)
    removeParticipant(ctx: StateContext<GenEventDetailStateModel>, { participantId }: GenEventRemoveParticipant) {

        if (participantId) {
            const tk = AppSettings.getString(USER_TOKEN)
            const event = new ParticipantGeneralDelete(
                tk, participantId
            );
            return this.webApiService.call(event,
                () => ({}),
                wsEvents
            ).pipe(
                tap(() => {
                    feedbackMessage(FeedbackType.Success, 'Účastník smazan.', `Id: ${participantId}`)
                    ctx.dispatch(new GenEventRemoveParticipantFromList(participantId))
                }),
                errorFeedbackOperator('CampEventRemoveParticipant')
            );
        }
    }

    @Action(GenEventUpdateParticipantStatisticAutoComputed)
    updateStatisticAuto(ctx: StateContext<GenEventDetailStateModel>, { eventId, value }: GenEventUpdateParticipantStatisticAutoComputed) {

        const tk = AppSettings.getString(USER_TOKEN)
        const event = new EventGeneralUpdateStatisticAutoComputed(
            tk, eventId, value
        );
        return this.webApiService.call(event,
            () => ({}),
            wsEvents
        ).pipe(
            tap(() => {
                feedbackMessage(FeedbackType.Success, 'Automaticky vyplnění', `Automaticky vyplnění změněno`)
            }),
            errorFeedbackOperator('EventGeneralUpdateStatisticAutoComputed')
        );

    }

    @Action(GenEventUpdateParticipant)
    updateParticipant(ctx: StateContext<GenEventDetailStateModel>, { payload }: GenEventUpdateParticipant) {
        if (payload) {
            const tk = AppSettings.getString(USER_TOKEN)
            const { ID, Days, Note } = payload.particip
            const model = new ParticipantGeneralUpdate(tk, ID, Days, Note)
            return this.webApiService.call(model,
                () => ({}),
                wsEvents
            ).pipe(
                tap(() => {
                    ctx.dispatch(new GenEventUpdateParticipantList(payload.particip))
                    feedbackMessage(FeedbackType.Success, 'Účastník upraven.', `Id: ${model.ID}`)
                }),
                errorFeedbackOperator('GenEventUpdateParticipant')
            );
        }

    }


}
