/**
 * Toolkit - Type Helpers
 * 
 * TypeScript utility types and helper functions.
 */

/**
 * Make specific properties optional
 */
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

/**
 * Make specific properties required
 */
export type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;

/**
 * Deep partial (makes all nested properties optional)
 */
export type DeepPartial<T> = T extends object
  ? { [P in keyof T]?: DeepPartial<T[P]> }
  : T;

/**
 * Extract keys of a certain type
 */
export type KeysOfType<T, U> = {
  [K in keyof T]: T[K] extends U ? K : never;
}[keyof T];

/**
 * Ensure all keys of a type are present
 */
export function ensureKeys<T extends Record<string, unknown>>(
  obj: Partial<T>,
  keys: (keyof T)[]
): obj is T {
  return keys.every(key => key in obj);
}

/**
 * Pick properties by value type
 */
export type PickByValue<T, V> = Pick<
  T,
  {
    [K in keyof T]: T[K] extends V ? K : never;
  }[keyof T]
>;

/**
 * Safely access nested property
 */
export function getNestedProperty<T>(
  obj: unknown,
  path: string,
  defaultValue?: T
): T | undefined {
  const keys = path.split(".");
  let current: any = obj;

  for (const key of keys) {
    if (current === null || current === undefined || typeof current !== "object") {
      return defaultValue;
    }
    current = current[key];
  }

  return current ?? defaultValue;
}

// ============================================================================
// Async State Management
// ============================================================================

/**
 * Generic async state type for handling loading/success/error states
 */
export type AsyncState<T, E = Error> =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: T }
  | { status: "error"; error: E };

/**
 * Create an idle state
 */
export function createIdleState<T, E = Error>(): AsyncState<T, E> {
  return { status: "idle" };
}

/**
 * Create a loading state
 */
export function createLoadingState<T, E = Error>(): AsyncState<T, E> {
  return { status: "loading" };
}

/**
 * Create a success state with data
 */
export function createSuccessState<T, E = Error>(data: T): AsyncState<T, E> {
  return { status: "success", data };
}

/**
 * Create an error state
 */
export function createErrorState<T, E = Error>(error: E): AsyncState<T, E> {
  return { status: "error", error };
}

/**
 * Type guard: check if state is idle
 */
export function isIdle<T, E>(
  state: AsyncState<T, E>
): state is { status: "idle" } {
  return state.status === "idle";
}

/**
 * Type guard: check if state is loading
 */
export function isLoading<T, E>(
  state: AsyncState<T, E>
): state is { status: "loading" } {
  return state.status === "loading";
}

/**
 * Type guard: check if state is success
 */
export function isSuccess<T, E>(
  state: AsyncState<T, E>
): state is { status: "success"; data: T } {
  return state.status === "success";
}

/**
 * Type guard: check if state is error
 */
export function isError<T, E>(
  state: AsyncState<T, E>
): state is { status: "error"; error: E } {
  return state.status === "error";
}

