import wx from '../utils/wx';
import config from './config';
import udid from './udid';
import {
  HmacSHA256,
  MD5
} from '../vendors/crypto';
import {
  stringify
} from '../vendors/query-stringify';

export const verify = {
  verifyMethod: 'resources.simple.pice',
  update() {
        return api.get({ // eslint-disable-line
      data: {
        method: this.verifyMethod
      }
    }).then(result => {
      if (result && result.code === 200 && result.data && result.data.sk) {
        wx.setStorageSync('verifyKey', result.data.sk);
      }

      return result;
    });
  },
  gen() {
    const self = this;
    let maxTryTimes = 3;

    function update() {
      return self.update().then(result => {
        if (result && result.code === 200 && result.data && result.data.sk) {
          return result.data.sk;
        } else if (maxTryTimes) {
          maxTryTimes--;

          return update();
        } else {
          return '';
        }
      });
    }

    return update();
  },
  get() {
    const verifyKey = wx.getStorageSync('verifyKey');

    if (!verifyKey) {
      this.gen(); // 异步更新
    }

    return verifyKey || '';
  },
  sign(data, encode = false) {
    const verifyKey = this.get();

    if (!verifyKey) {
      return '';
    }

    data = stringify(data, {
      encode: encode
    });

    return HmacSHA256(data, verifyKey).toString();
  },
  computeSecret(data, encode = false) {
    const newData = {
      private_key: config.apiParams.private_key
    };

    Object.keys(data).sort().forEach(key => {
      newData[key] = String(data[key]).trim();
    });

    newData.client_secret = MD5(stringify(newData, {
      encode: encode
    })).toString();
    delete newData.private_key;

    return newData;
  }
};

const api = {
  request(params) {
    const app = getApp();

    // 公有参数
    params.data = this.addParams(params.data);
    params = this.addSessionKey(params);

    // client_secret
    params.data = verify.computeSecret(params.data);

    // 接口验签
    if (!params.header['x-yoho-verify'] && params.data.method !== verify.verifyMethod) {
      params.header['x-yoho-verify'] = verify.sign(params.data);
    }

    return wx.request(params).then(result => {
      if (result.statusCode === 200) {
        const resultData = result && result.data || {};

        delete result.data;
        resultData.result = result;

        if (resultData.code === 508) {
          verify.gen();
        }

        if (resultData.code === params.code) {
          return resultData.data || {};
        }

        return resultData;
      } else if (result.statusCode === 401) {
        app.clearUserSession();
      } else {
        console.error('api statusCode:', result.statusCode);
        return result && result.data || {};
      }
    }).catch(err => {
      console.error(err);
      return {};
    });
  },
  addSessionKey(params) {
    const app = getApp();

    params = Object.assign({}, params);
    if (app && app.globalData && app.globalData.sessionKey) {
      params.data.session_key = app.globalData.sessionKey;

      if (!params.data.uid) {
        params.data.uid = app.globalData.userInfo.uid;
      }

      params.header.Cookies = `JSESSIONID=${app.globalData.sessionKey}`;
    }
    return params;
  },
  addParams(params) {
    return Object.assign({
      client_type: config.apiParams.client_type,
      app_version: config.apiParams.app_version,
      miniapp_version: config.apiParams.miniapp_version,
      udid: udid.get(),
      business_line: config.business_line,
      channel_type: 1
    }, params);
  },
  get(params) {
    // 默认值
    params = Object.assign({
      data: {},
      header: {},
      dataType: 'json'
    }, params, {
      url: config.domains[params.api || 'api'] + (params.url || ''),
    });

    // 构造好参数再请求
    return this.request(params);
  },
  post(params) {
    // 默认值
    params = Object.assign({
      method: 'post',
      data: {},
      header: {
        'content-type': 'application/x-www-form-urlencoded'
      },
      dataType: 'json'
    }, params, {
      url: config.domains[params.api || 'api'] + (params.url || ''),
    });

    // 构造好参数再请求
    return this.request(params);
  }
};

export default api;