import {types} from '@babel/core';
import {store} from '@redux/store';
import {Any} from '@react-spring/types';
import {type} from 'os';
import {Platform} from 'react-native';

import getUserAgent from './userAgent';

import {
  AccountName,
  EMail,
  Password,
  XAuthorization,
  UserId,
  Username,
  verifyId,
  WebSocketSessionId,
  XToken,
} from '../configs/types';
import MyUserManager from '@user/MyUserManager';

export const apiPath = {
  backend: {
    prefix: 'https://alpha-api.clickandjoin.umbach.dev/v1',
  },
};

export enum apiBackendRequest {
  REGISTER_STEP_1 = '/admin/users/email',
  REGISTER_RESEND_MAIL = '/admin/users/email/resend',
  REGISTER_STEP_2 = '/verify/email/:xToken/:verifyId',
  REGISTER_STEP_FINAL = '/admin/users',
  REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK = '/admin/users/validation/accountname',
  LOGIN = '/user',
  GET_USER_PROFILE = '/users/:userId',
  APP_START = '/appstart',
}

type requestGET = {[key: string]: string};
type requestHeader = {[key: string]: string | undefined};

export interface defaultRequest {
  status?: 200 | 400 | 422 | 500;
  error?: string;
  requestGET?: requestGET;
  requestHeader?: requestHeader;
}

interface REGISTER_STEP_1 extends defaultRequest {
  path: apiBackendRequest.REGISTER_STEP_1;

  request: {
    Email: EMail;
  };
  response: {
    XToken: XToken | undefined;
  };
}
interface REGISTER_RESEND_MAIL extends defaultRequest {
  path: apiBackendRequest.REGISTER_RESEND_MAIL;
  requestHeader: {
    'X-Token': XToken | undefined;
  };
  request: {
    Email: EMail;
  };
  response: {
    XToken: XToken | undefined;
  };
}

interface REGISTER_STEP_2 extends defaultRequest {
  path: apiBackendRequest.REGISTER_STEP_2;

  requestGET: {
    ':xToken': XToken;
    ':verifyId': verifyId;
  };
}

interface REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK extends defaultRequest {
  path: apiBackendRequest.REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK;

  request: {
    AccountName: AccountName;
  };
  // response: {
  //   XToken: XToken | undefined;
  //};
}

interface REGISTER_STEP_FINAL extends defaultRequest {
  path: apiBackendRequest.REGISTER_STEP_FINAL;
  requestHeader: {
    'X-Token': XToken;
  };
  request: {
    AccountName: AccountName;
    Username: Username;
    Password: Password;
  };
  response?: {
    XAuthorization: XAuthorization;
    UserId: UserId;
    WebSocketSessionId: WebSocketSessionId;
  };
}

interface LOGIN extends defaultRequest {
  path: apiBackendRequest.LOGIN;
  request: {
    Email: EMail;
    Password: Password;
  };
  response?: {
    XAuthorization: XAuthorization;
    UserId: UserId;
    WebSocketSessionId: WebSocketSessionId;
  };
}

interface GET_USER_PROFILE extends defaultRequest {
  path: apiBackendRequest.GET_USER_PROFILE;

  requestGET: {
    ':userId': UserId;
  };
  response: {
    AccountName: AccountName;
    Username: Username;
    Description: string;
    FollowersCount: number;
    FollowingCount: number;
    XpLevel: number;
    XpPoints: number;
    AvatarUrl: string;
  };
}

interface APP_START extends defaultRequest {
  path: apiBackendRequest.APP_START;

  response: {
    TokenValid: boolean;
    AccountName: AccountName;
    Username: Username;
    Description: string;
    FollowersCount: number;
    FollowingCount: number;
    XpLevel: number;
    XpPoints: number;
    AccountStatus: number;
    AvatarUrl: string;
    Events: any;
  };
}

type FetchTypes =
  | REGISTER_STEP_1
  | REGISTER_RESEND_MAIL
  | REGISTER_STEP_2
  | REGISTER_STEP_FINAL
  | REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK
  | LOGIN
  | GET_USER_PROFILE
  | APP_START;

function isA(obj: any): obj is REGISTER_STEP_1 {
  return obj.request !== undefined;
}

export function makeRequest<T1 extends FetchTypes>(type: T1): Promise<T1> {
  let makeRequestObj: any = type;

  let path = type.path.toString();

  if (type.requestGET !== undefined) {
    for (let key in type.requestGET) {
      path = path.replaceAll(key, (type.requestGET as requestGET)[key]);
    }
  }

  // Simple POST request with a JSON body using fetch

  let headers: HeadersInit_ = {
    'Content-Type': 'application/json',
    'X-App-Version': store
      .getState()
      .nonSaveVariables.currentAppVersion.toString(),
    'X-Language': store.getState().appVariables.lang.details.langCode,
  };

  if (type.requestHeader !== undefined) {
    for (let key in type.requestHeader) {
      let val = (type.requestHeader as requestHeader)[key];

      if (val !== undefined) headers[key] = val;
    }
  }

  if (Platform.OS === 'android' || Platform.OS === 'ios')
    headers['User-Agent'] = getUserAgent();

  const SessionId = MyUserManager.getSessionId();
  if (SessionId !== undefined) headers['X-Authorization'] = SessionId;

  const requestOptions: RequestInit = {
    method: makeRequestObj.request !== undefined ? 'POST' : 'GET',

    headers,
    body:
      makeRequestObj.request !== undefined
        ? JSON.stringify(makeRequestObj.request)
        : undefined,
  };

  return new Promise<T1>((resolve, reject) => {
    fetch(apiPath.backend.prefix + path, requestOptions)
      .then(response => {
        makeRequestObj.status = response.status;

        if (makeRequestObj.response === undefined) return {};

        return response.json();
      })
      .then(data => {
        makeRequestObj.response = data;

        //console.log(makeRequestObj);
        if (makeRequestObj.status !== 200) reject(makeRequestObj);
        else resolve(makeRequestObj);
      })
      .catch(error => {
        //console.error(error, makeRequestObj);
        makeRequestObj.error = error;
        reject(makeRequestObj);
      });
  });
}
