/**
 * Try to get door info
 */

import { ServerlessEventObject, ServerlessFunctionSignature } from "@twilio-labs/serverless-runtime-types/types";
import { TwilioContext } from "../../../types/TwilioContext";
import { createDynaBridgeClient } from "../../../utils/ddb";
import { DoorStatus } from "../../../types/DoorStatus";
import { DoorConfigSchema, getDoorConfigID } from "../../../schema/DoorConfig";
import { getDoorAliasID } from "../../../schema/DoorAlias";
import { getLockStatusID, isLockOpen } from "../../../schema/LockStatus";
import { withMetrics } from "../../../common/DoormanHandler";
import { z } from "zod";
import { UserAgentHeader } from "../../../utils/blockUserAgent";
import { setResponseJson } from "../../../utils/responseUtils";
import { sanitizePhoneNumber } from "../../../utils/phoneUtils";
import { BaseEvent, destroySession, setSessionOnResponse } from "../../../common/SessionHandler";

export const InfoRequestSchema = z.object({
  door: z.string().optional(),
  buzzer: z.string().optional(),
})
  .partial()
  .refine(data => data.buzzer || data.door, 'Buzzer or door must be provided');

export type InfoRequest = z.infer<typeof InfoRequestSchema>;
export type InfoRequestTwilio = ServerlessEventObject<InfoRequest, UserAgentHeader> & BaseEvent;

export const InfoResponseSchema = DoorConfigSchema
  .omit({ PK: true, SK: true, pin: true })
  .extend({ door: z.string(), status: z.nativeEnum(DoorStatus), id: z.string() });

export type InfoResponse = z.infer<typeof InfoResponseSchema>;

export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequestTwilio> = withMetrics("info", async (context, event, callback, metricsRegistry) => {
  const response = new Twilio.Response();
  const req = InfoRequestSchema.parse(event);

  let door = req.door;
  const buzzer = sanitizePhoneNumber(req.buzzer);

  const db = createDynaBridgeClient(context);

  if (buzzer) {
    door = await db.entities.doorAlias.findById(getDoorAliasID(buzzer))
      .then(async (alias) => {
        if (!alias) {
          setResponseJson(response, 404, {
            msg: "This buzzer is not registered",
          });
          return undefined;
        }
        return alias.name;
      });
  }

  if (door) {
    const config = await db.entities.doorConfig.findById(getDoorConfigID(door));

    if (!config) {
      setResponseJson(response, 404, {
        msg: "This buzzer is not registered",
      });
    } else {
      const lock = await db.entities.lockStatus.findById(getLockStatusID(door));
      const status = isLockOpen(lock) ? DoorStatus.OPEN : DoorStatus.CLOSED;

      const body: InfoResponse = InfoResponseSchema.parse({
        ...config,
        id: door,
        door,
        status,
      });

      setResponseJson(response, 200, body);
    }
  }

  // destroy the internal client after
  // @ts-ignore
  db.ddbClient.destroy();

  // if (event.request.session) {
  //   console.log(event.request.session);
  //   await destroySession(response);
  // } else {
  //   await setSessionOnResponse(response, context, { someSecret: new Date() });
  // }


  return callback(null, response);
});