//const client = require("../graphql-client/graphql-client").client;
const logger = require("../utils/logger");
const queries = require("../graphql-client/queries");
const client = require("../graphql-client/graphql-client").client;
const { pick, isNil } = require("lodash");
const { getClient } = require("../../libs/awsUtils");
const { JOB_DOCUMENT_FIELDS, getGlobalSearchQueryStringFields } = require("./os-search-config");

async function OpenSearchUpdateHandler(req, res) {
  try {
    const osClient = await getClient();

    if (req.body.event.op === "DELETE") {
      let response;
      response = await osClient.delete({
        id: req.body.event.data.old.id,
        index: req.body.table.name
      });
      res.status(200).json(response.body);
    } else {
      let document;

      switch (req.body.table.name) {
        case "jobs":
          document = pick(req.body.event.data.new, JOB_DOCUMENT_FIELDS);
          document.bodyshopid = req.body.event.data.new.shopid;
          break;
        case "vehicles":
          document = pick(req.body.event.data.new, [
            "id",
            "v_model_yr",
            "v_model_desc",
            "v_make_desc",
            "v_color",
            "v_vin",
            "plate_no"
          ]);
          document.bodyshopid = req.body.event.data.new.shopid;
          break;
        case "owners":
          document = pick(req.body.event.data.new, ["id", "ownr_fn", "ownr_ln", "ownr_co_nm", "ownr_ph1", "ownr_ph2"]);
          document.bodyshopid = req.body.event.data.new.shopid;
          break;
        case "bills": {
          const bill = await client.request(
            `query ADMIN_GET_BILL_BY_ID($billId: uuid!) {
            bills_by_pk(id: $billId) {
              id
              job {
                id
                ro_number
                shopid
              }
              vendor {
                id
                name
              }
            }
          }
          `,
            { billId: req.body.event.data.new.id }
          );
          document = {
            ...pick(req.body.event.data.new, [
              "id",
              "date",
              "exported",
              "exported_at",
              "invoice_number",
              "is_credit_memo",
              "total"
            ]),
            ...bill.bills_by_pk,
            bodyshopid: bill.bills_by_pk.job.shopid
          };
          break;
        }
        case "payments": {
          //Query to get the job and RO number

          const payment = await client.request(
            `query ADMIN_GET_PAYMENT_BY_ID($paymentId: uuid!) {
                payments_by_pk(id: $paymentId) {
                  id
                  job {
                    id
                    ro_number
                    shopid
                    ownerid
                    ownr_co_nm
                    ownr_fn
                    ownr_ln
                    owner {
                      id
                      ownr_co_nm
                      ownr_fn
                      ownr_ln
                    }
                  }
                }
              }              
            `,
            { paymentId: req.body.event.data.new.id }
          );
          document = {
            ...pick(req.body.event.data.new, [
              "id",
              "amount",
              "created_at",
              "date",
              "exportedat",
              "memo",
              "payer",
              "paymentnum",
              "transactionid",
              "type"
            ]),
            ...payment.payments_by_pk,
            bodyshopid: payment.payments_by_pk.job.shopid
          };
          break;
        }
      }
      const payload = {
        id: req.body.event.data.new.id,
        index: req.body.table.name,
        body: document
      };

      logger.log("os-handler", "DEBUG", null, null, {
        id: req.body.event.data.new.id,
        index: req.body.table.name,
        bodyshopid: payload.body.bodyshopid
        // body: document
      });

      const response = await osClient.index(payload);
      //console.log(response.body);
      res.status(200).json(response.body);
    }
  } catch (error) {
    // We don't want this spam message existing in development/test,
    if (process.env?.NODE_ENV !== "production" && error?.message === "Invalid URL") {
      return res.status(400).json(JSON.stringify(error));
    }

    logger.log("os-handler-error", "ERROR", null, null, {
      id: req.body.event.data.new.id,
      index: req.body.table.name,
      message: error.message,
      stack: error.stack
      // body: document
    });

    res.status(400).json(JSON.stringify(error));
  }
}

async function OpenSearchSearchHandler(req, res) {
  try {
    const { search, bodyshopid, index } = req.body;

    if (!req.user) {
      res.sendStatus(401);
      return;
    }

    logger.log("os-search", "DEBUG", req.user.email, null, {
      search,
      index,
      bodyshopid
    });

    const BearerToken = req.BearerToken;
    const client = req.userGraphQLClient;

    const assocs = await client.setHeaders({ Authorization: BearerToken }).request(queries.ACTIVE_SHOP_BY_USER, {
      user: req.user.email
    });

    if (assocs.associations.length === 0) {
      res.sendStatus(401);
      return;
    }

    const osClient = await getClient();

    const activeAssociation = assocs.associations[0];
    const bodyShopIdMatchOverride = isNil(process.env.BODY_SHOP_ID_MATCH_OVERRIDE)
      ? activeAssociation.shopid
      : process.env.BODY_SHOP_ID_MATCH_OVERRIDE;
    const isReynoldsEnabled = Boolean(activeAssociation.bodyshop?.rr_dealerid);

    const { body } = await osClient.search({
      ...(index ? { index } : { index: ["jobs", "vehicles", "owners", "bills", "payments"] }),
      body: {
        size: 100,
        query: {
          bool: {
            must: [
              {
                match: {
                  bodyshopid: bodyShopIdMatchOverride
                }
              },
              {
                bool: {
                  should: [
                    {
                      multi_match: {
                        query: search,
                        type: "cross_fields",
                        fields: ["*ownr_fn", "*ownr_ln"]
                      }
                    },
                    {
                      multi_match: {
                        query: search,
                        type: "most_fields",
                        fields: ["*v_model_yr", "*v_make_desc^2", "*v_model_desc^3"]
                      }
                    },
                    {
                      query_string: {
                        query: `*${search}*`,
                        // Weighted Fields
                        fields: [
                          ...getGlobalSearchQueryStringFields({ isReynoldsEnabled })
                          // "*"
                        ]
                      }
                    }
                  ],
                  minimum_should_match: 1
                }
              }
            ]
          }
        },
        sort: [
          {
            _score: {
              order: "desc"
            }
          }
        ]
      }
    });

    res.json(body);
  } catch (error) {
    //console.log(error);
    logger.log("os-search-error", "ERROR", req.user.email, null, {
      error: JSON.stringify(error)
    });
    res.status(400).json(error);
  }
}

exports.handler = OpenSearchUpdateHandler;
exports.search = OpenSearchSearchHandler;
