import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
import 'package:aman_kassa_flutter/redux/reducers/bank_reducer.dart';
import 'package:aman_kassa_flutter/redux/reducers/calc_reducer.dart';
import 'package:aman_kassa_flutter/redux/reducers/main_reducer.dart';
import 'package:aman_kassa_flutter/redux/reducers/setting_reducer.dart';
import 'package:aman_kassa_flutter/redux/reducers/user_reducer.dart';
import 'package:aman_kassa_flutter/redux/state/bank_state.dart';
import 'package:aman_kassa_flutter/redux/state/calc_state.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/state/setting_state.dart';
import 'package:aman_kassa_flutter/redux/state/user_state.dart';
import 'package:aman_kassa_flutter/views/payment/halyk_pos_service.dart';
import 'package:meta/meta.dart';
import 'package:redux/redux.dart';
import 'package:redux_persist_flutter/redux_persist_flutter.dart';
import 'package:redux_thunk/redux_thunk.dart';
import 'package:redux_persist/redux_persist.dart';

import 'actions/bank_actions.dart';
import 'actions/calc_actions.dart';

//reducer context
AppState appReducer(AppState state, dynamic action) {
  if (action is SetUserStateAction) {
    /** UserAction **/
    final nextUserState = userReducer(state.userState!, action);
    return state.copyWith(userState: nextUserState);
  } else if (action is SetKassaStateAction) {
    /** KassaAction **/
    final nextMainState = mainReducer(state.kassaState!, action);
    return state.copyWith(kassaState: nextMainState);
  } else if (action is SetSettingStateAction) {
    /** SettingAction **/
    final nextSettingState = settingReducer(state.settingState!, action);
    return state.copyWith(settingState: nextSettingState);
  } else if (action is SetCalcStateAction) {
    /** CalcAction **/
    final nextCalcState = calcReducer(state.calcState!, action);
    return state.copyWith(calcState: nextCalcState);
  } else if (action is SetBankStateAction) {
    /** BankAction **/
    final nextBankState = bankReducer(state.bankState!, action);
    return state.copyWith(bankState: nextBankState);
  }
  return state;
}

//Main  State
@immutable
class AppState {
  final UserState? userState;
  final KassaState? kassaState;
  final SettingState? settingState;
  final CalcState? calcState;
  final BankState? bankState;

  AppState({
    this.userState,
    this.kassaState,
    this.settingState,
    this.calcState,
    this.bankState,
  });

  //stable work
  AppState copyWith({
    UserState? userState,
    KassaState? kassaState,
    SettingState? settingState,
    CalcState? calcState,
    BankState? bankState,
  }) {
    return AppState(
      userState: userState ?? this.userState,
      kassaState: kassaState ?? this.kassaState,
      settingState: settingState ?? this.settingState,
      calcState: calcState ?? this.calcState,
      bankState: bankState ?? this.bankState,
    );
  }

  static AppState? fromJson(dynamic json){
    return json !=null
        ? AppState(
            settingState: SettingState.fromJson(json['settingState']),
            userState: UserState.fromJson(json['userState']),
            bankState: BankState.fromJson(json['bankState']),
          )
        : null;
  }

  dynamic toJson() {
    return {
      "settingState": settingState?.toJson(),
      "userState": userState?.toJson(),
      "bankState": bankState?.toJson(),
    };
  }
}

class Redux {
  static Store<AppState>? _store;

  static Store<AppState>? get store {
    if (_store == null) {
      throw Exception("store is not initialized");
    } else {
      return _store;
    }
  }

  //initial context
  static Future<void> init() async {
    // Create Persistor
    final persist = Persistor<AppState>(
      storage: FlutterStorage(), // Or use other engines
      serializer: JsonSerializer<AppState>(
          AppState.fromJson), // Or use other serializers
    );

    AppState? initialState;
    try {
      initialState = await persist.load();
    } catch (e, stack) {
      log.e('message', e, stack);
    }

    final userStateInitial = UserState.initial(initialState?.userState);
    final kassaStateInitial = KassaState.initial();
    final settingStateInitial = SettingState.initial(initialState?.settingState);
    final calcStateInitial = CalcState.initial();
    final bankStateInitial = BankState.initial(initialState?.bankState);

    _store = Store<AppState>(
      appReducer,
      middleware: [thunkMiddleware, persist.createMiddleware()],
      initialState: AppState(
          userState: userStateInitial,
          kassaState: kassaStateInitial,
          settingState: settingStateInitial,
          calcState: calcStateInitial,
          bankState: bankStateInitial),
    );
  }
}
