import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';

/// 표준화된 드롭다운 위젯
/// 3단계 상태 (로딩/오류/정상)를 자동으로 처리하며,
/// 모든 Form에서 일관된 사용자 경험을 제공합니다.
class StandardDropdown<T> extends StatelessWidget {
  /// 드롭다운 라벨
  final String label;
  
  /// 필수 항목 여부 (라벨에 * 표시)
  final bool isRequired;
  
  /// 드롭다운 옵션 데이터
  final List<T> items;
  
  /// 로딩 상태
  final bool isLoading;
  
  /// 오류 메시지 (null이면 오류 없음)
  final String? error;
  
  /// 재시도 콜백 함수
  final VoidCallback? onRetry;
  
  /// 선택 변경 콜백
  final void Function(T?) onChanged;
  
  /// 현재 선택된 값
  final T? selectedValue;
  
  /// 각 항목을 위젯으로 변환하는 빌더
  final Widget Function(T item) itemBuilder;
  
  /// 선택된 항목을 표시하는 빌더
  final Widget Function(T item) selectedItemBuilder;
  
  /// 값에서 고유 ID를 추출하는 함수
  final dynamic Function(T item) valueExtractor;
  
  /// 플레이스홀더 텍스트
  final String placeholder;
  
  /// 폼 검증 함수
  final String? Function(T? value)? validator;
  
  /// 비활성화 여부
  final bool enabled;
  
  const StandardDropdown({
    super.key,
    required this.label,
    this.isRequired = false,
    required this.items,
    this.isLoading = false,
    this.error,
    this.onRetry,
    required this.onChanged,
    this.selectedValue,
    required this.itemBuilder,
    required this.selectedItemBuilder,
    required this.valueExtractor,
    this.placeholder = '선택하세요',
    this.validator,
    this.enabled = true,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // 라벨
        Text(
          isRequired ? '$label *' : label,
          style: const TextStyle(fontWeight: FontWeight.bold),
        ),
        const SizedBox(height: 8),
        
        // 3단계 상태 처리
        _buildStateWidget(),
      ],
    );
  }
  
  /// 상태에 따른 위젯 빌드
  Widget _buildStateWidget() {
    // 1. 로딩 상태
    if (isLoading) {
      return _buildLoadingWidget();
    }
    
    // 2. 오류 상태
    if (error != null) {
      return _buildErrorWidget();
    }
    
    // 3. 정상 상태
    return _buildDropdownWidget();
  }
  
  /// 로딩 위젯
  Widget _buildLoadingWidget() {
    return SizedBox(
      height: 56,
      child: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SizedBox(
              width: 120, // 명시적 너비 지정으로 무한 너비 제약 해결
              child: const ShadProgress(),
            ),
            const SizedBox(width: 8),
            Text('$label 목록을 불러오는 중...'),
          ],
        ),
      ),
    );
  }
  
  /// 오류 위젯
  Widget _buildErrorWidget() {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.red.shade50,
        border: Border.all(color: Colors.red.shade200),
        borderRadius: BorderRadius.circular(8),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(Icons.error, color: Colors.red.shade600, size: 20),
              const SizedBox(width: 8),
              Text(
                '$label 로딩 실패',
                style: const TextStyle(fontWeight: FontWeight.w500),
              ),
            ],
          ),
          const SizedBox(height: 8),
          Text(
            error!,
            style: TextStyle(color: Colors.red.shade700, fontSize: 14),
          ),
          if (onRetry != null) ...[
            const SizedBox(height: 12),
            ShadButton(
              onPressed: onRetry,
              child: const Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(Icons.refresh, size: 16),
                  SizedBox(width: 4),
                  Text('다시 시도'),
                ],
              ),
            ),
          ],
        ],
      ),
    );
  }
  
  /// 드롭다운 위젯 (정상 상태)
  Widget _buildDropdownWidget() {
    // 비어있는 경우 처리
    if (items.isEmpty) {
      return Container(
        height: 56,
        padding: const EdgeInsets.all(16),
        decoration: BoxDecoration(
          color: Colors.grey.shade50,
          border: Border.all(color: Colors.grey.shade300),
          borderRadius: BorderRadius.circular(8),
        ),
        child: Center(
          child: Text(
            '$label이(가) 없습니다',
            style: TextStyle(color: Colors.grey.shade600),
          ),
        ),
      );
    }
    
    return ShadSelect<dynamic>(
      placeholder: Text(placeholder),
      options: items.map((item) {
        return ShadOption(
          value: valueExtractor(item),
          child: itemBuilder(item),
        );
      }).toList(),
      selectedOptionBuilder: (context, value) {
        if (value == null) return Text(placeholder);
        
        // 선택된 값에 해당하는 항목 찾기
        try {
          final selectedItem = items.firstWhere(
            (item) => valueExtractor(item) == value,
          );
          return selectedItemBuilder(selectedItem);
        } catch (e) {
          return Text('알 수 없는 항목 (값: $value)');
        }
      },
      onChanged: enabled ? (value) {
        if (value == null) {
          onChanged(null);
          return;
        }
        
        // 값에 해당하는 실제 객체 찾기
        try {
          final selectedItem = items.firstWhere(
            (item) => valueExtractor(item) == value,
          );
          onChanged(selectedItem);
        } catch (e) {
          onChanged(null);
        }
      } : null,
      initialValue: selectedValue != null ? valueExtractor(selectedValue as T) : null,
    );
  }
}

/// Int ID 타입을 위한 편의 클래스
class StandardIntDropdown<T> extends StandardDropdown<T> {
  StandardIntDropdown({
    super.key,
    required super.label,
    super.isRequired = false,
    required super.items,
    super.isLoading = false,
    super.error,
    super.onRetry,
    required super.onChanged,
    super.selectedValue,
    required super.itemBuilder,
    required super.selectedItemBuilder,
    required int Function(T item) idExtractor,
    super.placeholder = '선택하세요',
    super.validator,
    super.enabled = true,
  }) : super(
          valueExtractor: (item) => idExtractor(item),
        );
}

/// String 값 타입을 위한 편의 클래스
class StandardStringDropdown<T> extends StandardDropdown<T> {
  StandardStringDropdown({
    super.key,
    required super.label,
    super.isRequired = false,
    required super.items,
    super.isLoading = false,
    super.error,
    super.onRetry,
    required super.onChanged,
    super.selectedValue,
    required super.itemBuilder,
    required super.selectedItemBuilder,
    required super.valueExtractor,
    super.placeholder = '선택하세요',
    super.validator,
    super.enabled = true,
  });
}