export function getHandlers()

in frontend/src/apiMocks/handlers.ts [18:555]


export function getHandlers(
  defaultMockId: null | (typeof mockIds)[number] = null,
): HttpHandler[] {
  const handlers: HttpHandler[] = [];

  const getMockId = (req: Request): (typeof mockIds)[number] | null => {
    const authHeader = req.headers.get("Authorization");
    if (typeof authHeader !== "string") {
      return defaultMockId;
    }

    const token = authHeader.split(" ")[1];
    return mockIds.find((mockId) => mockId === token) ?? defaultMockId;
  };

  const addGetHandler: (...args: Parameters<typeof http.get>) => void = (
    path,
    resolver,
  ) => {
    handlers.push(http.get(path, resolver));
    handlers.push(http.get(`http://127.0.0.1:8000${path}`, resolver));
  };
  const addPatchHandler: (...args: Parameters<typeof http.patch>) => void = (
    path,
    resolver,
  ) => {
    handlers.push(http.patch(path, resolver));
    handlers.push(http.patch(`http://127.0.0.1:8000${path}`, resolver));
  };
  const addPostHandler: (...args: Parameters<typeof http.post>) => void = (
    path,
    resolver,
  ) => {
    handlers.push(http.post(path, resolver));
    handlers.push(http.post(`http://127.0.0.1:8000${path}`, resolver));
  };
  const addDeleteHandler: (...args: Parameters<typeof http.delete>) => void = (
    path,
    resolver,
  ) => {
    handlers.push(http.delete(path, resolver));
    handlers.push(http.delete(`http://127.0.0.1:8000${path}`, resolver));
  };

  addGetHandler("/accounts/logout", (_info) => {
    return HttpResponse.text(null, { status: 200 });
  });

  addGetHandler("/api/v1/runtime_data", (_info) => {
    return HttpResponse.json(mockedRuntimeData, { status: 200 });
  });

  addGetHandler("/api/v1/users/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 401 });
    }

    return HttpResponse.json([mockedUsers[mockId]], { status: 200 });
  });

  addGetHandler("/accounts/profile/subdomain", (info) => {
    const requestUrl = new URL(info.request.url);
    if (requestUrl.searchParams.get("subdomain") === "not-available") {
      return HttpResponse.json(
        {
          message: "error-subdomain-not-available",
          subdomain: "not-available",
        },
        { status: 400 },
      );
    }

    return HttpResponse.json({ available: true }, { status: 200 });
  });

  addPostHandler("/accounts/profile/subdomain", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const body = await info.request.text();
    const data = new URLSearchParams(body);
    mockedProfiles[mockId] = {
      ...mockedProfiles[mockId],
      subdomain: data.get("subdomain"),
    };
    return HttpResponse.text(null, { status: 200 });
  });

  addGetHandler("/api/v1/profiles/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 401 });
    }

    return HttpResponse.json([mockedProfiles[mockId]], { status: 200 });
  });

  addPatchHandler("/api/v1/profiles/:id/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const body = (await info.request.json()) as Partial<ProfileData>;
    mockedProfiles[mockId] = {
      ...mockedProfiles[mockId],
      ...body,
    };
    return HttpResponse.text(null, { status: 200 });
  });

  addGetHandler("/api/v1/relayaddresses/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    return HttpResponse.json(mockedRelayaddresses[mockId], { status: 200 });
  });

  addPostHandler("/api/v1/relayaddresses/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const body = (await info.request.json()) as Partial<RandomAliasData>;
    const ownAddresses = mockedRelayaddresses[mockId];
    const id = (ownAddresses[ownAddresses.length - 1]?.id ?? -1) + 1;
    ownAddresses.push({
      address: body.address ?? `random_${id}`,
      full_address: body.address ?? `random_${id}` + "@mozmail.com",
      created_at: new Date(Date.now()).toISOString(),
      description: "",
      domain: 1,
      enabled: true,
      block_list_emails: body.block_list_emails ?? false,
      block_level_one_trackers: body.block_level_one_trackers ?? false,
      generated_for: "",
      id: id,
      last_modified_at: new Date(Date.now()).toISOString(),
      last_used_at: new Date(Date.now()).toISOString(),
      num_blocked: 0,
      num_replied: 0,
      num_forwarded: 0,
      num_spam: 0,
      num_level_one_trackers_blocked: 0,
      mask_type: "random",
      used_on: "",
    });
    return HttpResponse.text(null, { status: 200 });
  });

  addPatchHandler("/api/v1/relayaddresses/:id/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const ownAddresses = mockedRelayaddresses[mockId];
    const index = ownAddresses.findIndex(
      (address) => address.id === Number.parseInt(info.params.id as string, 10),
    );
    if (index === -1) {
      return HttpResponse.text(null, { status: 404 });
    }
    const body = (await info.request.json()) as Partial<RandomAliasData>;
    ownAddresses[index] = {
      ...ownAddresses[index],
      ...body,
    };
    return HttpResponse.text(null, { status: 200 });
  });

  addDeleteHandler("/api/v1/relayaddresses/:id/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const ownAddresses = mockedRelayaddresses[mockId];
    const index = ownAddresses.findIndex(
      (address) => address.id === Number.parseInt(info.params.id as string, 10),
    );
    if (index === -1) {
      return HttpResponse.text(null, { status: 404 });
    }

    ownAddresses.splice(index, 1);
    return HttpResponse.text(null, { status: 200 });
  });

  addGetHandler("/api/v1/domainaddresses/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    return HttpResponse.json(mockedDomainaddresses[mockId], { status: 200 });
  });

  addPostHandler("/api/v1/domainaddresses/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const body = (await info.request.json()) as Partial<CustomAliasData>;
    const ownAddresses = mockedDomainaddresses[mockId];
    const id = (ownAddresses[ownAddresses.length - 1]?.id ?? -1) + 1;
    ownAddresses.push({
      address: body.address ?? `custom_alias_${id}`,
      full_address:
        body.address ?? `custom_alias_${id}` + "@mydomain.mozmail.com",
      created_at: new Date(Date.now()).toISOString(),
      description: "",
      domain: 2,
      enabled: true,
      block_list_emails: body.block_list_emails ?? false,
      block_level_one_trackers: body.block_level_one_trackers ?? false,
      id: id,
      last_modified_at: new Date(Date.now()).toISOString(),
      last_used_at: new Date(Date.now()).toISOString(),
      num_blocked: 0,
      num_replied: 0,
      num_forwarded: 0,
      num_spam: 0,
      num_level_one_trackers_blocked: 0,
      used_on: "",
      mask_type: "custom",
    });
    return HttpResponse.text(null, { status: 200 });
  });

  addPatchHandler("/api/v1/domainaddresses/:id/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const ownAddresses = mockedDomainaddresses[mockId];
    const index = ownAddresses.findIndex(
      (address) => address.id === Number.parseInt(info.params.id as string, 10),
    );
    if (index === -1) {
      return HttpResponse.text(null, { status: 404 });
    }

    const body = (await info.request.json()) as Partial<CustomAliasData>;
    ownAddresses[index] = {
      ...ownAddresses[index],
      ...body,
    };
    return HttpResponse.text(null, { status: 200 });
  });

  addDeleteHandler("/api/v1/domainaddresses/:id/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const ownAddresses = mockedDomainaddresses[mockId];
    const index = ownAddresses.findIndex(
      (address) => address.id === Number.parseInt(info.params.id as string, 10),
    );
    if (index === -1) {
      return HttpResponse.text(null, { status: 404 });
    }

    ownAddresses.splice(index, 1);
    return HttpResponse.text(null, { status: 200 });
  });

  addGetHandler("/api/v1/realphone/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    return HttpResponse.json(mockedRealphones[mockId], { status: 200 });
  });
  addPostHandler("/api/v1/realphone/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    type NewNumber = Pick<UnverifiedPhone, "number">;
    type Verification = Pick<VerifiedPhone, "number" | "verification_code">;
    const body = (await info.request.json()) as NewNumber | Verification;

    const isVerification = (
      request: NewNumber | Verification,
    ): request is Verification => {
      return typeof (request as Verification).verification_code === "string";
    };

    if (isVerification(body)) {
      mockedRealphones[mockId] = mockedRealphones[mockId].map((realPhone) => {
        if (realPhone.number !== body.number) {
          return realPhone;
        }

        return {
          ...realPhone,
          verified: true,
          verified_date: new Date().toISOString(),
        } as VerifiedPhone;
      });
    } else {
      // Pretend the verification was sent 4:40m ago,
      // so expiry can easily be tested:
      const sentDate = Date.now() - 5 * 60 * 1000 + 20 * 1000;
      const newVerificationPendingPhone: UnverifiedPhone = {
        id: mockedRealphones[mockId].length,
        number: body.number,
        verification_code: "123456",
        verification_sent_date: new Date(sentDate).toISOString(),
        verified: false,
        verified_date: null,
        country_code: "US",
      };
      mockedRealphones[mockId].push(newVerificationPendingPhone);
    }
    return HttpResponse.text(null, { status: 200 });
  });
  addGetHandler("/api/v1/realphone/:id/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }
    const relevantRealPhone = mockedRealphones[mockId].find(
      (realPhone) =>
        realPhone.id === Number.parseInt(info.params.id as string, 10),
    );
    return HttpResponse.json(relevantRealPhone, { status: 200 });
  });
  addPatchHandler("/api/v1/realphone/:id/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }
    type Verification = Pick<VerifiedPhone, "number" | "verification_code">;
    const body = (await info.request.json()) as Verification;
    mockedRealphones[mockId] = mockedRealphones[mockId].map((realPhone) => {
      if (
        realPhone.number !== body.number ||
        realPhone.id !== Number.parseInt(info.params.id as string, 10)
      ) {
        return realPhone;
      }

      return {
        ...realPhone,
        verified: true,
        verified_date: new Date().toISOString(),
      } as VerifiedPhone;
    });
    return HttpResponse.text(null, { status: 200 });
  });

  addGetHandler("/api/v1/relaynumber/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    return HttpResponse.json(mockedRelaynumbers[mockId], { status: 200 });
  });
  addPostHandler("/api/v1/relaynumber/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const body = (await info.request.json()) as Pick<RelayNumber, "number">;

    const newRelaynumber: RelayNumber = {
      number: body.number,
      location: "Unhošť",
      country_code: "US",
      enabled: true,
      id: mockedRelaynumbers[mockId].length,
      remaining_texts: 74,
      remaining_minutes: 49,
      calls_forwarded: 3,
      calls_blocked: 1,
      texts_forwarded: 17,
      texts_blocked: 5,
      calls_and_texts_forwarded: 20,
      calls_and_texts_blocked: 6,
    };
    mockedRelaynumbers[mockId].push(newRelaynumber);
    return HttpResponse.json(newRelaynumber, { status: 200 });
  });

  // TODO: Move to phone API hook:
  type TwilioPhone = {
    phone_number: string;
    locality: string;
    // See convert_twilio_numbers_to_dict in phones/models.py for other fields.
  };

  addGetHandler("/api/v1/relaynumber/search/", (info) => {
    const requestUrl = new URL(info.request.url);
    const location = requestUrl.searchParams.get("location");
    const areaCode = requestUrl.searchParams.get("area_code");

    if (location === null && areaCode === null) {
      return HttpResponse.json({}, { status: 404 });
    }

    const mockedSearchResults: TwilioPhone[] = Array.from(new Array(10), () => {
      const numberEnd = Math.random().toString().substring(4, 7);
      return {
        phone_number: `+1${areaCode ?? "808"}${numberEnd}`,
        locality: location ?? "Hilo",
      };
    });

    return HttpResponse.json(mockedSearchResults, { status: 200 });
  });

  addGetHandler("/api/v1/relaynumber/suggestions/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const userNumber = mockedRealphones[mockId][0]?.number ?? "+18089251571";

    const mockedSuggestions = {
      same_prefix_options: Array.from(new Array(10), (_, index) => {
        const suffixNum =
          Number.parseInt(userNumber.substring(10), 10) + 1 + index;
        const suggestedNumber: TwilioPhone = {
          phone_number: userNumber.substring(0, 10) + suffixNum.toString(),
          locality: "Hilo",
        };
        return suggestedNumber;
      }),
      other_areas_options: Array.from(new Array(10), () => {
        const areaCode = Math.random().toString().substring(2, 5);
        const suggestedNumber: TwilioPhone = {
          phone_number:
            userNumber.substring(0, 2) + areaCode + userNumber.substring(5),
          locality: "Hilo",
        };
        return suggestedNumber;
      }),
      same_area_options: Array.from(new Array(10), () => {
        const suffixNum = Math.random().toString().substring(2, 9);
        const suggestedNumber: TwilioPhone = {
          phone_number: userNumber.substring(0, 5) + suffixNum.toString(),
          locality: "Hilo",
        };
        return suggestedNumber;
      }),
      random_options: Array.from(new Array(10), () => {
        const suffixNum = Math.random().toString().substring(2, 12);
        const randomNumber: TwilioPhone = {
          phone_number: userNumber.substring(0, 2) + suffixNum.toString(),
          locality: "Hilo",
        };
        return randomNumber;
      }),
    };

    return HttpResponse.json(mockedSuggestions, { status: 200 });
  });

  addGetHandler("/api/v1/relaynumber/:id/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    return HttpResponse.json(
      mockedRelaynumbers[mockId][Number.parseInt(info.params.id as string, 10)],
      { status: 200 },
    );
  });

  addPatchHandler("/api/v1/relaynumber/:id/", async (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    const ownRelayNumbers = mockedRelaynumbers[mockId];
    const index = ownRelayNumbers.findIndex(
      (relayNumber) =>
        relayNumber.id === Number.parseInt(info.params.id as string, 10),
    );
    if (index === -1) {
      return HttpResponse.text(null, { status: 404 });
    }

    const body = (await info.request.json()) as Partial<RelayNumber>;
    ownRelayNumbers[index] = {
      ...ownRelayNumbers[index],
      ...body,
    };
    return HttpResponse.text(null, { status: 200 });
  });

  addGetHandler("/api/v1/inboundcontact/", (info) => {
    const mockId = getMockId(info.request);
    if (mockId === null) {
      return HttpResponse.text(null, { status: 400 });
    }

    return HttpResponse.json(mockedInboundContacts[mockId], { status: 200 });
  });

  handlers.push(
    http.post("https://basket-mock.com/news/subscribe/", (_info) => {
      return HttpResponse.json({ status: "ok" }, { status: 200 });
    }),
  );
  handlers.push(
    http.get("https://accounts.firefox.com/metrics-flow", (_info) => {
      return HttpResponse.json(
        {
          flowId: "mock-flow-id",
          flowBeginTime: Date.now(),
        },
        { status: 200 },
      );
    }),
  );

  return handlers;
}