// Util functions for communicating with FreeAgent
// Not able to use Applet Library since it is not an iframe within the FreeAgent context

const createEntityMutation = `
mutation createEntity($entity: String!, $field_values: JSON!) {
  createEntity(entity: $entity, field_values: $field_values) {
    entity_value {
      id
      seq_id
      field_values
    }
  }
}`

const getTeamMembersQuery = `
query getTeamMembers($active: Boolean, $order: [[String]], $show_hidden_rows: Boolean) {
  getTeamMembers(active: $active, order: $order, show_hidden_rows: $show_hidden_rows) {
    agents {
      id
      full_name
      teamId
      email_address
      access_level
      status
      job_title
      roles {
        id
        name
        import
        export
        bulk_edit
        bulk_delete
        task_delete
        is_admin
      }
      subteams {
        id
        name
        description
      }
    }
  }
}`

const getFieldsQuery = `
query getFields($entity:String,$show_hidden:Boolean) {
  getFields(entity:$entity,show_hidden:$show_hidden){
    id
    name
    name_label
    main_type
    is_required
    is_visible
    is_unique
    default_value
    catalog_type_id
    reference_field_id
    reference_fa_entity_id
    reference_fa_entity_name
  }
}`

const getFieldItemsQuery = `
query getFieldItems($fa_field_config_id:String,$pattern:String,$limit:Int) {
  getFieldItems(fa_field_config_id:$fa_field_config_id,pattern:$pattern,limit:$limit){
    id
    name
    order
  }
}`

const listEntityValuesQuery = `
query listEntityValues($entity: String!, $fields: [String], $order: [[String]], $limit: Int, $offset: Int, $pattern: String, $filters: [Filter]) {
  listEntityValues(entity: $entity, fields: $fields, order: $order, limit: $limit, offset: $offset, pattern: $pattern, filters: $filters) {
    count
    entity_values {
      id
      seq_id
      field_values
    }
  }
}`
const resolveFieldConfigTransportIdQuery =
  `query resolveFieldConfigTransportId($transport_id: String!) {
  resolveFieldConfigTransportId(transport_id: $transport_id) {
    id
  }
}`

const resolveCatalogTransportIdQuery =
  `query resolveCatalogTransportId($transport_id: String!) {
  resolveCatalogTransportId(transport_id: $transport_id) {
    id
    catalog_type_id
  }
}`

const resolveCatalogTypeTransportIdQuery =
  `query resolveCatalogTypeTransportId($transport_id: String!) {
  resolveCatalogTypeTransportId(transport_id: $transport_id) {
    id
    catalogs
  }
}`

const profileToContactMap = {
  "phone": "work_phone",
  "email": "work_email",
  "twitter": "twitter",
  "linkedin": "linkedin"
}

// change to correct environment
const faURL = "https://freeagent.network/"



// Resolves transport id
function resolveTID(tid, type) {
  const variables = {
    "transport_id": tid
  }

  let operationName = ''
  let query = null
  if (type === "catalog") {
    operationName = 'resolveCatalogTransportId';
    query = resolveCatalogTransportIdQuery;
  }
  else if (type === "field") {
    operationName = 'resolveFieldConfigTransportId';
    query = resolveFieldConfigTransportIdQuery;
  }
  else if (type === "catalog_type") {
    operationName = 'resolveCatalogTypeTransportId';
    query = resolveCatalogTypeTransportIdQuery;
  }
  const body = JSON.stringify({
    operationName,
    query,
    variables
  })
  return faGraphQLRequest(body);

}
function queryChoiceListValues(choiceListID) {
  const variables = {
    "fa_field_config_id": choiceListID,
    "pattern": "",
  }
  const body = JSON.stringify({
    operationName: 'getFieldItems',
    query: getFieldItemsQuery,
    variables
  })
  return faGraphQLRequest(body);
}
function queryFAContactFields() {
  const variables = {
    "entity": "contact",
    "show_hidden": false
  }
  const body = JSON.stringify({
    operationName: 'getFields',
    query: getFieldsQuery,
    variables
  })
  return faGraphQLRequest(body);
}

function queryFAUsers() {
  const variables = {
    "active": true,
    "order": [["full_name", "ASC"]],
    "show_hidden_rows": false
  }
  const body = JSON.stringify({
    operationName: 'getTeamMembers',
    query: getTeamMembersQuery,
    variables
  })
  return faGraphQLRequest(body);

}
function getFAToken(client_id, client_secret) {
  const options = {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    cache: "no-cache",

    body: JSON.stringify({
      grant_type: 'client_credentials',
      client_id,
      client_secret
    })
  };
  return fetch(faURL + "oauth/token", options)
    .then(res => res.json())
    .then(res => res.access_token);
}

function refreshFAToken(client_id, client_secret, refresh_token) {
  const options = {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      grant_type: 'refresh_token',
      client_id,
      client_secret,
      refresh_token
    })

  };
  return fetch(faURL + "oauth/token", options)
    .then(res => res.json())
}

function createContactFromProfile(profile, account_id) {
  const variables = {
    entity: "contact",
    field_values: {
      first_name: profile.firstName,
      last_name: profile.lastName,
      current_position: profile.jobTitle,
      lead_owner_id: profile.owner,
      logo_id: account_id,
      work_email: profile.email,
      work_phone: profile.phone,
      contact_field4: profile.list,
      contact_field14: profile.linkedInSalesNav,
      contact_field15: profile.id,
      lead_source_id: profile.source_id,
      contact_field0: profile.imgSrc
    }
  }

  const body = JSON.stringify({
    operationName: 'createEntity',
    query: createEntityMutation,
    variables
  })
  return faGraphQLRequest(body);
}


async function getFAContact(profile) {
  let queryVariables = {
    entity: "contact",
    fields: ["seq_id", "full_name"],
    filters: [
      {
        "field_name": "work_email",
        "operator": "is",
        "values": [profile.email]
      }
    ]
  }

  let queryBody = JSON.stringify({
    operationName: 'listEntityValues',
    query: listEntityValuesQuery,
    variables: queryVariables
  })
  const emailRes = await faGraphQLRequest(queryBody);
  if (emailRes?.data.listEntityValues.count === 0) {
    let queryVariables = {
      entity: "contact",
      fields: ["seq_id", "full_name"],
      filters: [
        {
          "field_name": "contact_field15",
          "operator": "is",
          "values": [profile.id]
        }
      ]
    }

    let queryBody = JSON.stringify({
      operationName: 'listEntityValues',
      query: listEntityValuesQuery,
      variables: queryVariables
    })
    return await faGraphQLRequest(queryBody);

  }
  else {
    return emailRes
  }
}
function createAccount(company) {
  const variables = {
    entity: "logo",
    field_values: {
      name: company.companyName,
      owner_id: company.owner,
      logo_field5: company.lisn,
      logo_field6: company.industry,
      hq_location: company.location,
      num_employees: company.numEmployees,
      revenue: company.revenue.replace(/[$ , .]/g, ''),
      website: company.website,
      logo_field0: company.imgSrc

    }
  }
  const body = JSON.stringify({
    operationName: 'createEntity',
    query: createEntityMutation,
    variables
  })
  return faGraphQLRequest(body);
}
async function getAccountByName(name) {
  let queryVariables = {
    entity: "logo",
    fields: ["seq_id", "name"],
    filters: [
      {
        "field_name": "name",
        "operator": "is",
        "values": [name]
      }
    ]
  }

  let queryBody = JSON.stringify({
    operationName: 'listEntityValues',
    query: listEntityValuesQuery,
    variables: queryVariables
  })

  const queryRes = await faGraphQLRequest(queryBody);
  // no account found
  if (!queryRes) return null;
  if (queryRes.data.listEntityValues.count === 0) {
    return -1;
  }
  else {
    return queryRes.data.listEntityValues.entity_values[0].id
  }
}
async function getAccount(name, url) {
  console.log(">> getting account");
  let queryVariables = {
    entity: "logo",
    fields: ["seq_id", "name"],
    filters: [
      {
        "field_name": "logo_field5",
        "operator": "is",
        "values": [url]
      }
    ]
  }

  let queryBody = JSON.stringify({
    operationName: 'listEntityValues',
    query: listEntityValuesQuery,
    variables: queryVariables
  })

  const queryRes = await faGraphQLRequest(queryBody);
  // no account found
  if (!queryRes) return null;
  if (queryRes.data.listEntityValues.count === 0) {
    return getAccountByName(name);
  }
  else {
    return queryRes.data.listEntityValues.entity_values[0].id
  }
}

function createAccountForProfile(profile) {
  const variables = {
    entity: "logo",
    field_values: {
      name: profile.companyName,
      owner_id: profile.owner,
      logo_field5: profile.companyLISN
    }
  }
  const body = JSON.stringify({
    operationName: 'createEntity',
    query: createEntityMutation,
    variables
  })
  return faGraphQLRequest(body);
}
function faGraphQLRequest(body) {
  return new Promise((resolve, reject) => {
    chrome.storage.sync.get(["faKeys", "access_token", "refresh_token"], async (res) => {
      if (res.access_token === "" || res.refresh_token === "") {
        reject("Not logged in");
        return;
      }
      const options = {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": "Bearer " + res.access_token
        },
        body,
      }
      let reqRes = await fetch(faURL + "api/graphql", options)
        .then(res => {
          let json = null
          if (res.status === 200) {
            json = res.json();
          }
          return {
            json,
            status: res.status
          }
        })
      if (reqRes.status === 401) {
        const refreshRes = await refreshFAToken(res.faKeys.client_id, res.faKeys.client_secret, res.refresh_token);
        chrome.storage.sync.set({
          access_token: refreshRes.access_token,
          refresh_token: refreshRes.refresh_token
        }, () => { console.log("refreshed token") })
        options.headers["Authorization"] = "Bearer " + refreshRes.access_token;
        reqRes = await fetch(faURL + "api/graphql", options)
          .then(res => {
            let json = null
            if (res.status === 200) {
              json = res.json();
            }
            return {
              json,
              status: res.status
            }
          })

      }
      if (reqRes.status === 200)
        resolve(reqRes.json);
      else
        reject(reqRes);

    });
  }).catch(res => {
    console.log(">> FA GraphQL error");
    console.log(res);
  });

}


