import 'dart:async';

import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart' as lucide;
import 'package:shadcn_ui/shadcn_ui.dart';

import 'keyboard_shortcuts.dart';

const double _kDialogMaxWidth = 640;
const double _kDialogMobileBreakpoint = 640;
const EdgeInsets _kDialogDesktopInset = EdgeInsets.symmetric(
  horizontal: 24,
  vertical: 32,
);
const EdgeInsets _kDialogBodyPadding = EdgeInsets.symmetric(
  horizontal: 20,
  vertical: 24,
);

/// 공통 모달 다이얼로그 scaffold.
///
/// - ShadCard 기반으로 헤더/본문/푸터 영역을 분리한다.
/// - 모바일에서는 전체 화면으로 확장되며 시스템 인셋을 자동 반영한다.
/// - 닫기 버튼 및 사용자 정의 액션을 지원한다.
class SuperportDialog extends StatelessWidget {
  const SuperportDialog({
    super.key,
    required this.title,
    this.description,
    this.child = const SizedBox.shrink(),
    this.primaryAction,
    this.secondaryAction,
    this.mobileFullscreen = true,
    this.constraints,
    this.actions,
    this.contentPadding,
    this.header,
    this.footer,
    this.showCloseButton = true,
    this.onClose,
    this.scrollable = true,
    this.insetPadding,
    this.onSubmit,
    this.enableFocusTrap = true,
    this.headerActions,
  });

  final String title;
  final String? description;
  final Widget child;
  final Widget? primaryAction;
  final Widget? secondaryAction;
  final bool mobileFullscreen;
  final BoxConstraints? constraints;
  final List<Widget>? actions;
  final EdgeInsetsGeometry? contentPadding;
  final Widget? header;
  final Widget? footer;
  final bool showCloseButton;
  final VoidCallback? onClose;
  final bool scrollable;
  final EdgeInsets? insetPadding;
  final FutureOr<void> Function()? onSubmit;
  final bool enableFocusTrap;

  /// 헤더 우측에 표시할 추가 액션 위젯 목록.
  ///
  /// - 닫기 버튼 왼쪽에 순서대로 렌더링된다.
  final List<Widget>? headerActions;

  /// 공통 다이얼로그를 노출하는 헬퍼. `showDialog`와 동일하게 동작한다.
  static Future<T?> show<T>({
    required BuildContext context,
    required SuperportDialog dialog,
    bool barrierDismissible = true,
  }) {
    return showDialog<T>(
      context: context,
      barrierDismissible: barrierDismissible,
      builder: (_) => dialog,
    );
  }

  @override
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);
    final theme = ShadTheme.of(context);
    final screenWidth = mediaQuery.size.width;
    final isMobile = screenWidth <= _kDialogMobileBreakpoint;

    void handleClose() {
      if (onClose != null) {
        onClose!();
        return;
      }
      Navigator.of(context).maybePop();
    }

    final resolvedHeader =
        header ??
        _SuperportDialogHeader(
          title: title,
          description: description,
          showCloseButton: showCloseButton,
          onClose: handleClose,
          actions: headerActions,
        );
    final resolvedFooter = footer ?? _buildFooter(context);

    final card = ShadCard(
      padding: EdgeInsets.zero,
      child: ClipRRect(
        borderRadius: theme.radius,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            resolvedHeader,
            Flexible(
              child: _DialogBody(
                padding: contentPadding ?? _kDialogBodyPadding,
                scrollable: scrollable,
                child: child,
              ),
            ),
            if (resolvedFooter != null) resolvedFooter,
          ],
        ),
      ),
    );

    final resolvedConstraints =
        constraints ??
        BoxConstraints(
          maxWidth: isMobile && mobileFullscreen
              ? screenWidth
              : _kDialogMaxWidth,
          minWidth: isMobile && mobileFullscreen ? screenWidth : 360,
        );

    final resolvedInset =
        insetPadding ??
        (isMobile && mobileFullscreen ? EdgeInsets.zero : _kDialogDesktopInset);

    return Dialog(
      insetPadding: resolvedInset,
      backgroundColor: Colors.transparent,
      surfaceTintColor: Colors.transparent,
      child: SafeArea(
        child: AnimatedPadding(
          duration: const Duration(milliseconds: 120),
          curve: Curves.easeOut,
          padding: mediaQuery.viewInsets,
          child: ConstrainedBox(
            constraints: resolvedConstraints,
            child: DialogKeyboardShortcuts(
              onEscape: handleClose,
              onSubmit: onSubmit,
              enableFocusTrap: enableFocusTrap,
              child: card,
            ),
          ),
        ),
      ),
    );
  }

  Widget? _buildFooter(BuildContext context) {
    if (actions != null) {
      final filtered = actions!.whereType<Widget>().toList();
      if (filtered.isEmpty) {
        return null;
      }
      return _DialogFooter(children: filtered);
    }

    final fallback = <Widget>[
      if (secondaryAction != null) secondaryAction!,
      primaryAction ??
          ShadButton.ghost(
            onPressed:
                onClose ??
                () => Navigator.of(context, rootNavigator: true).maybePop(),
            child: const Text('닫기'),
          ),
    ].whereType<Widget>().toList();

    if (fallback.isEmpty) {
      return null;
    }

    return _DialogFooter(children: fallback);
  }
}

class _DialogBody extends StatelessWidget {
  const _DialogBody({
    required this.child,
    required this.padding,
    required this.scrollable,
  });

  final Widget child;
  final EdgeInsetsGeometry padding;
  final bool scrollable;

  @override
  Widget build(BuildContext context) {
    final content = Padding(padding: padding, child: child);

    if (!scrollable) {
      return content;
    }

    return SingleChildScrollView(child: content);
  }
}

class _DialogFooter extends StatelessWidget {
  const _DialogFooter({required this.children});

  final List<Widget> children;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
      decoration: BoxDecoration(
        color: ShadTheme.of(context).colorScheme.muted,
        border: Border(
          top: BorderSide(color: ShadTheme.of(context).colorScheme.border),
        ),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          for (var i = 0; i < children.length; i++)
            Padding(
              padding: EdgeInsets.only(left: i == 0 ? 0 : 12),
              child: children[i],
            ),
        ],
      ),
    );
  }
}

class _SuperportDialogHeader extends StatelessWidget {
  const _SuperportDialogHeader({
    required this.title,
    this.description,
    required this.showCloseButton,
    required this.onClose,
    this.actions,
  });

  final String title;
  final String? description;
  final bool showCloseButton;
  final VoidCallback onClose;
  final List<Widget>? actions;

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
      decoration: BoxDecoration(
        color: theme.colorScheme.card,
        border: Border(bottom: BorderSide(color: theme.colorScheme.border)),
      ),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(title, style: theme.textTheme.h3),
                if (description != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 8),
                    child: Text(description!, style: theme.textTheme.muted),
                  ),
              ],
            ),
          ),
          if (actions != null && actions!.isNotEmpty)
            Padding(
              padding: const EdgeInsets.only(right: 4, top: 2),
              child: Wrap(spacing: 8, runSpacing: 8, children: actions!),
            ),
          if (showCloseButton)
            IconButton(
              icon: const Icon(lucide.LucideIcons.x, size: 18),
              tooltip: '닫기',
              onPressed: onClose,
            ),
        ],
      ),
    );
  }
}

/// 페이지에서 반복되는 호출 패턴을 줄이기 위한 편의 함수.
Future<T?> showSuperportDialog<T>({
  required BuildContext context,
  required String title,
  String? description,
  required Widget body,
  Widget? primaryAction,
  Widget? secondaryAction,
  List<Widget>? actions,
  bool mobileFullscreen = true,
  bool barrierDismissible = true,
  BoxConstraints? constraints,
  EdgeInsetsGeometry? contentPadding,
  bool scrollable = true,
  bool showCloseButton = true,
  VoidCallback? onClose,
  FutureOr<void> Function()? onSubmit,
  bool enableFocusTrap = true,
  List<Widget>? headerActions,
}) {
  return SuperportDialog.show<T>(
    context: context,
    barrierDismissible: barrierDismissible,
    dialog: SuperportDialog(
      title: title,
      description: description,
      primaryAction: primaryAction,
      secondaryAction: secondaryAction,
      actions: actions,
      constraints: constraints,
      mobileFullscreen: mobileFullscreen,
      contentPadding: contentPadding,
      scrollable: scrollable,
      showCloseButton: showCloseButton,
      onClose: onClose,
      onSubmit: onSubmit,
      enableFocusTrap: enableFocusTrap,
      headerActions: headerActions,
      child: body,
    ),
  );
}
