/* eslint-disable @typescript-eslint/no-explicit-any */
/** biome-ignore-all lint/suspicious/noExplicitAny: reason 42 */

import type { Page } from '@playwright/test';
import type { Test } from '../types/Test.js';

declare module '@playwright/test' {
  interface Page {
    subject: SubjectType;
    get: <T>(ctor: new (page: Page) => T) => T;
  }
}

class Get {
  private _page: Page;
  constructor(page: Page) {
    this._page = page;
  }
  getSubject<T>(ctor: new (page: Page) => T): T {
    return new ctor(this._page);
  }
}

export type SubjectType = {
  none: unknown;
};

export class SubjectRegistry {
  private _test: Test;

  constructor(test: Test) {
    this._test = test.extend({
      page: async ({ page }, use) => {
        const getInstance = new Get(page);
        page.get = getInstance.getSubject.bind(getInstance);

        page.subject = new Proxy({} as SubjectType, {
          get: (target, prop: string | symbol) => {
            if (prop === 'then') return undefined;
            if (typeof prop === 'symbol') return (target as any)[prop];

            const paths: Record<string, string> = {
              none: ''
            };

            const path = paths[prop as string];
            if (!path) return undefined;

            return {
              // biome-ignore lint/suspicious/noThenProperty: must be thenable
              then: (onfulfilled: any) => {
                return import(path).then((m) => {
                  // eslint-disable-next-line @typescript-eslint/naming-convention
                  const SubjectClass = m[prop as string] || m.default;
                  if (!SubjectClass) throw new Error(`Class ${String(prop)} not found`);

                  const instance = page.get(SubjectClass);
                  return onfulfilled(instance);
                });
              }
            };
          }
        });

        await use(page);
      }
    });
  }

  get test() {
    return this._test;
  }
}
