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

import 'package:superport_v2/core/network/failure.dart';
import 'package:superport_v2/widgets/components/superport_table.dart';

import '../../domain/entities/postal_code.dart';
import '../../domain/repositories/postal_search_repository.dart';
import '../models/postal_search_result.dart';

typedef PostalSearchFetcher =
    Future<List<PostalSearchResult>> Function(String keyword);

/// 우편번호 검색 모달을 노출한다.
Future<PostalSearchResult?> showPostalSearchDialog(
  BuildContext context, {
  PostalSearchFetcher? fetcher,
  String? initialKeyword,
}) {
  return showDialog<PostalSearchResult>(
    context: context,
    builder: (dialogContext) {
      return _PostalSearchDialog(
        fetcher: fetcher,
        initialKeyword: initialKeyword,
      );
    },
  );
}

class _PostalSearchDialog extends StatefulWidget {
  const _PostalSearchDialog({required this.fetcher, this.initialKeyword});

  final PostalSearchFetcher? fetcher;
  final String? initialKeyword;

  @override
  State<_PostalSearchDialog> createState() => _PostalSearchDialogState();
}

class _PostalSearchDialogState extends State<_PostalSearchDialog> {
  late final TextEditingController _keywordController;
  final FocusNode _keywordFocus = FocusNode();
  List<PostalSearchResult> _results = const [];
  bool _isLoading = false;
  bool _hasSearched = false;
  String? _errorMessage;

  @override
  void initState() {
    super.initState();
    _keywordController = TextEditingController(text: widget.initialKeyword);
    if (_keywordController.text.isNotEmpty) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _performSearch();
      });
    }
  }

  @override
  void dispose() {
    _keywordController.dispose();
    _keywordFocus.dispose();
    super.dispose();
  }

  Future<void> _performSearch() async {
    final keyword = _keywordController.text.trim();
    if (keyword.isEmpty) {
      setState(() {
        _results = const [];
        _errorMessage = null;
        _hasSearched = false;
      });
      return;
    }

    final fetcher = _resolveFetcher();
    if (fetcher == null) {
      setState(() {
        _results = const [];
        _errorMessage = '검색 기능이 아직 연결되지 않았습니다.';
        _hasSearched = true;
      });
      return;
    }

    setState(() {
      _isLoading = true;
      _errorMessage = null;
      _hasSearched = true;
    });

    try {
      final items = await fetcher(keyword);
      if (!mounted) return;
      setState(() {
        _results = items;
        _errorMessage = null;
      });
    } catch (error) {
      if (!mounted) return;
      setState(() {
        _results = const [];
        final failure = Failure.from(error);
        _errorMessage = failure.describe();
      });
    } finally {
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  PostalSearchFetcher? _resolveFetcher() {
    final customFetcher = widget.fetcher;
    if (customFetcher != null) {
      return customFetcher;
    }

    final container = GetIt.instance;
    if (!container.isRegistered<PostalSearchRepository>()) {
      return null;
    }

    return (keyword) async {
      final repository = container<PostalSearchRepository>();
      final List<PostalCode> results = await repository.search(
        keyword: keyword,
        limit: 50,
      );
      return results
          .map(PostalSearchResult.fromPostalCode)
          .toList(growable: false);
    };
  }

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);
    final navigator = Navigator.of(context);

    return Dialog(
      clipBehavior: Clip.antiAlias,
      insetPadding: const EdgeInsets.all(24),
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 760, maxHeight: 600),
        child: ShadCard(
          title: Text('우편번호 검색', style: theme.textTheme.h3),
          description: Text(
            '도로명, 건물번호, 우편번호를 입력하면 검색 결과에서 직접 선택할 수 있습니다.',
            style: theme.textTheme.muted,
          ),
          footer: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              ShadButton.ghost(
                onPressed: () => navigator.pop(),
                child: const Text('닫기'),
              ),
            ],
          ),
          child: Column(
            mainAxisSize: MainAxisSize.max,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Expanded(
                    child: ShadInput(
                      controller: _keywordController,
                      focusNode: _keywordFocus,
                      placeholder: const Text('도로명, 건물번호, 우편번호를 입력'),
                      leading: const Icon(LucideIcons.search, size: 16),
                      onSubmitted: (_) => _performSearch(),
                    ),
                  ),
                  const SizedBox(width: 12),
                  ShadButton(
                    onPressed: _isLoading ? null : _performSearch,
                    child: _isLoading
                        ? const SizedBox(
                            width: 16,
                            height: 16,
                            child: CircularProgressIndicator(strokeWidth: 2),
                          )
                        : const Text('검색'),
                  ),
                ],
              ),
              const SizedBox(height: 16),
              Expanded(child: _buildResultArea(theme, navigator)),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildResultArea(ShadThemeData theme, NavigatorState navigator) {
    if (_isLoading) {
      return const Center(child: CircularProgressIndicator());
    }

    if (_errorMessage != null) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Text(
            _errorMessage!,
            textAlign: TextAlign.center,
            style: theme.textTheme.small,
          ),
        ),
      );
    }

    if (_results.isEmpty) {
      final label = _hasSearched
          ? '검색 결과가 없습니다. 다른 키워드로 시도해 주세요.'
          : '검색어를 입력한 뒤 엔터 또는 검색 버튼을 눌러 주세요.';
      return Center(child: Text(label, style: theme.textTheme.muted));
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('검색 결과 ${_results.length}건', style: theme.textTheme.muted),
        const SizedBox(height: 8),
        Expanded(
          child: DecoratedBox(
            decoration: BoxDecoration(
              border: Border.all(color: theme.colorScheme.border),
              borderRadius: BorderRadius.circular(8),
            ),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(8),
              child: SuperportTable(
                columns: const [
                  Text('우편번호'),
                  Text('시도'),
                  Text('시군구'),
                  Text('도로명'),
                  Text('건물번호'),
                ],
                rows: [
                  for (final item in _results)
                    [
                      Text(item.zipcode),
                      Text(item.sido ?? '-'),
                      Text(item.sigungu ?? '-'),
                      Text(item.roadName ?? '-'),
                      Text(item.buildingNumber ?? '-'),
                    ],
                ],
                onRowTap: (index) {
                  if (index < 0 || index >= _results.length) {
                    return;
                  }
                  navigator.pop(_results[index]);
                },
                emptyLabel: '검색 결과가 없습니다.',
              ),
            ),
          ),
        ),
        const SizedBox(height: 8),
        Text('행을 클릭하면 선택한 주소가 부모 폼에 채워집니다.', style: theme.textTheme.small),
      ],
    );
  }
}
