/**
 * 响应式设计 Hook
 * 提供屏幕尺寸、断点、方向、平台检测等响应式信息
 */

import { useState, useEffect, useMemo, useCallback } from 'react';
import { Dimensions, ScaledSize, Platform } from 'react-native';

// ==================== 断点定义 ====================
export const BREAKPOINTS = {
  mobile: 0,      // 手机
  tablet: 768,    // 平板竖屏
  desktop: 1024,  // 平板横屏/桌面
  wide: 1440,     // 宽屏桌面
} as const;

export type BreakpointKey = keyof typeof BREAKPOINTS;
export type BreakpointValue = typeof BREAKPOINTS[BreakpointKey];

// ==================== 更细粒度的断点定义 ====================
export const FINE_BREAKPOINTS = {
  xs: 0,      // 超小屏手机
  sm: 375,    // 小屏手机 (iPhone SE, 小屏安卓)
  md: 414,    // 中屏手机 (iPhone Pro Max, 大屏安卓)
  lg: 768,    // 平板竖屏 / 大折叠屏手机展开
  xl: 1024,   // 平板横屏 / 小桌面
  '2xl': 1280, // 桌面
  '3xl': 1440, // 大桌面
  '4xl': 1920, // 超大屏
} as const;

export type FineBreakpointKey = keyof typeof FINE_BREAKPOINTS;

// ==================== 响应式值类型 ====================
export type ResponsiveValue<T> = T | Partial<Record<FineBreakpointKey, T>>;

// ==================== 返回值类型 ====================
export interface ResponsiveInfo {
  // 基础尺寸
  width: number;
  height: number;
  
  // 基础断点
  breakpoint: BreakpointKey;
  isMobile: boolean;
  isTablet: boolean;
  isDesktop: boolean;
  isWide: boolean;
  isWideScreen: boolean;
  
  // 细粒度断点
  fineBreakpoint: FineBreakpointKey;
  isXS: boolean;
  isSM: boolean;
  isMD: boolean;
  isLG: boolean;
  isXL: boolean;
  is2XL: boolean;
  is3XL: boolean;
  is4XL: boolean;
  
  // 方向
  orientation: 'portrait' | 'landscape';
  isPortrait: boolean;
  isLandscape: boolean;
  
  // 平台检测
  platform: {
    OS: 'ios' | 'android' | 'windows' | 'macos' | 'web';
    isWeb: boolean;
    isIOS: boolean;
    isAndroid: boolean;
    isNative: boolean;
  };
}

// ==================== 获取当前断点 ====================
function getBreakpoint(width: number): BreakpointKey {
  if (width >= BREAKPOINTS.wide) {
    return 'wide';
  }
  if (width >= BREAKPOINTS.desktop) {
    return 'desktop';
  }
  if (width >= BREAKPOINTS.tablet) {
    return 'tablet';
  }
  return 'mobile';
}

// ==================== 获取细粒度断点 ====================
function getFineBreakpoint(width: number): FineBreakpointKey {
  if (width >= FINE_BREAKPOINTS['4xl']) return '4xl';
  if (width >= FINE_BREAKPOINTS['3xl']) return '3xl';
  if (width >= FINE_BREAKPOINTS['2xl']) return '2xl';
  if (width >= FINE_BREAKPOINTS.xl) return 'xl';
  if (width >= FINE_BREAKPOINTS.lg) return 'lg';
  if (width >= FINE_BREAKPOINTS.md) return 'md';
  if (width >= FINE_BREAKPOINTS.sm) return 'sm';
  return 'xs';
}

// ==================== 获取屏幕方向 ====================
function getOrientation(width: number, height: number): 'portrait' | 'landscape' {
  return width > height ? 'landscape' : 'portrait';
}

// ==================== useWindowDimensions Hook ====================
/**
 * 获取窗口尺寸，支持屏幕旋转响应
 * 替代 Dimensions.get('window')，提供实时尺寸更新
 */
function useWindowDimensions(): ScaledSize {
  const [dimensions, setDimensions] = useState(() => Dimensions.get('window'));

  useEffect(() => {
    const subscription = Dimensions.addEventListener('change', ({ window }) => {
      setDimensions(window);
    });

    return () => {
      subscription.remove();
    };
  }, []);

  return dimensions;
}

// ==================== useResponsive Hook ====================
/**
 * 响应式设计 Hook
 * 提供屏幕尺寸、断点、方向、平台检测等响应式信息
 * 
 * @returns ResponsiveInfo 响应式信息对象
 * 
 * @example
 * const { 
 *   width, height, 
 *   breakpoint, isMobile, isTablet, isDesktop, isWide,
 *   fineBreakpoint, isXS, isSM, isMD, isLG, isXL,
 *   orientation, isPortrait, isLandscape,
 *   platform: { isWeb, isIOS, isAndroid }
 * } = useResponsive();
 */
export function useResponsive(): ResponsiveInfo {
  const windowDimensions = useWindowDimensions();
  const { width, height } = windowDimensions;

  const breakpoint = getBreakpoint(width);
  const fineBreakpoint = getFineBreakpoint(width);
  const orientation = getOrientation(width, height);

  const isMobile = breakpoint === 'mobile';
  const isTablet = breakpoint === 'tablet';
  const isDesktop = breakpoint === 'desktop';
  const isWide = breakpoint === 'wide';
  const isWideScreen = isTablet || isDesktop || isWide;

  const isXS = fineBreakpoint === 'xs';
  const isSM = fineBreakpoint === 'sm';
  const isMD = fineBreakpoint === 'md';
  const isLG = fineBreakpoint === 'lg';
  const isXL = fineBreakpoint === 'xl';
  const is2XL = fineBreakpoint === '2xl';
  const is3XL = fineBreakpoint === '3xl';
  const is4XL = fineBreakpoint === '4xl';

  const isPortrait = orientation === 'portrait';
  const isLandscape = orientation === 'landscape';

  const platform = useMemo(() => ({
    OS: Platform.OS,
    isWeb: Platform.OS === 'web',
    isIOS: Platform.OS === 'ios',
    isAndroid: Platform.OS === 'android',
    isNative: Platform.OS !== 'web',
  }), []);

  return {
    width,
    height,
    breakpoint,
    isMobile,
    isTablet,
    isDesktop,
    isWide,
    isWideScreen,
    fineBreakpoint,
    isXS,
    isSM,
    isMD,
    isLG,
    isXL,
    is2XL,
    is3XL,
    is4XL,
    orientation,
    isPortrait,
    isLandscape,
    platform,
  };
}

// ==================== 响应式值选择器 ====================
/**
 * 根据当前断点从响应式值对象中选择合适的值
 * 
 * @param value - 响应式值，可以是单一值或断点映射对象
 * @param currentBreakpoint - 当前细粒度断点
 * @returns 选中的值
 * 
 * @example
 * const padding = useResponsiveValue({ xs: 8, md: 16, lg: 24 });
 * // 在 xs 屏幕返回 8，md 屏幕返回 16，lg 及以上返回 24
 */
export function useResponsiveValue<T>(value: ResponsiveValue<T>): T {
  const { fineBreakpoint } = useResponsive();
  
  return useMemo(() => {
    // 如果不是对象，直接返回
    if (typeof value !== 'object' || value === null || Array.isArray(value)) {
      return value as T;
    }
    
    const breakpointOrder: FineBreakpointKey[] = ['4xl', '3xl', '2xl', 'xl', 'lg', 'md', 'sm', 'xs'];
    const valueMap = value as Partial<Record<FineBreakpointKey, T>>;
    
    // 从当前断点开始向下查找
    const currentIndex = breakpointOrder.indexOf(fineBreakpoint);
    for (let i = currentIndex; i < breakpointOrder.length; i++) {
      const bp = breakpointOrder[i];
      if (bp in valueMap) {
        return valueMap[bp]!;
      }
    }
    
    // 如果没找到，返回 xs 的值或第一个值
    return (valueMap.xs ?? Object.values(valueMap)[0]) as T;
  }, [value, fineBreakpoint]);
}

// ==================== 响应式样式生成器 ====================
/**
 * 根据断点生成响应式样式
 * 
 * @param styles - 响应式样式对象
 * @returns 当前断点对应的样式
 * 
 * @example
 * const containerStyle = useResponsiveStyle({
 *   padding: { xs: 8, md: 16, lg: 24 },
 *   fontSize: { xs: 14, lg: 16 }
 * });
 */
export function useResponsiveStyle<T extends Record<string, ResponsiveValue<unknown>>>(
  styles: T
): { [K in keyof T]: T[K] extends ResponsiveValue<infer V> ? V : never } {
  const { fineBreakpoint } = useResponsive();
  
  return useMemo(() => {
    const result = {} as { [K in keyof T]: T[K] extends ResponsiveValue<infer V> ? V : never };
    
    for (const key in styles) {
      const value = styles[key];
      
      if (typeof value !== 'object' || value === null || Array.isArray(value)) {
        (result as Record<string, unknown>)[key] = value;
      } else {
        const valueMap = value as Partial<Record<FineBreakpointKey, unknown>>;
        const breakpointOrder: FineBreakpointKey[] = ['4xl', '3xl', '2xl', 'xl', 'lg', 'md', 'sm', 'xs'];
        const currentIndex = breakpointOrder.indexOf(fineBreakpoint);
        
        let selectedValue: unknown = undefined;
        for (let i = currentIndex; i < breakpointOrder.length; i++) {
          const bp = breakpointOrder[i];
          if (bp in valueMap) {
            selectedValue = valueMap[bp];
            break;
          }
        }
        
        (result as Record<string, unknown>)[key] = selectedValue ?? valueMap.xs ?? Object.values(valueMap)[0];
      }
    }
    
    return result;
  }, [styles, fineBreakpoint]);
}

// ==================== 断点比较工具 ====================
/**
 * 检查当前断点是否大于等于目标断点
 * 
 * @param current - 当前断点
 * @param target - 目标断点
 * @returns 是否满足条件
 */
export function isBreakpointGTE(
  current: FineBreakpointKey,
  target: FineBreakpointKey
): boolean {
  const order: FineBreakpointKey[] = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'];
  return order.indexOf(current) >= order.indexOf(target);
}

/**
 * 检查当前断点是否小于目标断点
 * 
 * @param current - 当前断点
 * @param target - 目标断点
 * @returns 是否满足条件
 */
export function isBreakpointLT(
  current: FineBreakpointKey,
  target: FineBreakpointKey
): boolean {
  return !isBreakpointGTE(current, target);
}

// ==================== 断点范围检查 Hook ====================
/**
 * 检查当前是否在指定断点范围内
 * 
 * @param options - 断点范围选项
 * @returns 是否在范围内
 * 
 * @example
 * const isMediumUp = useBreakpointGTE('md');
 * const isMobileOnly = useBreakpointLT('lg');
 */
export function useBreakpointGTE(target: FineBreakpointKey): boolean {
  const { fineBreakpoint } = useResponsive();
  return isBreakpointGTE(fineBreakpoint, target);
}

export function useBreakpointLT(target: FineBreakpointKey): boolean {
  const { fineBreakpoint } = useResponsive();
  return isBreakpointLT(fineBreakpoint, target);
}

export function useBreakpointBetween(
  min: FineBreakpointKey,
  max: FineBreakpointKey
): boolean {
  const { fineBreakpoint } = useResponsive();
  return isBreakpointGTE(fineBreakpoint, min) && !isBreakpointGTE(fineBreakpoint, max);
}

// ==================== 平台检测 Hook ====================
/**
 * 平台检测 Hook
 * 提供便捷的平台检测方法
 * 
 * @example
 * const { isWeb, isIOS, isAndroid, isNative } = usePlatform();
 */
export function usePlatform() {
  const { platform } = useResponsive();
  return platform;
}

// ==================== 媒体查询模拟 ====================
/**
 * 模拟 CSS 媒体查询
 * 
 * @param query - 查询条件
 * @returns 是否匹配
 * 
 * @example
 * const isMinWidth768 = useMediaQuery({ minWidth: 768 });
 * const isMaxWidth1024 = useMediaQuery({ maxWidth: 1024 });
 * const isPortrait = useMediaQuery({ orientation: 'portrait' });
 */
interface MediaQueryOptions {
  minWidth?: number;
  maxWidth?: number;
  minHeight?: number;
  maxHeight?: number;
  orientation?: 'portrait' | 'landscape';
}

export function useMediaQuery(query: MediaQueryOptions): boolean {
  const { width, height, orientation: currentOrientation } = useResponsive();
  
  return useMemo(() => {
    if (query.minWidth !== undefined && width < query.minWidth) return false;
    if (query.maxWidth !== undefined && width > query.maxWidth) return false;
    if (query.minHeight !== undefined && height < query.minHeight) return false;
    if (query.maxHeight !== undefined && height > query.maxHeight) return false;
    if (query.orientation !== undefined && currentOrientation !== query.orientation) return false;
    return true;
  }, [width, height, currentOrientation, query]);
}

// ==================== 列数计算工具 ====================
/**
 * 根据容器宽度计算合适的列数
 * 
 * @param containerWidth - 容器宽度
 * @param options - 配置选项
 * @returns 列数
 * 
 * @example
 * const columns = useColumnCount({
 *   xs: 1,
 *   sm: 2,
 *   md: 3,
 *   lg: 4
 * });
 */
export function useColumnCount(
  columnConfig: Partial<Record<FineBreakpointKey, number>> = {}
): number {
  const { fineBreakpoint } = useResponsive();
  
  const defaultConfig: Record<FineBreakpointKey, number> = {
    xs: 1,
    sm: 1,
    md: 2,
    lg: 3,
    xl: 4,
    '2xl': 4,
    '3xl': 5,
    '4xl': 6,
  };
  
  return useMemo(() => {
    const config = { ...defaultConfig, ...columnConfig };
    const breakpointOrder: FineBreakpointKey[] = ['4xl', '3xl', '2xl', 'xl', 'lg', 'md', 'sm', 'xs'];
    const currentIndex = breakpointOrder.indexOf(fineBreakpoint);
    
    for (let i = currentIndex; i < breakpointOrder.length; i++) {
      const bp = breakpointOrder[i];
      if (config[bp] !== undefined) {
        return config[bp];
      }
    }
    
    return 1;
  }, [fineBreakpoint, columnConfig]);
}

// ==================== 间距计算工具 ====================
/**
 * 响应式间距 Hook
 * 
 * @param spacingConfig - 间距配置
 * @returns 当前断点对应的间距值
 * 
 * @example
 * const gap = useResponsiveSpacing({ xs: 8, md: 16, lg: 24 });
 */
export function useResponsiveSpacing(
  spacingConfig: Partial<Record<FineBreakpointKey, number>> = {}
): number {
  const { fineBreakpoint } = useResponsive();
  
  const defaultConfig: Record<FineBreakpointKey, number> = {
    xs: 8,
    sm: 8,
    md: 12,
    lg: 16,
    xl: 20,
    '2xl': 24,
    '3xl': 32,
    '4xl': 40,
  };
  
  return useMemo(() => {
    const config = { ...defaultConfig, ...spacingConfig };
    const breakpointOrder: FineBreakpointKey[] = ['4xl', '3xl', '2xl', 'xl', 'lg', 'md', 'sm', 'xs'];
    const currentIndex = breakpointOrder.indexOf(fineBreakpoint);
    
    for (let i = currentIndex; i < breakpointOrder.length; i++) {
      const bp = breakpointOrder[i];
      if (config[bp] !== undefined) {
        return config[bp];
      }
    }
    
    return defaultConfig.xs;
  }, [fineBreakpoint, spacingConfig]);
}

export default useResponsive;
