import 'dart:async';

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

import '../../../../../core/network/failure.dart';
import '../../../vendor/domain/entities/vendor.dart';
import '../../../vendor/domain/repositories/vendor_repository.dart';

/// 공급업체를 검색해 선택할 수 있는 자동완성 입력 필드.
class VendorAutocompleteField extends StatefulWidget {
  const VendorAutocompleteField({
    super.key,
    required this.initialOptions,
    this.selectedVendorId,
    this.initialLabel,
    required this.onSelected,
    this.enabled = true,
    this.placeholder,
  });

  final List<Vendor> initialOptions;
  final int? selectedVendorId;
  final String? initialLabel;
  final ValueChanged<int?> onSelected;
  final bool enabled;
  final Widget? placeholder;

  @override
  State<VendorAutocompleteField> createState() =>
      _VendorAutocompleteFieldState();
}

class _VendorAutocompleteFieldState extends State<VendorAutocompleteField> {
  static const Duration _debounceDuration = Duration(milliseconds: 250);

  VendorRepository? get _repository => GetIt.I.isRegistered<VendorRepository>()
      ? GetIt.I<VendorRepository>()
      : null;

  final TextEditingController _controller = TextEditingController();
  final FocusNode _focusNode = FocusNode();
  final List<Vendor> _baseOptions = [];
  final List<Vendor> _suggestions = [];
  Vendor? _selected;
  bool _isSearching = false;
  String? _error;
  Timer? _debounce;
  int _requestId = 0;
  bool _isApplyingText = false;

  @override
  void initState() {
    super.initState();
    _controller.addListener(_handleTextChanged);
    _focusNode.addListener(_handleFocusChange);
    _initializeOptions();
  }

  @override
  void didUpdateWidget(covariant VendorAutocompleteField oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (!identical(widget.initialOptions, oldWidget.initialOptions)) {
      _baseOptions
        ..clear()
        ..addAll(widget.initialOptions);
      if (_controller.text.trim().isEmpty) {
        _resetSuggestions();
      }
    }
    if (widget.selectedVendorId != oldWidget.selectedVendorId) {
      _applySelectionFromId(
        widget.selectedVendorId,
        label: widget.initialLabel,
      );
    }
  }

  @override
  void dispose() {
    _controller.removeListener(_handleTextChanged);
    _controller.dispose();
    _focusNode
      ..removeListener(_handleFocusChange)
      ..dispose();
    _debounce?.cancel();
    super.dispose();
  }

  void _initializeOptions() {
    _baseOptions
      ..clear()
      ..addAll(widget.initialOptions);
    _resetSuggestions();
    if (widget.selectedVendorId != null) {
      _applySelectionFromId(
        widget.selectedVendorId,
        label: widget.initialLabel,
      );
    } else if (widget.initialLabel != null && widget.initialLabel!.isNotEmpty) {
      _isApplyingText = true;
      _controller
        ..text = widget.initialLabel!
        ..selection = TextSelection.collapsed(
          offset: widget.initialLabel!.length,
        );
      _isApplyingText = false;
    }
    _log('초기 옵션 준비 완료 (base=${_baseOptions.length})');
  }

  void _resetSuggestions() {
    setState(() {
      _suggestions
        ..clear()
        ..addAll(_baseOptions);
    });
    _log('입력 초기화 -> 제안 목록 리셋 (count=${_suggestions.length})');
  }

  void _handleTextChanged() {
    if (_isApplyingText) {
      return;
    }
    final keyword = _controller.text.trim();
    if (keyword.isEmpty) {
      _debounce?.cancel();
      _resetSuggestions();
      return;
    }

    if (_selected != null && keyword != _displayLabel(_selected!)) {
      _selected = null;
      widget.onSelected(null);
    }
    _scheduleSearch(keyword);
  }

  void _scheduleSearch(String keyword) {
    _debounce?.cancel();
    _debounce = Timer(_debounceDuration, () => _search(keyword));
    _log('검색 예약: "$keyword"');
  }

  Future<void> _search(String keyword) async {
    final repository = _repository;
    if (repository == null) {
      setState(() {
        _error = '공급업체 데이터 소스를 찾을 수 없습니다.';
      });
      return;
    }
    final request = ++_requestId;
    setState(() {
      _isSearching = true;
      _error = null;
    });
    try {
      _log('공급업체 검색 시작: "$keyword"');
      final result = await repository.list(
        page: 1,
        pageSize: 20,
        query: keyword,
        isActive: true,
      );
      if (!mounted || request != _requestId) {
        return;
      }
      final items = result.items.toList(growable: false);
      setState(() {
        _suggestions
          ..clear()
          ..addAll(items);
        _isSearching = false;
      });
      _log('공급업체 검색 완료: ${items.length}건');
    } catch (error) {
      if (!mounted || request != _requestId) {
        return;
      }
      setState(() {
        final failure = Failure.from(error);
        _error = failure.describe();
        _suggestions.clear();
        _isSearching = false;
      });
      _log('공급업체 검색 실패: ${_error ?? '알 수 없는 오류'}');
    }
  }

  void _applySelectionFromId(int? id, {String? label}) {
    if (id == null) {
      _setSelection(null, notify: true);
      return;
    }
    final match = _findById(_baseOptions, id) ?? _findById(_suggestions, id);
    if (match != null) {
      _setSelection(match, notify: false);
      return;
    }
    if (label != null && label.isNotEmpty) {
      _isApplyingText = true;
      _controller
        ..text = label
        ..selection = TextSelection.collapsed(offset: label.length);
      _isApplyingText = false;
    }
  }

  Vendor? _findById(List<Vendor> options, int id) {
    for (final option in options) {
      if (option.id == id) {
        return option;
      }
    }
    return null;
  }

  void _setSelection(Vendor? vendor, {bool notify = true}) {
    setState(() {
      _selected = vendor;
      if (vendor != null && !_baseOptions.any((item) => item.id == vendor.id)) {
        _baseOptions.add(vendor);
      }
      if (vendor == null) {
        _applyControllerText('');
      } else {
        _applyControllerText(_displayLabel(vendor));
      }
    });
    if (vendor == null) {
      _log('선택 해제됨');
    } else {
      _log('항목 선택: id=${vendor.id}, label=${_displayLabel(vendor)}');
    }
    if (notify) {
      widget.onSelected(vendor?.id);
    }
  }

  String _displayLabel(Vendor vendor) {
    final code = vendor.vendorCode.isEmpty ? '' : ' (${vendor.vendorCode})';
    return '${vendor.vendorName}$code';
  }

  @override
  Widget build(BuildContext context) {
    if (_error != null && _baseOptions.isEmpty && _suggestions.isEmpty) {
      return ShadInput(
        readOnly: true,
        enabled: false,
        placeholder: Text(_error!),
      );
    }

    return RawAutocomplete<Vendor>(
      textEditingController: _controller,
      focusNode: _focusNode,
      optionsBuilder: (textEditingValue) {
        if (textEditingValue.text.trim().isEmpty) {
          if (_suggestions.isEmpty) {
            return _baseOptions;
          }
          return _baseOptions;
        }
        return _suggestions;
      },
      displayStringForOption: _displayLabel,
      onSelected: (vendor) => _setSelection(vendor),
      fieldViewBuilder: (context, textController, focusNode, onFieldSubmitted) {
        assert(identical(textController, _controller));
        final placeholder = widget.placeholder ?? const Text('제조사를 선택하세요');
        return Stack(
          alignment: Alignment.centerRight,
          children: [
            ShadInput(
              controller: textController,
              focusNode: focusNode,
              enabled: widget.enabled,
              readOnly: !widget.enabled,
              placeholder: placeholder,
              onPressedOutside: (event) {
                _log(
                  '입력 외부 포인터 감지 -> 포커스 유지 시도 '
                  'pos=${event.localPosition} kind=${event.kind}',
                );
                focusNode.requestFocus();
              },
            ),
            if (_isSearching)
              const Padding(
                padding: EdgeInsets.only(right: 12),
                child: SizedBox(
                  width: 16,
                  height: 16,
                  child: CircularProgressIndicator(strokeWidth: 2),
                ),
              ),
          ],
        );
      },
      optionsViewBuilder: (context, onSelected, options) {
        if (options.isEmpty) {
          return Listener(
            onPointerDown: (event) {
              _log(
                '오버레이 포인터 다운 (빈 목록) '
                'pos=${event.localPosition} kind=${event.kind}',
              );
              if (!_focusNode.hasPrimaryFocus) {
                _log('포커스 복구 시도 (빈 목록)');
                _focusNode.requestFocus();
              }
            },
            child: Align(
              alignment: Alignment.topLeft,
              child: ConstrainedBox(
                constraints: const BoxConstraints(
                  maxHeight: 200,
                  minWidth: 260,
                ),
                child: ShadCard(
                  padding: const EdgeInsets.symmetric(vertical: 12),
                  child: const Center(child: Text('검색 결과가 없습니다.')),
                ),
              ),
            ),
          );
        }
        _log('드롭다운 리스트 표시: ${options.length}건');
        return Listener(
          onPointerDown: (event) {
            _log(
              '오버레이 포인터 다운 pos=${event.localPosition} '
              'kind=${event.kind}',
            );
            if (!_focusNode.hasPrimaryFocus) {
              _log('포커스 복구 시도');
              _focusNode.requestFocus();
            }
          },
          child: Align(
            alignment: Alignment.topLeft,
            child: ConstrainedBox(
              constraints: const BoxConstraints(maxHeight: 240, minWidth: 260),
              child: ShadCard(
                padding: EdgeInsets.zero,
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: options.length,
                  itemBuilder: (context, index) {
                    final vendor = options.elementAt(index);
                    return GestureDetector(
                      behavior: HitTestBehavior.opaque,
                      onTapDown: (_) =>
                          _log('항목 탭다운: id=${vendor.id} index=$index'),
                      onTapCancel: () =>
                          _log('항목 탭 취소: id=${vendor.id} index=$index'),
                      onTap: () {
                        _log('항목 탭 -> onSelected 호출: id=${vendor.id}');
                        onSelected(vendor);
                      },
                      child: Padding(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 12,
                          vertical: 10,
                        ),
                        child: Text(_displayLabel(vendor)),
                      ),
                    );
                  },
                ),
              ),
            ),
          ),
        );
      },
    );
  }

  void _applyControllerText(String value) {
    _isApplyingText = true;
    _controller.text = value;
    _controller.selection = TextSelection.collapsed(offset: value.length);
    _isApplyingText = false;
    _log('입력 필드 텍스트 적용: "$value"');
  }

  void _handleFocusChange() {
    if (_focusNode.hasFocus) {
      _log('포커스 획득 -> 드롭다운 진입');
    } else {
      _log('포커스 해제 -> 드롭다운 종료');
    }
  }

  void _log(String message) {
    debugPrint('[VendorAutocomplete] $message');
  }
}
