import { Model, routerRedux } from "dva";
import _ from 'lodash';
import { delay } from 'dva/saga';
import { PageState, AreaCode, AreaCodes } from '@/types/common';
import { getAreaCodes } from '@/services/common';
import { message, Modal } from 'antd';
import { formatMessage } from 'umi-plugin-locale';
import { validPwd, validPhone, validPhoneInput } from '@/utils/validate';
import { changePhone, sendCode } from './service';
import { dispatch } from '@/utils/utils';
import { encodePhone } from '@/utils/transform';

export interface ChphoneModelState {
  pageState: PageState;
  areacodes: AreaCodes,
  areacode: AreaCode | undefined, // 选中的地区

  phone: string;
  code: string;
  submitting: boolean;
  sendingCode: boolean;
  codeTimer: number;
}

const initState: ChphoneModelState = {
  pageState: PageState.Pending,
  areacodes: [],
  areacode: undefined,

  phone: '',
  code: '',
  submitting: false,
  sendingCode: false,
  codeTimer: -1,
};

const model: Model = {
  namespace: 'chphone',

  state: initState,

  effects: {
    *load(_, { put, call }) {
      yield put({ type: 'onUpdateState', pageState: PageState.Pending });
      try {
        const areacodes = yield call(getAreaCodes);
        yield put({
          type: 'onUpdateState',
          pageState: PageState.Success,
          areacodes,
          areacode: areacodes[0],
          phone: '',
          code: '',
          submitting: false,
          sendingCode: false,
          codeTimer: -1,
        });
      } catch (e) {
        yield put({
          type: 'onUpdateState',
          pageState: PageState.Failure,
        });
      }
    },

    *submit(_, { put, call, select }) {
      const {
        areacode,
        phone,
        code,
        submitting,
      } = (yield select((state: any) => state.chphone)) as ChphoneModelState;
      if (submitting) return;
      if (!areacode) return message.warn(formatMessage({ id: 'check.msgArea' }));
      if (!validPhone(phone)) return message.warn(formatMessage({ id: 'check.msgPhone' }));
      if (!code) return message.warn(formatMessage({ id: 'check.msgCode' }));
      yield put({ type: 'onUpdateState', submitting: true });
      try {
        yield call(changePhone, areacode, phone, code);
        yield put({ type: 'user/updateUser', payload: { phone: encodePhone(areacode, phone) } });
        Modal.success({
          okText: formatMessage({ id: 'common.iknow' }),
          title: formatMessage({ id: 'common.prompt' }),
          content: formatMessage({ id: 'chphone.success' }),
          onOk: () => dispatch(routerRedux.goBack()),
          maskClosable: false,
        });
      } catch (e) {
        message.error(e.message);
      } finally {
        yield put({ type: 'onUpdateState', submitting: false })
      }
    },

    *timer({ payload }: any, { put }) {
      yield put({ type: 'onUpdateState', codeTimer: payload });
      yield delay(1000);
      const next = payload - 1;
      if (next >= 0) {
        yield put({ type: 'timer', payload: next });
      }
    },

    *sendCode(_, { select, put, call }) {
      const { areacode, phone } = yield select((state: any) => state.chphone);
      if (!areacode) return message.warn(formatMessage({ id: 'check.msgArea' }));
      if (!validPhone(phone)) return message.warn(formatMessage({ id: 'check.msgPhone' }));

      yield put({ type: 'onUpdateState', sendingCode: true });
      try {
        yield call(sendCode, areacode, phone);
        yield put({ type: 'timer', payload: 60 });
      } catch(e) {
        message.error(e.message);
      } finally {
        yield put({ type: 'onUpdateState', sendingCode: false });
      }
    },
  },

  reducers: {
    onUpdateState(state, payload) {
      return {
        ...state,
        ...payload,
      };
    },

    onUpdatePhone(state, { payload } : any) {
      const phone = validPhoneInput(payload) ? payload : state.phone;
      return {
        ...state,
        phone,
      };
    },
  },
};

export default model;
