/**
 * @file SearchParamBuilder.ts
 * Type-safe builder for constructing search parameter strings
 * Pure function, no side effects
 */

import { SearchParamValidators } from './SearchParamValidators';

export class SearchParamBuilder {
  private params: URLSearchParams;

  constructor() {
    this.params = new URLSearchParams();
  }

  // Auth params
  returnTo(value: string | null): this {
    if (value !== null) {
      const validation = SearchParamValidators.validateReturnTo(value);
      if (!validation.isValid) {
        throw new Error(`Invalid returnTo: ${validation.errors.join(', ')}`);
      }
      this.params.set('returnTo', value);
    }
    return this;
  }

  token(value: string | null): this {
    if (value !== null) {
      const validation = SearchParamValidators.validateToken(value);
      if (!validation.isValid) {
        throw new Error(`Invalid token: ${validation.errors.join(', ')}`);
      }
      this.params.set('token', value);
    }
    return this;
  }

  email(value: string | null): this {
    if (value !== null) {
      const validation = SearchParamValidators.validateEmail(value);
      if (!validation.isValid) {
        throw new Error(`Invalid email: ${validation.errors.join(', ')}`);
      }
      this.params.set('email', value);
    }
    return this;
  }

  error(value: string | null): this {
    if (value !== null) {
      this.params.set('error', value);
    }
    return this;
  }

  message(value: string | null): this {
    if (value !== null) {
      this.params.set('message', value);
    }
    return this;
  }

  // Sponsor params
  campaignType(value: string | null): this {
    if (value !== null) {
      const validation = SearchParamValidators.validateCampaignType(value);
      if (!validation.isValid) {
        throw new Error(`Invalid campaign type: ${validation.errors.join(', ')}`);
      }
      this.params.set('type', value);
    }
    return this;
  }

  campaignId(value: string | null): this {
    if (value !== null) {
      this.params.set('campaignId', value);
    }
    return this;
  }

  // Pagination params
  page(value: number | null): this {
    if (value !== null) {
      const validation = SearchParamValidators.validatePage(value.toString());
      if (!validation.isValid) {
        throw new Error(`Invalid page: ${validation.errors.join(', ')}`);
      }
      this.params.set('page', value.toString());
    }
    return this;
  }

  limit(value: number | null): this {
    if (value !== null) {
      const validation = SearchParamValidators.validateLimit(value.toString());
      if (!validation.isValid) {
        throw new Error(`Invalid limit: ${validation.errors.join(', ')}`);
      }
      this.params.set('limit', value.toString());
    }
    return this;
  }

  offset(value: number | null): this {
    if (value !== null) {
      this.params.set('offset', value.toString());
    }
    return this;
  }

  // Sorting params
  sortBy(value: string | null): this {
    if (value !== null) {
      this.params.set('sortBy', value);
    }
    return this;
  }

  order(value: string | null): this {
    if (value !== null) {
      const validation = SearchParamValidators.validateOrder(value);
      if (!validation.isValid) {
        throw new Error(`Invalid order: ${validation.errors.join(', ')}`);
      }
      this.params.set('order', value);
    }
    return this;
  }

  // Filtering params
  status(value: string | null): this {
    if (value !== null) {
      this.params.set('status', value);
    }
    return this;
  }

  role(value: string | null): this {
    if (value !== null) {
      this.params.set('role', value);
    }
    return this;
  }

  tier(value: string | null): this {
    if (value !== null) {
      this.params.set('tier', value);
    }
    return this;
  }

  // Wizard params
  step(value: string | null): this {
    if (value !== null) {
      this.params.set('step', value);
    }
    return this;
  }

  // Generic setter
  set(key: string, value: string | null): this {
    if (value !== null) {
      this.params.set(key, value);
    }
    return this;
  }

  // Build the query string
  build(): string {
    const queryString = this.params.toString();
    return queryString ? `?${queryString}` : '';
  }

  // Static factory methods for common scenarios
  static auth(returnTo?: string | null, token?: string | null, email?: string | null): string {
    const builder = new SearchParamBuilder();
    if (returnTo !== undefined) builder.returnTo(returnTo);
    if (token !== undefined) builder.token(token);
    if (email !== undefined) builder.email(email);
    return builder.build();
  }

  static pagination(page?: number | null, limit?: number | null): string {
    const builder = new SearchParamBuilder();
    if (page !== undefined) builder.page(page);
    if (limit !== undefined) builder.limit(limit);
    return builder.build();
  }

  static sorting(sortBy?: string | null, order?: string | null): string {
    const builder = new SearchParamBuilder();
    if (sortBy !== undefined) builder.sortBy(sortBy);
    if (order !== undefined) builder.order(order);
    return builder.build();
  }

  static sponsorCampaign(type?: string | null, campaignId?: string | null): string {
    const builder = new SearchParamBuilder();
    if (type !== undefined) builder.campaignType(type);
    if (campaignId !== undefined) builder.campaignId(campaignId);
    return builder.build();
  }
}
