import { Result } from '@core/shared/domain/Result';
import type { CheckoutInfoDTO } from '../../../application/dto/CheckoutInfoDTO';
import { CheckoutPrice } from '../../../domain/value-objects/CheckoutPrice';
import { CheckoutState } from '../../../domain/value-objects/CheckoutState';
import { IRACING_SELECTORS } from './dom/RacingSelectors';

interface Page {
  locator(_selector: string): Locator;
}

interface Locator {
  first(): Locator;
  locator(_selector: string): Locator;
  getAttribute(name: string): Promise<string | null>;
  innerHTML(): Promise<string>;
  textContent(): Promise<string | null>;
}

export class CheckoutPriceExtractor {
  // Use the price action selector from IRACING_SELECTORS
  private readonly selector = IRACING_SELECTORS.BLOCKED_SELECTORS.priceAction;

  constructor(private readonly page: Page) {}

  async extractCheckoutInfo(): Promise<Result<CheckoutInfoDTO>> {
    try {
      // Prefer the explicit pill element which contains the price
      const pillLocator = this.page.locator('.label-pill, .label-inverse');
      const pillText = await pillLocator.first().textContent().catch(() => null);
 
      let price: CheckoutPrice | null = null;
      let state = CheckoutState.unknown();
      let buttonHtml = '';
 
      if (pillText) {
        // Parse price if possible
        try {
          price = CheckoutPrice.fromString(pillText.trim());
        } catch {
          price = null;
        }
 
        // Try to find the containing button and its classes/html
        // Primary: locate button via known selector that contains the pill
        const buttonLocator = this.page.locator(this.selector).first();
        let classes = await buttonLocator.getAttribute('class').catch(() => null);
        let html = await buttonLocator.innerHTML().catch(() => '');
 
        if (!classes) {
          // Fallback: find ancestor <a> of the pill (XPath)
          const ancestorButton = pillLocator.first().locator('xpath=ancestor::a[1]');
          classes = await ancestorButton.getAttribute('class').catch(() => null);
          html = await ancestorButton.innerHTML().catch(() => '');
        }
 
        if (classes) {
          state = CheckoutState.fromButtonClasses(classes);
          buttonHtml = html ?? '';
        }
      } else {
        // No pill found — attempt to read button directly (best-effort)
        const buttonLocator = this.page.locator(this.selector).first();
        const classes = await buttonLocator.getAttribute('class').catch(() => null);
        const html = await buttonLocator.innerHTML().catch(() => '');
 
        if (classes) {
          state = CheckoutState.fromButtonClasses(classes);
          buttonHtml = html ?? '';
        }
      }
 
      // Additional fallback: search the wizard-footer for any price text if pill was not present or parsing failed
      if (!price) {
        try {
          const footerLocator = this.page.locator('.wizard-footer, .modal-footer').first();
          const footerText = await footerLocator.textContent().catch(() => null);
          if (footerText) {
            const match = footerText.match(/\$\d+\.\d{2}/);
            if (match) {
              try {
                price = CheckoutPrice.fromString(match[0]);
              } catch {
                price = null;
              }
            }
          }
        } catch {
          // ignore footer parse errors
        }
      }
 
      return Result.ok({
        price,
        state,
        buttonHtml
      });
    } catch (error) {
      // On any unexpected error, return an "unknown" result (do not throw)
      return Result.ok({
        price: null,
        state: CheckoutState.unknown(),
        buttonHtml: ''
      });
    }
  }
}