import {
  ORDER_TYPE,
  buildOrderConfigurations,
  normalizeOrderSelections,
  type OrderConfigurations,
  type OrderSelections,
  type OrderTypeValue,
} from "@customer-portal/domain/orders";

export interface CheckoutParamsSnapshot {
  orderType: OrderTypeValue;
  selections: OrderSelections;
  configuration?: OrderConfigurations | undefined;
  planReference: string | null;
  warnings: string[];
}

export class CheckoutParamsService {
  private static toRecord(params: URLSearchParams): Record<string, string> {
    const record: Record<string, string> = {};
    for (const [key, value] of params.entries()) {
      if (key !== "type") {
        record[key] = value;
      }
    }
    return record;
  }

  static resolveOrderType(params: URLSearchParams): OrderTypeValue {
    const typeParam = params.get("type");

    // Default to Internet if no type specified
    if (!typeParam) {
      return ORDER_TYPE.INTERNET;
    }

    // Case-insensitive match against valid order types
    const validTypes = Object.values(ORDER_TYPE) as string[];
    const matchedType = validTypes.find(type => type.toLowerCase() === typeParam.toLowerCase());

    if (matchedType) {
      return matchedType as OrderTypeValue;
    }

    throw new Error(`Unsupported order type: ${typeParam}`);
  }

  private static coalescePlanReference(selections: OrderSelections): string | null {
    const planSku = selections.planSku;
    if (typeof planSku === "string" && planSku.trim().length > 0) return planSku.trim();
    return null;
  }

  static buildSnapshot(params: URLSearchParams): CheckoutParamsSnapshot {
    const orderType = this.resolveOrderType(params);
    const rawRecord = this.toRecord(params);
    const warnings: string[] = [];

    let selections: OrderSelections;
    try {
      selections = normalizeOrderSelections(rawRecord);
    } catch (error) {
      warnings.push(
        error instanceof Error ? error.message : "Failed to normalize checkout selections"
      );
      selections = rawRecord as unknown as OrderSelections;
    }

    let configuration: OrderConfigurations | undefined;
    try {
      configuration = buildOrderConfigurations(selections);
    } catch (error) {
      warnings.push(
        error instanceof Error ? error.message : "Failed to derive order configuration"
      );
    }

    const planReference = this.coalescePlanReference(selections);

    return {
      orderType,
      selections,
      configuration,
      planReference,
      warnings,
    };
  }
}
