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 'package:satu/core/redux/actions/journal_actions.dart';
import 'package:satu/core/redux/actions/nav_actions.dart';
import 'package:satu/core/redux/actions/sell_actions.dart';
import 'package:satu/core/redux/actions/setting_actions.dart';
import 'package:satu/core/redux/reducers/journal_reducer.dart';
import 'package:satu/core/redux/reducers/nav_reducer.dart';
import 'package:satu/core/redux/reducers/sell_reducer.dart';
import 'package:satu/core/redux/reducers/setting_reducer.dart';
import 'package:satu/core/redux/reducers/user_reducer.dart';
import 'package:satu/core/redux/state/journal_state.dart';
import 'package:satu/core/redux/state/nav_state.dart';
import 'package:satu/core/redux/state/sell_state.dart';
import 'package:satu/core/redux/state/setting_state.dart';
import 'package:satu/core/redux/state/user_state.dart';

import 'actions/user_actions.dart';

//reducer context
AppState appReducer(AppState state, dynamic action) {
  if (action is SetUserStateAction) {
    final UserState nextState = userReducer(state.userState!, action);
    return state.copyWith(userState: nextState);
  } else if (action is SetNavStateAction) {
    final NavState nextState = navReducer(state.navState!, action);
    return state.copyWith(navState: nextState);
  } else if (action is SetSellStateAction) {
    final SellState nextState = sellReducer(state.sellState!, action);
    return state.copyWith(sellState: nextState);
  } else if (action is SetJournalStateAction) {
    final JournalState nextState = journalReducer(state.journalState!, action);
    return state.copyWith(journalState: nextState);
  } else if (action is SetSettingStateAction) {
    final SettingState nextState = settingReducer(state.settingState!, action);
    return state.copyWith(settingState: nextState);
  }
  return state;
}

//Main  State
@immutable
class AppState {
  const AppState({
    this.userState,
    this.navState,
    this.sellState,
    this.journalState,
    this.settingState,
  });

  final UserState? userState;
  final NavState? navState;
  final SellState? sellState;
  final JournalState? journalState;
  final SettingState? settingState;

  //stable work
  AppState copyWith({
    UserState? userState,
    NavState? navState,
    SellState? sellState,
    JournalState? journalState,
    SettingState? settingState,
  }) {
    return AppState(
      userState: userState ?? this.userState,
      navState: navState ?? this.navState,
      sellState: sellState ?? this.sellState,
      journalState: journalState ?? this.journalState,
      settingState: settingState ?? this.settingState,
    );
  }

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

  dynamic toJson() {
    return {
      'userState': userState!.toJson(),
      'settingState': settingState!.toMap(),
    };
  }
}

class Redux {
  static Store<AppState>? _store;

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

  //blank function just for lint context
  Future<void> blank() async {}

  //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
    );

    final AppState? initialState = await persist.load();
    final userStateInitial = UserState.initial(initialState?.userState);
    final navStateInitial = NavState.initial();
    final sellStateInitial = SellState.initial();
    final journalStateInitial = JournalState.initial();
    final settingStateInitial =
        SettingState.initial(initialState?.settingState);

    _store = Store<AppState>(
      appReducer,
      middleware: [thunkMiddleware, persist.createMiddleware()],
      initialState: AppState(
        userState: userStateInitial,
        navState: navStateInitial,
        sellState: sellStateInitial,
        journalState: journalStateInitial,
        settingState: settingStateInitial,
      ),
    );
  }
}
