interface Cookie {
  name: string;
  value: string;
  domain: string;
  path: string;
  secure?: boolean;
  httpOnly?: boolean;
  sameSite?: 'Strict' | 'Lax' | 'None';
}

export class CookieConfiguration {
  private readonly cookie: Cookie;
  private readonly targetUrl: URL;

  constructor(cookie: Cookie, targetUrl: string) {
    this.cookie = cookie;
    try {
      this.targetUrl = new URL(targetUrl);
    } catch {
      throw new Error(`Invalid target URL: ${targetUrl}`);
    }

    this.validate();
  }

  private validate(): void {
    if (!this.isValidDomain()) {
      throw new Error(
        `Domain mismatch: Cookie domain "${this.cookie.domain}" is invalid for target "${this.targetUrl.hostname}"`
      );
    }

    if (!this.isValidPath()) {
      throw new Error(
        `Path not valid: Cookie path "${this.cookie.path}" is invalid for target path "${this.targetUrl.pathname}"`
      );
    }
  }

  private isValidDomain(): boolean {
    const targetHost = this.targetUrl.hostname;
    const cookieDomain = this.cookie.domain;

    // Empty domain is invalid
    if (!cookieDomain) {
      return false;
    }

    // Exact match
    if (cookieDomain === targetHost) {
      return true;
    }

    // Wildcard domain (e.g., ".iracing.com" matches "members-ng.iracing.com")
    if (cookieDomain.startsWith('.')) {
      const domainWithoutDot = cookieDomain.slice(1);
      return targetHost === domainWithoutDot || targetHost.endsWith('.' + domainWithoutDot);
    }

    // Subdomain compatibility: Allow cookies from related subdomains if they share the same base domain
    // Example: "members.iracing.com" → "members-ng.iracing.com" (both share "iracing.com")
    if (this.isSameBaseDomain(cookieDomain, targetHost)) {
      return true;
    }

    return false;
  }

  /**
   * Check if two domains share the same base domain (last 2 parts)
   * @example
   * isSameBaseDomain('members.iracing.com', 'members-ng.iracing.com') // true
   * isSameBaseDomain('example.com', 'iracing.com') // false
   */
  private isSameBaseDomain(domain1: string, domain2: string): boolean {
    const parts1 = domain1.split('.');
    const parts2 = domain2.split('.');

    // Need at least 2 parts (domain.tld) for valid comparison
    if (parts1.length < 2 || parts2.length < 2) {
      return false;
    }

    // Compare last 2 parts (e.g., "iracing.com")
    const base1 = parts1.slice(-2).join('.');
    const base2 = parts2.slice(-2).join('.');

    return base1 === base2;
  }

  private isValidPath(): boolean {
    // Empty path is invalid
    if (!this.cookie.path) {
      return false;
    }

    // Path must be prefix of target pathname
    return this.targetUrl.pathname.startsWith(this.cookie.path);
  }

  getValidatedCookie(): Cookie {
    return { ...this.cookie };
  }
}