import axios from 'axios';
import { parse } from 'cookie';
import { IncomingMessage } from 'http';
import jwtDecode from 'jwt-decode';
import getConfig from 'next/config';
import { IContext, TokenPayload, User } from 'typings/context';

type SmsResponse = {
  code: number;
  message: string;
};

const AUTH_URL = '/audkenning/begin';

const { publicRuntimeConfig } = getConfig();

const EXPIRE_OFFSET = 60000 * 1;

const isServer = typeof window === 'undefined';

export function initAuth(context: IContext, state = '/') {
  let redirectUrl = `${AUTH_URL}?redirect_uri=${state}`;

  const { token } = parseToken(context.req as IncomingMessage);

  if (state.indexOf('/staff') > -1 || context?.query?.isStaff === 'true' || isStaffToken(token)) {
    redirectUrl += '&acr=adfs';
  }

  if (isServer) {
    context.res?.writeHead(303, { Location: redirectUrl });
    context.res?.end();
  } else {
    window.location.href = redirectUrl;
  }
  return;
}

export function refreshAuth(token: string, state = '/') {
  let redirectUrl = `${AUTH_URL}?redirect_uri=${state}`;

  if (isStaffToken(token)) {
    redirectUrl += '&acr=adfs';
  }

  window.location.href = redirectUrl;

  return;
}

export function reLogin(returnUrl = '/') {
  window.location.href = `${AUTH_URL}?prompt=login&redirect_uri=${returnUrl}`;
}

export function isValid(token: string): boolean {
  if (!token) {
    return false;
  }

  const decodedToken = decodeToken(token);

  if (decodedToken && decodedToken.exp) {
    const { exp } = decodedToken;

    return new Date(exp * 1000 - EXPIRE_OFFSET) > new Date();
  }
  return false;
}

export function isStaffToken(token: string): boolean {
  if (!token) {
    return false;
  }

  const decodedToken = decodeToken(token);

  if (decodedToken && decodedToken.is_staff) {
    return decodedToken.is_staff === 'true';
  }
  return false;
}

export function decodeToken(token: string): TokenPayload | null {
  if (!token) {
    return null;
  }

  return jwtDecode(token);
}

export function parseCookies(req?: IncomingMessage, options = {}) {
  return parse(req ? req.headers.cookie || '' : document.cookie, options);
}

export const getSmsCode = async (msisdn: string): Promise<SmsResponse> => {
  const res = await axios.post(`${publicRuntimeConfig.AUTHENTICATION_SERVER_URL}/api/otp/sendsms`, {
    msisdn,
  });

  return res.data;
};

export function parseToken(req?: IncomingMessage, options = {}) {
  const { token } = parseCookies(req, options);

  return {
    token,
  };
}

export function getUserFromToken(token: string): User {
  const profileName = decodeToken(token)?.profile_name
    ? decodeToken(token)?.profile_name
    : decodeToken(token)?.name;
  const profileSsn = decodeToken(token)?.profile_ssn
    ? decodeToken(token)?.profile_ssn
    : decodeToken(token)?.ssn;

  const isMainProfile = decodeToken(token)?.profile_ssn === decodeToken(token)?.ssn;
  return {
    ssn: decodeToken(token)?.ssn || '',
    name: decodeToken(token)?.name || '',
    email: decodeToken(token)?.email || '',
    profileName: profileName,
    profileSsn: profileSsn,
    msisdn: decodeToken(token)?.msisdn || '',
    isStaff: decodeToken(token)?.is_staff === 'true',
    customerId: decodeToken(token)?.customer_id || '',
    isMainProfile,
  };
}
