// Copyright 2025 Northern.tech AS
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
import type { Page } from '@playwright/test';

import { timeouts } from './constants.ts';

export const selectReleaseByName = async (page: Page, name: string) => {
  await page.getByRole('button', { name: 'Select software' }).click();
  await page.getByRole('textbox', { name: 'Search software name...' }).fill(name);
  await page.waitForTimeout(timeouts.default);
  return locateReleaseByName(page, name).click();
};

export const locateReleaseByName = (page: Page, name: string) => {
  const container = page.locator('#deployment-release-container');
  return container.getByText(name).first();
};

export const selectDeviceLimitInput = (page: Page, tier: string) => {
  const tierCheckbox = page.getByLabel(`${tier} devices`);
  const deviceInputContainer = page.locator('div').filter({ has: tierCheckbox }).last();
  return deviceInputContainer.getByLabel('Device limit');
};

export const triggerDeploymentCreation = async (page: Page, successCheck: Promise<any>) => {
  const creationButton = await page.getByRole('button', { name: /create deployment/i });
  await creationButton.scrollIntoViewIfNeeded();
  const deploymentWatcher = page.waitForResponse(
    async response =>
      response.url().match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i) &&
      response.status() === 200 &&
      response.request().method() === 'POST' &&
      (await response.json()).status === 'finished'
  );
  await creationButton.click();
  return Promise.any([successCheck, deploymentWatcher]);
};

export const poll = async <T>({
  callback,
  condition = null,
  delay = timeouts.oneSecond,
  maxAttempts = 5,
  message = 'timeout waiting for callback',
  attempt = 1
}: {
  attempt?: number;
  callback: () => Promise<T>;
  condition?: (value: T) => boolean | null;
  delay?: number;
  maxAttempts?: number;
  message?: string;
}): Promise<T> => {
  const res = await callback();
  if (condition && condition(res)) {
    return Promise.resolve(res);
  } else if (res) {
    return Promise.resolve(res);
  }
  if (attempt >= maxAttempts) {
    console.error(message);
    throw new Error(message);
  }
  await new Promise(resolve => setTimeout(resolve, delay));
  return poll({ callback, condition, maxAttempts, delay, message, attempt: attempt + 1 });
};
