import 'dart:async';

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

import '../../../../../widgets/components/superport_detail_dialog.dart';
import '../../../../util/postal_search/presentation/models/postal_search_result.dart';
import '../../../../util/postal_search/presentation/widgets/postal_search_dialog.dart';
import '../../domain/entities/customer.dart';

/// 고객 상세 다이얼로그에서 발생 가능한 액션 종류이다.
enum CustomerDetailDialogAction { created, updated, deleted, restored }

/// 고객 상세 다이얼로그가 반환하는 결과 모델이다.
class CustomerDetailDialogResult {
  const CustomerDetailDialogResult({
    required this.action,
    required this.message,
    this.customer,
  });

  final CustomerDetailDialogAction action;
  final String message;

  /// 갱신된 고객 엔터티. 삭제 동작의 경우 null일 수 있다.
  final Customer? customer;
}

typedef CustomerCreateCallback =
    Future<Customer?> Function(CustomerInput input);
typedef CustomerUpdateCallback =
    Future<Customer?> Function(int id, CustomerInput input);
typedef CustomerDeleteCallback = Future<bool> Function(int id);
typedef CustomerRestoreCallback = Future<Customer?> Function(int id);

/// 고객 상세 다이얼로그를 노출한다.
Future<CustomerDetailDialogResult?> showCustomerDetailDialog({
  required BuildContext context,
  required intl.DateFormat dateFormat,
  Customer? customer,
  required CustomerCreateCallback onCreate,
  required CustomerUpdateCallback onUpdate,
  required CustomerDeleteCallback onDelete,
  required CustomerRestoreCallback onRestore,
}) {
  final metadata = customer == null
      ? const <SuperportDetailMetadata>[]
      : [
          SuperportDetailMetadata.text(
            label: 'ID',
            value: customer.id?.toString() ?? '-',
          ),
          SuperportDetailMetadata.text(
            label: '고객사 코드',
            value: customer.customerCode,
          ),
          SuperportDetailMetadata.text(
            label: '유형',
            value: _resolveType(customer),
          ),
          SuperportDetailMetadata.text(
            label: '담당자',
            value: customer.contactName?.isEmpty ?? true
                ? '-'
                : customer.contactName!,
          ),
          SuperportDetailMetadata.text(
            label: '연락처',
            value: customer.mobileNo?.isEmpty ?? true
                ? '-'
                : customer.mobileNo!,
          ),
          SuperportDetailMetadata.text(
            label: '이메일',
            value: customer.email?.isEmpty ?? true ? '-' : customer.email!,
          ),
          SuperportDetailMetadata.text(
            label: '사용 상태',
            value: customer.isActive ? '사용중' : '미사용',
          ),
          SuperportDetailMetadata.text(
            label: '삭제 여부',
            value: customer.isDeleted ? '삭제됨' : '정상',
          ),
          SuperportDetailMetadata.text(
            label: '우편번호',
            value: customer.zipcode?.zipcode ?? '-',
          ),
          SuperportDetailMetadata.text(
            label: '주소',
            value: _resolveAddress(customer),
          ),
          SuperportDetailMetadata.text(
            label: '비고',
            value: customer.note?.isEmpty ?? true ? '-' : customer.note!,
          ),
          SuperportDetailMetadata.text(
            label: '생성일시',
            value: customer.createdAt == null
                ? '-'
                : dateFormat.format(customer.createdAt!.toLocal()),
          ),
          SuperportDetailMetadata.text(
            label: '수정일시',
            value: customer.updatedAt == null
                ? '-'
                : dateFormat.format(customer.updatedAt!.toLocal()),
          ),
        ];

  return showSuperportDetailDialog<CustomerDetailDialogResult>(
    context: context,
    title: customer == null ? '고객사 등록' : '고객사 상세',
    description: customer == null
        ? '새로운 고객사 정보를 입력하세요.'
        : '고객사 기본 정보와 연락처·주소를 확인하고 관리합니다.',
    sections: [
      _CustomerEditSection(
        id: customer == null
            ? _CustomerDetailSections.create
            : _CustomerDetailSections.edit,
        label: customer == null ? '등록' : '수정',
        customer: customer,
        onSubmit: (input) async {
          if (customer == null) {
            final created = await onCreate(input);
            if (created == null) {
              return null;
            }
            return CustomerDetailDialogResult(
              action: CustomerDetailDialogAction.created,
              message: '고객사를 등록했습니다.',
              customer: created,
            );
          }
          final updated = await onUpdate(customer.id!, input);
          if (updated == null) {
            return null;
          }
          return CustomerDetailDialogResult(
            action: CustomerDetailDialogAction.updated,
            message: '고객사를 수정했습니다.',
            customer: updated,
          );
        },
      ),
      if (customer != null)
        SuperportDetailDialogSection(
          id: customer.isDeleted
              ? _CustomerDetailSections.restore
              : _CustomerDetailSections.delete,
          label: customer.isDeleted ? '복구' : '삭제',
          icon: customer.isDeleted ? LucideIcons.history : LucideIcons.trash2,
          builder: (_) => _CustomerDangerSection(
            customer: customer,
            onDelete: () async {
              final success = await onDelete(customer.id!);
              if (!success) {
                return null;
              }
              return const CustomerDetailDialogResult(
                action: CustomerDetailDialogAction.deleted,
                message: '고객사를 삭제했습니다.',
              );
            },
            onRestore: () async {
              final restored = await onRestore(customer.id!);
              if (restored == null) {
                return null;
              }
              return CustomerDetailDialogResult(
                action: CustomerDetailDialogAction.restored,
                message: '고객사를 복구했습니다.',
                customer: restored,
              );
            },
          ),
        ),
    ],
    summary: customer == null
        ? null
        : Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                customer.customerName,
                style: ShadTheme.of(context).textTheme.h4,
              ),
              const SizedBox(height: 4),
              Text(
                '코드 ${customer.customerCode}',
                style: ShadTheme.of(context).textTheme.muted,
              ),
            ],
          ),
    summaryBadges: customer == null
        ? const []
        : [
            if (customer.isPartner && customer.isGeneral)
              const ShadBadge(child: Text('파트너/일반'))
            else if (customer.isPartner)
              const ShadBadge(child: Text('파트너'))
            else if (customer.isGeneral)
              const ShadBadge(child: Text('일반')),
            if (customer.isActive)
              const ShadBadge.outline(child: Text('사용중'))
            else
              const ShadBadge.destructive(child: Text('미사용')),
            if (customer.isDeleted)
              const ShadBadge.destructive(child: Text('삭제됨')),
          ],
    metadata: metadata,
    emptyPlaceholder: const Text('표시할 고객사 정보가 없습니다.'),
    initialSectionId: customer == null
        ? _CustomerDetailSections.create
        : _CustomerDetailSections.edit,
  );
}

/// 다이얼로그 섹션 식별자 상수 모음이다.
class _CustomerDetailSections {
  static const edit = 'edit';
  static const create = 'create';
  static const delete = 'delete';
  static const restore = 'restore';
}

/// 키-값 형태의 행을 표현하는 내부 모델이다.

/// 고객 등록/수정 폼 섹션 정의이다.
class _CustomerEditSection extends SuperportDetailDialogSection {
  _CustomerEditSection({
    required super.id,
    required super.label,
    required this.customer,
    required this.onSubmit,
  }) : super(
         icon: LucideIcons.pencil,
         builder: (context) =>
             _CustomerForm(customer: customer, onSubmit: onSubmit),
       );

  final Customer? customer;
  final Future<CustomerDetailDialogResult?> Function(CustomerInput input)
  onSubmit;
}

/// 삭제/복구 단계를 안내하는 위험 섹션이다.
class _CustomerDangerSection extends StatelessWidget {
  const _CustomerDangerSection({
    required this.customer,
    required this.onDelete,
    required this.onRestore,
  });

  final Customer customer;
  final Future<CustomerDetailDialogResult?> Function() onDelete;
  final Future<CustomerDetailDialogResult?> Function() onRestore;

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);
    final isDeleted = customer.isDeleted;
    final description = isDeleted
        ? '고객사를 복구하면 다시 목록에 노출되고 사용중 상태로 전환됩니다.'
        : '고객사를 삭제하면 목록에서 숨겨지고 관련 데이터는 보존됩니다.';
    final actionLabel = isDeleted ? '복구' : '삭제';

    return Padding(
      padding: const EdgeInsets.only(top: 8),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(description, style: theme.textTheme.small),
          const SizedBox(height: 16),
          if (isDeleted)
            ShadButton(
              onPressed: () async {
                final navigator = Navigator.of(context, rootNavigator: true);
                final result = await onRestore();
                if (result != null && navigator.mounted) {
                  navigator.pop(result);
                }
              },
              child: Text(actionLabel),
            )
          else
            ShadButton.destructive(
              onPressed: () async {
                final navigator = Navigator.of(context, rootNavigator: true);
                final result = await onDelete();
                if (result != null && navigator.mounted) {
                  navigator.pop(result);
                }
              },
              child: Text(actionLabel),
            ),
        ],
      ),
    );
  }
}

/// 고객 입력 폼을 관리하는 상태ful 위젯이다.
class _CustomerForm extends StatefulWidget {
  const _CustomerForm({required this.customer, required this.onSubmit});

  final Customer? customer;
  final Future<CustomerDetailDialogResult?> Function(CustomerInput input)
  onSubmit;

  @override
  State<_CustomerForm> createState() => _CustomerFormState();
}

class _CustomerFormState extends State<_CustomerForm> {
  late final TextEditingController _codeController;
  late final TextEditingController _nameController;
  late final TextEditingController _contactController;
  late final TextEditingController _emailController;
  late final TextEditingController _mobileController;
  late final TextEditingController _zipcodeController;
  late final TextEditingController _addressController;
  late final TextEditingController _noteController;
  late bool _isPartner;
  late bool _isGeneral;
  late bool _isActive;
  PostalSearchResult? _selectedPostal;
  String? _codeError;
  String? _nameError;
  String? _typeError;
  String? _zipcodeError;
  String? _submitError;
  bool _isSubmitting = false;
  bool _isApplyingPostalSelection = false;

  bool get _isEdit => widget.customer != null;

  @override
  void initState() {
    super.initState();
    final existing = widget.customer;
    _codeController = TextEditingController(text: existing?.customerCode ?? '');
    _nameController = TextEditingController(text: existing?.customerName ?? '');
    _contactController = TextEditingController(
      text: existing?.contactName ?? '',
    );
    _emailController = TextEditingController(text: existing?.email ?? '');
    _mobileController = TextEditingController(text: existing?.mobileNo ?? '');
    _zipcodeController = TextEditingController(
      text: existing?.zipcode?.zipcode ?? '',
    );
    _addressController = TextEditingController(
      text: existing?.addressDetail ?? '',
    );
    _noteController = TextEditingController(text: existing?.note ?? '');

    final zipcode = existing?.zipcode;
    _selectedPostal = zipcode == null
        ? null
        : PostalSearchResult(
            zipcode: zipcode.zipcode,
            sido: zipcode.sido,
            sigungu: zipcode.sigungu,
            roadName: zipcode.roadName,
          );

    _isPartner = existing?.isPartner ?? false;
    _isGeneral = existing?.isGeneral ?? true;
    _isActive = existing?.isActive ?? true;

    _zipcodeController.addListener(_handleZipcodeChanged);
  }

  @override
  void dispose() {
    _codeController.dispose();
    _nameController.dispose();
    _contactController.dispose();
    _emailController.dispose();
    _mobileController.dispose();
    _zipcodeController.removeListener(_handleZipcodeChanged);
    _zipcodeController.dispose();
    _addressController.dispose();
    _noteController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);
    final destructiveColor = theme.colorScheme.destructive;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _CustomerFormField(
          label: '고객사코드',
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              ShadInput(
                controller: _codeController,
                readOnly: _isEdit,
                onChanged: (_) {
                  if (_codeController.text.trim().isNotEmpty) {
                    setState(() {
                      _codeError = null;
                    });
                  }
                },
              ),
              if (_codeError != null)
                Padding(
                  padding: const EdgeInsets.only(top: 6),
                  child: Text(
                    _codeError!,
                    style: theme.textTheme.small.copyWith(
                      color: destructiveColor,
                    ),
                  ),
                ),
            ],
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '고객사명',
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              ShadInput(
                controller: _nameController,
                onChanged: (_) {
                  if (_nameController.text.trim().isNotEmpty) {
                    setState(() {
                      _nameError = null;
                    });
                  }
                },
              ),
              if (_nameError != null)
                Padding(
                  padding: const EdgeInsets.only(top: 6),
                  child: Text(
                    _nameError!,
                    style: theme.textTheme.small.copyWith(
                      color: destructiveColor,
                    ),
                  ),
                ),
            ],
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '담당자',
          child: ShadInput(controller: _contactController),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '유형',
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  ShadCheckbox(
                    value: _isPartner,
                    onChanged: _isSubmitting
                        ? null
                        : (value) {
                            setState(() {
                              _isPartner = value;
                              if (!_isPartner && !_isGeneral) {
                                _typeError = '파트너/일반 중 하나 이상 선택하세요.';
                              } else {
                                _typeError = null;
                              }
                            });
                          },
                  ),
                  const SizedBox(width: 8),
                  const Text('파트너'),
                  const SizedBox(width: 24),
                  ShadCheckbox(
                    value: _isGeneral,
                    onChanged: _isSubmitting
                        ? null
                        : (value) {
                            setState(() {
                              _isGeneral = value;
                              if (!_isPartner && !_isGeneral) {
                                _typeError = '파트너/일반 중 하나 이상 선택하세요.';
                              } else {
                                _typeError = null;
                              }
                            });
                          },
                  ),
                  const SizedBox(width: 8),
                  const Text('일반'),
                ],
              ),
              if (_typeError != null)
                Padding(
                  padding: const EdgeInsets.only(top: 6),
                  child: Text(
                    _typeError!,
                    style: theme.textTheme.small.copyWith(
                      color: destructiveColor,
                    ),
                  ),
                ),
            ],
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '이메일',
          child: ShadInput(
            controller: _emailController,
            keyboardType: TextInputType.emailAddress,
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '연락처',
          child: ShadInput(
            controller: _mobileController,
            keyboardType: TextInputType.phone,
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '우편번호',
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Expanded(
                    child: ShadInput(
                      controller: _zipcodeController,
                      placeholder: const Text('예: 06000'),
                      keyboardType: TextInputType.number,
                    ),
                  ),
                  const SizedBox(width: 8),
                  ShadButton.outline(
                    onPressed: _isSubmitting ? null : _openPostalSearch,
                    child: const Text('검색'),
                  ),
                ],
              ),
              const SizedBox(height: 8),
              Text(
                _selectedPostal == null
                    ? '검색 버튼을 눌러 주소를 선택하세요.'
                    : _selectedPostal!.fullAddress.isEmpty
                    ? '선택한 우편번호에 주소 정보가 없습니다.'
                    : _selectedPostal!.fullAddress,
                style: theme.textTheme.small.copyWith(
                  color: _selectedPostal == null
                      ? theme.colorScheme.mutedForeground
                      : theme.textTheme.small.color,
                ),
              ),
              if (_zipcodeError != null)
                Padding(
                  padding: const EdgeInsets.only(top: 6),
                  child: Text(
                    _zipcodeError!,
                    style: theme.textTheme.small.copyWith(
                      color: destructiveColor,
                    ),
                  ),
                ),
            ],
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '상세주소',
          child: ShadInput(
            controller: _addressController,
            placeholder: const Text('상세주소 입력'),
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '사용여부',
          child: Row(
            children: [
              ShadSwitch(
                value: _isActive,
                onChanged: _isSubmitting
                    ? null
                    : (next) {
                        setState(() {
                          _isActive = next;
                        });
                      },
              ),
              const SizedBox(width: 8),
              Text(_isActive ? '사용' : '미사용'),
            ],
          ),
        ),
        const SizedBox(height: 16),
        _CustomerFormField(
          label: '비고',
          child: ShadTextarea(
            controller: _noteController,
            minHeight: 96,
            maxHeight: 200,
          ),
        ),
        if (widget.customer != null) ...[
          const SizedBox(height: 20),
          Text(
            '생성일시: ${_formatDateTime(widget.customer!.createdAt)}',
            style: theme.textTheme.small,
          ),
          const SizedBox(height: 4),
          Text(
            '수정일시: ${_formatDateTime(widget.customer!.updatedAt)}',
            style: theme.textTheme.small,
          ),
        ],
        if (_submitError != null) ...[
          const SizedBox(height: 16),
          Text(
            _submitError!,
            style: theme.textTheme.small.copyWith(color: destructiveColor),
          ),
        ],
        const SizedBox(height: 20),
        Align(
          alignment: Alignment.centerRight,
          child: ShadButton(
            onPressed: _isSubmitting ? null : _handleSubmit,
            child: Text(_isEdit ? '저장' : '등록'),
          ),
        ),
      ],
    );
  }

  Future<void> _openPostalSearch() async {
    final keyword = _zipcodeController.text.trim();
    final result = await showPostalSearchDialog(
      context,
      initialKeyword: keyword.isEmpty ? null : keyword,
    );
    if (result == null) {
      return;
    }
    _isApplyingPostalSelection = true;
    _zipcodeController
      ..text = result.zipcode
      ..selection = TextSelection.collapsed(offset: result.zipcode.length);
    _isApplyingPostalSelection = false;
    setState(() {
      _selectedPostal = result;
      if (result.fullAddress.isNotEmpty) {
        _addressController
          ..text = result.fullAddress
          ..selection = TextSelection.collapsed(
            offset: _addressController.text.length,
          );
      }
      _zipcodeError = null;
    });
  }

  void _handleZipcodeChanged() {
    if (_isApplyingPostalSelection) {
      return;
    }
    final text = _zipcodeController.text.trim();
    if (text.isEmpty) {
      if (_selectedPostal != null) {
        setState(() {
          _selectedPostal = null;
        });
      }
      if (_zipcodeError != null) {
        setState(() {
          _zipcodeError = null;
        });
      }
      return;
    }
    if (_selectedPostal != null && _selectedPostal!.zipcode != text) {
      setState(() {
        _selectedPostal = null;
      });
    }
    if (_zipcodeError != null) {
      setState(() {
        _zipcodeError = null;
      });
    }
  }

  Future<void> _handleSubmit() async {
    final code = _codeController.text.trim();
    final name = _nameController.text.trim();
    final contact = _contactController.text.trim();
    final email = _emailController.text.trim();
    final mobile = _mobileController.text.trim();
    final zipcode = _zipcodeController.text.trim();
    final address = _addressController.text.trim();
    final note = _noteController.text.trim();

    if (!_isPartner && !_isGeneral) {
      setState(() {
        _isGeneral = true;
      });
    }

    setState(() {
      _codeError = code.isEmpty ? '고객사코드를 입력하세요.' : null;
      _nameError = name.isEmpty ? '고객사명을 입력하세요.' : null;
      _typeError = (!_isPartner && !_isGeneral)
          ? '파트너/일반 중 하나 이상 선택하세요.'
          : null;
      _zipcodeError = zipcode.isNotEmpty && _selectedPostal == null
          ? '우편번호 검색으로 주소를 선택하세요.'
          : null;
      _submitError = null;
    });

    if (_codeError != null ||
        _nameError != null ||
        _typeError != null ||
        _zipcodeError != null) {
      return;
    }

    setState(() {
      _isSubmitting = true;
    });

    final input = CustomerInput(
      customerCode: code,
      customerName: name,
      contactName: contact.isEmpty ? null : contact,
      isPartner: _isPartner,
      isGeneral: _isGeneral,
      email: email.isEmpty ? null : email,
      mobileNo: mobile.isEmpty ? null : mobile,
      zipcode: zipcode.isEmpty ? null : zipcode,
      addressDetail: address.isEmpty ? null : address,
      isActive: _isActive,
      note: note.isEmpty ? null : note,
    );

    final navigator = Navigator.of(context, rootNavigator: true);
    final result = await widget.onSubmit(input);

    if (!mounted) {
      return;
    }

    setState(() {
      _isSubmitting = false;
      _submitError = result == null ? '요청 처리에 실패했습니다.' : null;
    });

    if (result != null && navigator.mounted) {
      navigator.pop(result);
    }
  }

  String _formatDateTime(DateTime? value) {
    if (value == null) {
      return '-';
    }
    return value.toLocal().toIso8601String();
  }
}

/// 고객 폼 필드의 레이블·컨텐츠 배치를 담당한다.
class _CustomerFormField extends StatelessWidget {
  const _CustomerFormField({required this.label, required this.child});

  final String label;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(label, style: theme.textTheme.small),
        const SizedBox(height: 6),
        child,
      ],
    );
  }
}

String _resolveType(Customer customer) {
  if (customer.isPartner && customer.isGeneral) {
    return '파트너/일반';
  }
  if (customer.isPartner) {
    return '파트너';
  }
  if (customer.isGeneral) {
    return '일반';
  }
  return '-';
}

String _resolveAddress(Customer customer) {
  final zipcode = customer.zipcode;
  final detail = customer.addressDetail;
  if (zipcode == null && (detail == null || detail.isEmpty)) {
    return '-';
  }
  final buffer = StringBuffer();
  if (zipcode != null) {
    buffer.write(zipcode.zipcode);
    final components = [
      zipcode.sido,
      zipcode.sigungu,
      zipcode.roadName,
    ].whereType<String>().where((value) => value.isNotEmpty);
    if (components.isNotEmpty) {
      buffer.write(' (${components.join(' ')})');
    }
  }
  if (detail != null && detail.isNotEmpty) {
    if (buffer.isNotEmpty) {
      buffer.write('\n');
    }
    buffer.write(detail);
  }
  return buffer.isEmpty ? '-' : buffer.toString();
}
