/**
 * @file SearchParamParser.ts
 * Type-safe parser for search parameters from URL
 * Returns Result type for clean error handling
 */

import { Result } from '@/lib/contracts/Result';
import { SearchParamValidators } from './SearchParamValidators';

export interface ParsedAuthParams {
  returnTo?: string | null;
  token?: string | null;
  email?: string | null;
  error?: string | null;
  message?: string | null;
}

export interface ParsedSponsorParams {
  type?: string | null;
  campaignId?: string | null;
}

export interface ParsedPaginationParams {
  page?: number;
  limit?: number;
  offset?: number;
}

export interface ParsedSortingParams {
  sortBy?: string | null;
  order?: 'asc' | 'desc';
}

export interface ParsedFilterParams {
  status?: string | null;
  role?: string | null;
  tier?: string | null;
}

export interface ParsedWizardParams {
  step?: string | null;
}

export class SearchParamParser {
  private static getParam(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null, key: string): string | null {
    if (!params) {
      return null;
    }
    if (params instanceof URLSearchParams) {
      return params.get(key);
    }
    const value = params[key];
    if (Array.isArray(value)) {
      return value[0] ?? null;
    }
    return value ?? null;
  }

  // Parse auth parameters
  static parseAuth(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null): Result<ParsedAuthParams, string> {
    const errors: string[] = [];
    
    const returnTo = this.getParam(params, 'returnTo');
    if (returnTo !== null) {
      const validation = SearchParamValidators.validateReturnTo(returnTo);
      if (!validation.isValid) {
        errors.push(...validation.errors);
      }
    }

    const token = this.getParam(params, 'token');
    if (token !== null) {
      const validation = SearchParamValidators.validateToken(token);
      if (!validation.isValid) {
        errors.push(...validation.errors);
      }
    }

    const email = this.getParam(params, 'email');
    if (email !== null) {
      const validation = SearchParamValidators.validateEmail(email);
      if (!validation.isValid) {
        errors.push(...validation.errors);
      }
    }

    if (errors.length > 0) {
      return Result.err(errors.join(', '));
    }

    return Result.ok({
      returnTo: this.getParam(params, 'returnTo'),
      token: this.getParam(params, 'token'),
      email: this.getParam(params, 'email'),
      error: this.getParam(params, 'error'),
      message: this.getParam(params, 'message'),
    });
  }

  // Parse sponsor parameters
  static parseSponsor(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null): Result<ParsedSponsorParams, string> {
    const errors: string[] = [];
    
    const type = this.getParam(params, 'type');
    if (type !== null) {
      const validation = SearchParamValidators.validateCampaignType(type);
      if (!validation.isValid) {
        errors.push(...validation.errors);
      }
    }

    if (errors.length > 0) {
      return Result.err(errors.join(', '));
    }

    return Result.ok({
      type: this.getParam(params, 'type'),
      campaignId: this.getParam(params, 'campaignId'),
    });
  }

  // Parse pagination parameters
  static parsePagination(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null): Result<ParsedPaginationParams, string> {
    const result: ParsedPaginationParams = {};
    const errors: string[] = [];

    const page = this.getParam(params, 'page');
    if (page !== null) {
      const validation = SearchParamValidators.validatePage(page);
      if (!validation.isValid) {
        errors.push(...validation.errors);
      } else {
        result.page = parseInt(page);
      }
    }

    const limit = this.getParam(params, 'limit');
    if (limit !== null) {
      const validation = SearchParamValidators.validateLimit(limit);
      if (!validation.isValid) {
        errors.push(...validation.errors);
      } else {
        result.limit = parseInt(limit);
      }
    }

    const offset = this.getParam(params, 'offset');
    if (offset !== null) {
      const num = parseInt(offset);
      if (!isNaN(num)) {
        result.offset = num;
      }
    }

    if (errors.length > 0) {
      return Result.err(errors.join(', '));
    }

    return Result.ok(result);
  }

  // Parse sorting parameters
  static parseSorting(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null): Result<ParsedSortingParams, string> {
    const errors: string[] = [];
    
    const order = this.getParam(params, 'order');
    if (order !== null) {
      const validation = SearchParamValidators.validateOrder(order);
      if (!validation.isValid) {
        errors.push(...validation.errors);
      }
    }

    if (errors.length > 0) {
      return Result.err(errors.join(', '));
    }

    return Result.ok({
      sortBy: this.getParam(params, 'sortBy'),
      order: (this.getParam(params, 'order') as 'asc' | 'desc') || undefined,
    });
  }

  // Parse filter parameters
  static parseFilters(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null): Result<ParsedFilterParams, string> {
    return Result.ok({
      status: this.getParam(params, 'status'),
      role: this.getParam(params, 'role'),
      tier: this.getParam(params, 'tier'),
    });
  }

  // Parse wizard parameters
  static parseWizard(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null): Result<ParsedWizardParams, string> {
    return Result.ok({
      step: this.getParam(params, 'step'),
    });
  }

  // Parse all parameters at once
  static parseAll(params: URLSearchParams | Record<string, string | string[] | undefined> | undefined | null): Result<
    {
      auth: ParsedAuthParams;
      sponsor: ParsedSponsorParams;
      pagination: ParsedPaginationParams;
      sorting: ParsedSortingParams;
      filters: ParsedFilterParams;
    },
    string
  > {
    const authResult = this.parseAuth(params);
    if (authResult.isErr()) return Result.err(authResult.getError());

    const sponsorResult = this.parseSponsor(params);
    if (sponsorResult.isErr()) return Result.err(sponsorResult.getError());

    const paginationResult = this.parsePagination(params);
    if (paginationResult.isErr()) return Result.err(paginationResult.getError());

    const sortingResult = this.parseSorting(params);
    if (sortingResult.isErr()) return Result.err(sortingResult.getError());

    const filtersResult = this.parseFilters(params);

    return Result.ok({
      auth: authResult.unwrap(),
      sponsor: sponsorResult.unwrap(),
      pagination: paginationResult.unwrap(),
      sorting: sortingResult.unwrap(),
      filters: filtersResult.unwrap(),
    });
  }
}
