import { makeAutoObservable } from 'mobx';
import { fflagsService } from 'App/services';
import FeatureFlag from './types/FeatureFlag';

type All = '0';
type Active = '1';
type Inactive = '2';
export type Activity = All | Active | Inactive;

export default class FeatureFlagsStore {
  currentFflag: FeatureFlag | null = null;

  isDescrEditing: boolean = false;

  isTitleEditing: boolean = false;

  flags: FeatureFlag[] = [];

  isLoading: boolean = false;

  flagsSearch: string = '';

  activity: Activity = '0';

  sort = { order: 'DESC', query: '' };

  page: number = 1;

  total = 0;

  readonly pageSize: number = 10;

  client: typeof fflagsService;

  constructor() {
    makeAutoObservable(this);
    this.client = fflagsService;
  }

  setFlagsSearch = (search: string) => {
    this.flagsSearch = search;
  };

  setPage = (page: number) => {
    this.page = page;
    void this.fetchFlags();
  };

  setEditing = ({ isDescrEditing = false, isTitleEditing = false }) => {
    this.isDescrEditing = isDescrEditing;
    this.isTitleEditing = isTitleEditing;
  };

  setList = (flags: FeatureFlag[]) => {
    this.flags = flags;
  };

  removeFromList = (id: FeatureFlag['featureFlagId']) => {
    this.flags = this.flags.filter((f) => f.featureFlagId !== id);
  };

  addFlag = (flag: FeatureFlag) => {
    this.flags.push(flag);
  };

  getFlagById = (id: string) =>
    this.flags.find((f) => f.featureFlagId === parseInt(id, 10));

  setCurrentFlag = (flag: FeatureFlag | null) => {
    this.currentFflag = flag;
  };

  initNewFlag = () => {
    this.currentFflag = new FeatureFlag();
  };

  setLoading = (isLoading: boolean) => {
    this.isLoading = isLoading;
  };

  setActivity = (activity: Activity) => {
    this.activity = activity;
  };

  setSort = (sort: { order: string; query: string }) => {
    this.sort = sort;
  };

  fetchFlags = async () => {
    this.setLoading(true);
    try {
      const filters = {
        limit: this.pageSize,
        page: this.page,
        order: this.sort.order,
        query: this.sort.query,
        isActive: this.activity === '0' ? undefined : this.activity === '1',
        // userId: 3,
      };
      const { list, total } = await this.client.fetchFlags(filters);
      const flags = list.map((record) => new FeatureFlag(record));
      this.setList(flags);
      this.setTotal(total);
    } catch (e) {
      console.error(e);
    } finally {
      this.setLoading(false);
    }
  };

  setTotal(total: number) {
    this.total = total;
  }

  checkFlagForm = () => {
    if (!this.currentFflag) return 'Feature flag not initialized';
    if (this.currentFflag.flagKey === '') {
      return 'Feature flag must have a key';
    }
    if (
      !this.currentFflag.isSingleOption &&
      this.currentFflag?.variants.findIndex((v) => v.value === '') !== -1
    ) {
      return 'All variants must include unique key';
    }
    if (
      !this.currentFflag?.isSingleOption &&
      this.currentFflag?.isRedDistribution
    ) {
      return 'Variants rollout percentage must add up to 100%';
    }
    return null;
  };

  createFlag = async () => {
    if (this.currentFflag) {
      this.setLoading(true);
      try {
        this.currentFflag.setHasChanged(false);
        const result = await this.client.createFlag(this.currentFflag.toJS());
        this.addFlag(new FeatureFlag(result));
      } catch (e) {
        console.error(e);
        throw e.response;
      } finally {
        this.setLoading(false);
      }
    }
  };

  updateFlagStatus = async (flagId: number, isActive: boolean) => {
    try {
      await this.client.updateStatus(flagId, isActive);
    } catch (e) {
      console.error(e);
      throw e;
    }
  };

  updateFlag = async (flag?: FeatureFlag, skipLoader?: boolean) => {
    const usedFlag = flag || this.currentFflag;
    if (usedFlag) {
      if (!skipLoader) {
        this.setLoading(true);
      }
      try {
        // @ts-ignore
        const result = await this.client.updateFlag(usedFlag.toJS());
        if (!flag) this.setCurrentFlag(new FeatureFlag(result));
        if (!flag) this.currentFflag?.setHasChanged(false);
      } catch (e) {
        console.error('getting api error', e);
        throw e.response;
      } finally {
        this.setLoading(false);
      }
    }
  };

  deleteFlag = async (id: FeatureFlag['featureFlagId']) => {
    this.setLoading(true);
    try {
      await this.client.deleteFlag(id);
      this.removeFromList(id);
    } catch (e) {
      console.error(e);
    } finally {
      this.setLoading(false);
    }
  };

  fetchFlag = async (id: FeatureFlag['featureFlagId']) => {
    this.setLoading(true);
    try {
      const result = await this.client.getFlag(id);
      this.setCurrentFlag(new FeatureFlag(result));
    } catch (e) {
      console.error(e);
    } finally {
      this.setLoading(false);
    }
  };
}
