import 'package:flutter/material.dart';
import 'package:kasy_kit/core/theme/theme.dart';

// ─────────────────────────────────────────────────────────────────────────────
// Data model
// ─────────────────────────────────────────────────────────────────────────────

/// Data model for a single tab item.
class KasyTabItem {
  final String label;
  final IconData? icon;
  final bool enabled;

  const KasyTabItem({
    required this.label,
    this.icon,
    this.enabled = true,
  });
}

// ─────────────────────────────────────────────────────────────────────────────
// Enums
// ─────────────────────────────────────────────────────────────────────────────

/// Visual style for [KasyTabs].
enum KasyTabsVariant {
  /// Sliding white pill on a gray container.
  primary,

  /// Blue underline indicator with a bottom divider.
  secondary,
}

/// Sizing mode for [KasyTabs].
enum KasyTabsMode {
  /// Wraps content (intrinsic width tabs).
  hug,

  /// Each tab stretches to fill the available width equally.
  fill,
}

// ─────────────────────────────────────────────────────────────────────────────
// KasyTabs
// ─────────────────────────────────────────────────────────────────────────────

/// Animated tab bar with primary (pill) and secondary (underline) variants.
///
/// Usage:
/// ```dart
/// KasyTabs(
///   tabs: ['General', 'Appearance', 'Notifications'],
///   selectedIndex: _index,
///   onTabSelected: (i) => setState(() => _index = i),
/// )
/// ```
///
/// Supports [KasyTabItem] for per-tab icons and disabled state. The short-form
/// constructor accepts plain [String] labels.
class KasyTabs extends StatefulWidget {
  /// Plain-string convenience constructor.
  ///
  /// Converts each string to a [KasyTabItem] with default settings.
  KasyTabs({
    super.key,
    required List<String> tabs,
    required this.selectedIndex,
    required this.onTabSelected,
    this.variant = KasyTabsVariant.primary,
    this.mode = KasyTabsMode.hug,
  }) : items = tabs.map((l) => KasyTabItem(label: l)).toList();

  /// Full constructor accepting [KasyTabItem] instances (supports icons/disabled).
  const KasyTabs.items({
    super.key,
    required this.items,
    required this.selectedIndex,
    required this.onTabSelected,
    this.variant = KasyTabsVariant.primary,
    this.mode = KasyTabsMode.hug,
  });

  final List<KasyTabItem> items;

  /// Index of the currently selected tab.
  final int selectedIndex;

  /// Called when the user taps an enabled tab.
  final ValueChanged<int> onTabSelected;

  final KasyTabsVariant variant;
  final KasyTabsMode mode;

  @override
  State<KasyTabs> createState() => _KasyTabsState();
}

class _KasyTabsState extends State<KasyTabs> {
  // One GlobalKey per tab to measure position/size after layout.
  late List<GlobalKey> _keys;

  // Indicator geometry (left offset, width) resolved from measured keys.
  double _indicatorLeft = 0;
  double _indicatorWidth = 0;

  // Whether we have a valid measurement yet.
  bool _measured = false;

  @override
  void initState() {
    super.initState();
    _keys = List.generate(
      widget.items.length,
      (_) => GlobalKey(),
    );
    WidgetsBinding.instance.addPostFrameCallback((_) => _measure());
  }

  @override
  void didUpdateWidget(KasyTabs old) {
    super.didUpdateWidget(old);
    // Rebuild keys list if tab count changes.
    if (old.items.length != widget.items.length) {
      _keys = List.generate(
        widget.items.length,
        (_) => GlobalKey(),
      );
      _measured = false;
    }
    // Re-measure whenever selected index changes or keys were rebuilt.
    WidgetsBinding.instance.addPostFrameCallback((_) => _measure());
  }

  void _measure() {
    if (!mounted) return;
    if (widget.items.isEmpty) return;

    final int clampedIndex = widget.selectedIndex.clamp(
      0,
      widget.items.length - 1,
    );

    final RenderBox? containerBox =
        context.findRenderObject() as RenderBox?;
    if (containerBox == null) return;

    final GlobalKey key = _keys[clampedIndex];
    final RenderBox? tabBox =
        key.currentContext?.findRenderObject() as RenderBox?;
    if (tabBox == null) return;

    final Offset tabOffset = tabBox.localToGlobal(
      Offset.zero,
      ancestor: containerBox,
    );

    final double newLeft = tabOffset.dx;
    final double newWidth = tabBox.size.width;

    if (!_measured ||
        (_indicatorLeft - newLeft).abs() > 0.1 ||
        (_indicatorWidth - newWidth).abs() > 0.1) {
      setState(() {
        _indicatorLeft = newLeft;
        _indicatorWidth = newWidth;
        _measured = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    if (widget.items.isEmpty) return const SizedBox.shrink();

    return widget.variant == KasyTabsVariant.primary
        ? _buildPrimary(context)
        : _buildSecondary(context);
  }

  // ── Primary (pill indicator) ───────────────────────────────────────────────

  Widget _buildPrimary(BuildContext context) {
    final KasyColors c = context.colors;
    final bool isDark = context.isDark;

    return DecoratedBox(
      decoration: BoxDecoration(
        color: c.avatarFallbackFill,
        borderRadius: BorderRadius.circular(KasyRadius.full),
      ),
      child: Padding(
        padding: const EdgeInsets.all(4),
        child: Stack(
          children: [
            // Animated pill background.
            if (_measured)
              AnimatedPositioned(
                duration: const Duration(milliseconds: 250),
                curve: Curves.easeInOut,
                left: _indicatorLeft,
                top: 0,
                bottom: 0,
                width: _indicatorWidth,
                child: DecoratedBox(
                  decoration: BoxDecoration(
                    color: c.surface,
                    borderRadius: BorderRadius.circular(KasyRadius.full),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withValues(
                          alpha: isDark ? 0.18 : 0.08,
                        ),
                        blurRadius: 8,
                        offset: const Offset(0, 2),
                      ),
                      BoxShadow(
                        color: Colors.black.withValues(
                          alpha: isDark ? 0.10 : 0.04,
                        ),
                        spreadRadius: 1,
                      ),
                    ],
                  ),
                ),
              ),
            // Tab labels (on top of the pill).
            Row(
              mainAxisSize: widget.mode == KasyTabsMode.fill
                  ? MainAxisSize.max
                  : MainAxisSize.min,
              children: List.generate(widget.items.length, (i) {
                final KasyTabItem item = widget.items[i];
                final bool selected = i == widget.selectedIndex;
                return _PrimaryTab(
                  key: _keys[i],
                  item: item,
                  selected: selected,
                  expand: widget.mode == KasyTabsMode.fill,
                  onTap: item.enabled ? () => widget.onTabSelected(i) : null,
                );
              }),
            ),
          ],
        ),
      ),
    );
  }

  // ── Secondary (underline indicator) ───────────────────────────────────────

  Widget _buildSecondary(BuildContext context) {
    final KasyColors c = context.colors;

    return Stack(
      clipBehavior: Clip.none,
      children: [
        // Full-width bottom divider.
        Positioned(
          left: 0,
          right: 0,
          bottom: 0,
          child: DecoratedBox(
            decoration: BoxDecoration(
              color: c.outline.withValues(alpha: 0.2),
            ),
            child: const SizedBox(height: 1),
          ),
        ),
        // Animated underline indicator.
        if (_measured)
          AnimatedPositioned(
            duration: const Duration(milliseconds: 250),
            curve: Curves.easeInOut,
            left: _indicatorLeft,
            bottom: 0,
            width: _indicatorWidth,
            height: 2,
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: c.primary,
                borderRadius: BorderRadius.circular(1),
              ),
            ),
          ),
        // Tab labels.
        Row(
          mainAxisSize: widget.mode == KasyTabsMode.fill
              ? MainAxisSize.max
              : MainAxisSize.min,
          children: List.generate(widget.items.length, (i) {
            final KasyTabItem item = widget.items[i];
            final bool selected = i == widget.selectedIndex;
            return _SecondaryTab(
              key: _keys[i],
              item: item,
              selected: selected,
              expand: widget.mode == KasyTabsMode.fill,
              onTap: item.enabled ? () => widget.onTabSelected(i) : null,
            );
          }),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// Internal tab widgets
// ─────────────────────────────────────────────────────────────────────────────

class _PrimaryTab extends StatelessWidget {
  const _PrimaryTab({
    super.key,
    required this.item,
    required this.selected,
    required this.expand,
    required this.onTap,
  });

  final KasyTabItem item;
  final bool selected;
  final bool expand;
  final VoidCallback? onTap;

  Widget _tabContent(BuildContext context) {
    final KasyColors c = context.colors;
    final bool disabled = !item.enabled;

    return GestureDetector(
      onTap: onTap,
      behavior: HitTestBehavior.opaque,
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (item.icon != null) ...[
              Opacity(
                opacity: disabled ? 0.4 : 1.0,
                child: Icon(
                  item.icon,
                  size: 16,
                  color: selected ? c.onSurface : c.muted,
                ),
              ),
              const SizedBox(width: 6),
            ],
            Opacity(
              opacity: disabled ? 0.4 : 1.0,
              child: Text(
                item.label,
                style: context.textTheme.labelLarge?.copyWith(
                  color: selected ? c.onSurface : c.muted,
                  fontWeight: selected ? FontWeight.w500 : FontWeight.w400,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final Widget inner = _tabContent(context);
    return expand ? Expanded(child: inner) : inner;
  }
}

class _SecondaryTab extends StatelessWidget {
  const _SecondaryTab({
    super.key,
    required this.item,
    required this.selected,
    required this.expand,
    required this.onTap,
  });

  final KasyTabItem item;
  final bool selected;
  final bool expand;
  final VoidCallback? onTap;

  Widget _tabContent(BuildContext context) {
    final KasyColors c = context.colors;
    final bool disabled = !item.enabled;

    return GestureDetector(
      onTap: onTap,
      behavior: HitTestBehavior.opaque,
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (item.icon != null) ...[
              Opacity(
                opacity: disabled ? 0.4 : 1.0,
                child: Icon(
                  item.icon,
                  size: 16,
                  color: selected ? c.onSurface : c.muted,
                ),
              ),
              const SizedBox(width: 6),
            ],
            Opacity(
              opacity: disabled ? 0.4 : 1.0,
              child: Text(
                item.label,
                style: context.textTheme.labelLarge?.copyWith(
                  color: selected ? c.onSurface : c.muted,
                  fontWeight: selected ? FontWeight.w600 : FontWeight.w400,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final Widget inner = _tabContent(context);
    return expand ? Expanded(child: inner) : inner;
  }
}
