import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../api_client.dart';
import '../widgets/payment_overview.dart';
import '../widgets/payment_bottom_sheet.dart' show showPaymentBottomSheet, showTransactionStatusDialog;

// ── Design tokens (design.json) ──────────────────────────────────────────────
class _Brand {
  static const bg = Color(0xFF0F1114);
  static const card = Color(0xFF21252D);
  static const amber = Color(0xFFFF9500);
  static const textPrimary = Color(0xFFF2F2F2);
  static const textMuted = Color(0xFF8A8F99);
  static const divider = Color(0xFF2C3040);
  static const red = Color(0xFFFF4545);
  // Rescue+ service accent (design.json service_accent_colors.rescue)
  static const rescueAccent = Color(0xFFFF4545);
  static const rescueGlow = Color(0x22FF4545);

  static const screenPadding = 20.0;
  static const sectionGap = 24.0;
  static const cardRadius = 16.0;
  static const buttonRadius = 12.0;
  static const iconBadgeRadius = 9.0;
}

// ─────────────────────────────────────────────────────────────────────────────

class RescueFlowScreen extends StatefulWidget {
  const RescueFlowScreen({super.key, required this.onUnauthorized, this.onOrderCreated});

  final VoidCallback onUnauthorized;
  final VoidCallback? onOrderCreated;

  @override
  State<RescueFlowScreen> createState() => _RescueFlowScreenState();
}

class _RescueFlowScreenState extends State<RescueFlowScreen> {
  late Dio _dio;
  List<dynamic> _services = [];
  List<dynamic> _addresses = [];
  Map? _config;
  int _step = 0;
  Map? _selectedService;
  Map? _selectedAddress;
  Map? _user;
  int _pointsToUse = 0;
  bool _loading = false;
  String? _error;

  static const _totalSteps = 3;

  @override
  void initState() {
    super.initState();
    _dio = createApiClient(() => widget.onUnauthorized());
    _loadInitial();
  }

  Future<void> _loadInitial() async {
    setState(() => _loading = true);
    try {
      final r = await Future.wait([
        _dio.get('/api/rescue-services'),
        _dio.get('/api/addresses'),
        _dio.get('/api/config'),
        _dio.get('/api/auth/me'),
      ]);
      if (!mounted) return;
      setState(() {
        _services = (r[0].data is Map && r[0].data['data'] is List) ? List.from(r[0].data['data'] as List) : [];
        _addresses = (r[1].data is Map && r[1].data['data'] is List) ? List.from(r[1].data['data'] as List) : [];
        _config = (r[2].data is Map && r[2].data['data'] != null) ? r[2].data['data'] as Map : null;
        _user = (r[3].data is Map && r[3].data['data'] != null) ? r[3].data['data'] as Map : null;
        _loading = false;
      });
    } catch (e) {
      if (e is DioException && e.response?.statusCode == 401) widget.onUnauthorized();
      if (mounted) setState(() => _loading = false);
    }
  }

  double get _serviceFee => (_config != null && _config!['service_fee'] != null) ? (double.tryParse(_config!['service_fee'].toString()) ?? 0) : 0;
  double get _deliveryFee => (_config != null && _config!['delivery_fee'] != null) ? (double.tryParse(_config!['delivery_fee'].toString()) ?? 0) : 0;
  double get _subtotal => _selectedService != null ? (double.tryParse(_selectedService!['price'].toString()) ?? 0) : 0;
  double get _total => _subtotal + _serviceFee + _deliveryFee;

  int get _pointsBalance =>
      (_user != null && _user!['points_balance'] != null)
          ? (int.tryParse(_user!['points_balance'].toString()) ?? 0)
          : 0;
  int get _maxRedeemablePoints {
    final totalInt = _total.floor();
    if (totalInt <= 0 || _pointsBalance <= 0) return 0;
    return totalInt.clamp(0, _pointsBalance);
  }
  double get _amountAfterPoints {
    final use = _pointsToUse.clamp(0, _maxRedeemablePoints);
    return (_total - use).clamp(0.0, double.infinity);
  }

  String _fmt(double v) {
    final parts = v.toStringAsFixed(0).split('');
    final buf = StringBuffer();
    for (int i = 0; i < parts.length; i++) {
      if (i > 0 && (parts.length - i) % 3 == 0) buf.write(',');
      buf.write(parts[i]);
    }
    return buf.toString();
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      statusBarIconBrightness: Brightness.light,
    ));
    return Scaffold(
      backgroundColor: _Brand.bg,
      appBar: AppBar(
        backgroundColor: _Brand.bg,
        elevation: 0,
        scrolledUnderElevation: 0,
        title: const Text(
          'RESCUE+',
          style: TextStyle(
            fontFamily: 'RobotoMono',
            fontSize: 15,
            fontWeight: FontWeight.w700,
            letterSpacing: 3,
            color: _Brand.textPrimary,
          ),
        ),
        leading: Padding(
          padding: const EdgeInsets.only(left: 12),
          child: GestureDetector(
            onTap: () => Navigator.of(context).pop(),
            child: Container(
              padding: const EdgeInsets.all(10),
              decoration: BoxDecoration(
                color: _Brand.card,
                borderRadius: BorderRadius.circular(_Brand.iconBadgeRadius),
                border: Border.all(color: _Brand.divider),
              ),
              child: const Icon(Icons.arrow_back_ios_new, size: 13, color: _Brand.textMuted),
            ),
          ),
        ),
        leadingWidth: 56,
      ),
      body: _loading && _services.isEmpty
          ? const Center(
              child: SizedBox(
                width: 32,
                height: 32,
                child: CircularProgressIndicator(
                  strokeWidth: 2.5,
                  valueColor: AlwaysStoppedAnimation(_Brand.amber),
                ),
              ),
            )
          : SingleChildScrollView(
              padding: const EdgeInsets.fromLTRB(
                _Brand.screenPadding,
                8,
                _Brand.screenPadding,
                40,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Text(
                    'STEP ${_step + 1} OF $_totalSteps',
                    style: const TextStyle(
                      fontSize: 10,
                      fontWeight: FontWeight.w700,
                      letterSpacing: 2.5,
                      color: _Brand.amber,
                    ),
                  ),
                  const SizedBox(height: 12),
                  if (_error != null) ...[
                    _ErrorBanner(_error!),
                    const SizedBox(height: _Brand.sectionGap),
                  ],
                  if (_step == 0) _buildServiceStep(),
                  if (_step == 1) _buildAddressStep(),
                  if (_step == 2) _buildPaymentStep(),
                ],
              ),
            ),
    );
  }

  Widget _buildServiceStep() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        const _SectionLabel('SELECT RESCUE+ SERVICE'),
        const SizedBox(height: 12),
        ..._services.map<Widget>((s) {
          final m = s is Map ? s : {};
          final name = m['name']?.toString() ?? 'Service';
          final price = double.tryParse(m['price'].toString()) ?? 0;
          final selected = _selectedService == m;
          return Padding(
            padding: const EdgeInsets.only(bottom: 12),
            child: _SelectableTile(
              selected: selected,
              accentColor: _Brand.rescueAccent,
              glowColor: _Brand.rescueGlow,
              onTap: () => setState(() => _selectedService = m),
              leading: Container(
                width: 40,
                height: 40,
                decoration: BoxDecoration(
                  color: _Brand.rescueGlow,
                  borderRadius: BorderRadius.circular(_Brand.iconBadgeRadius),
                  border: Border.all(color: _Brand.rescueAccent.withOpacity(0.35)),
                ),
                child: const Icon(Icons.emergency_rounded, color: _Brand.rescueAccent, size: 20),
              ),
              title: name,
              subtitle: '${_fmt(price)} UGX',
            ),
          );
        }),
        const SizedBox(height: _Brand.sectionGap),
        _PrimaryButton(
          label: 'NEXT',
          onPressed: _selectedService == null ? null : () => setState(() => _step = 1),
        ),
      ],
    );
  }

  Widget _buildAddressStep() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        const _SectionLabel('SELECT LOCATION'),
        const SizedBox(height: 12),
        if (_addresses.isEmpty)
          const Padding(
            padding: EdgeInsets.only(bottom: 12),
            child: Text(
              'No addresses. Add one in Settings.',
              style: TextStyle(color: _Brand.textMuted, fontSize: 13),
            ),
          )
        else
          ..._addresses.map<Widget>((a) {
            final m = a is Map ? a : {};
            final selected = _selectedAddress == m;
            final name = m['address_name']?.toString();
            final lat = m['latitude'];
            final lng = m['longitude'];
            final plusCode = m['plus_code']?.toString();
            final latStr = lat != null && lat is num ? (lat).toDouble().toStringAsFixed(5) : (lat?.toString() ?? '—');
            final lngStr = lng != null && lng is num ? (lng).toDouble().toStringAsFixed(5) : (lng?.toString() ?? '—');
            final subtitle = (plusCode?.isNotEmpty == true ? plusCode : '$latStr, $lngStr') ?? '';
            return Padding(
              padding: const EdgeInsets.only(bottom: 12),
              child: _SelectableTile(
                selected: selected,
                accentColor: _Brand.rescueAccent,
                glowColor: _Brand.rescueGlow,
                onTap: () => setState(() => _selectedAddress = m),
                leading: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                    color: _Brand.rescueGlow,
                    borderRadius: BorderRadius.circular(_Brand.iconBadgeRadius),
                    border: Border.all(color: _Brand.rescueAccent.withOpacity(0.35)),
                  ),
                  child: const Icon(Icons.location_on_rounded, color: _Brand.rescueAccent, size: 20),
                ),
                title: name?.isNotEmpty == true ? name! : 'Saved location',
                subtitle: subtitle,
              ),
            );
          }),
        const SizedBox(height: _Brand.sectionGap),
        _PrimaryButton(
          label: 'NEXT',
          onPressed: _addresses.isEmpty || _selectedAddress == null ? null : () => setState(() => _step = 2),
        ),
      ],
    );
  }

  Widget _buildPaymentStep() {
    final addr = _selectedAddress != null
        ? (_selectedAddress!['address_name']?.toString() ??
            _selectedAddress!['plus_code']?.toString() ??
            '${_selectedAddress!['latitude']}, ${_selectedAddress!['longitude']}')
        : '';
    final svc = 'Rescue+ ${_selectedService?['name']}';
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        const _SectionLabel('JAMBO POINTS'),
        const SizedBox(height: 12),
        PointsRedeemSection(
          pointsBalance: _pointsBalance,
          maxRedeemable: _maxRedeemablePoints,
          pointsToUse: _pointsToUse,
          totalUgx: _total,
          onChanged: (v) => setState(() => _pointsToUse = v),
        ),
        const SizedBox(height: _Brand.sectionGap),
        PaymentOverview(
          data: PaymentOverviewData(
            addressSummary: addr,
            serviceSummary: svc,
            subtotal: _subtotal,
            serviceFee: _serviceFee,
            deliveryFee: _deliveryFee,
            total: _amountAfterPoints,
            pointsDiscount: _pointsToUse.toDouble(),
            pointsUsed: _pointsToUse,
          ),
          onMakePayment: () => showPaymentBottomSheet(
            context,
            amount: _amountAfterPoints,
            dio: _dio,
            callbackBaseUrl: baseUrl,
            onSuccess: () {
              _createOrder().then((success) {
                if (!mounted) return;
                showTransactionStatusDialog(
                  context,
                  success: success,
                  onDone: () {
                    Navigator.pop(context, true);
                    widget.onOrderCreated?.call();
                  },
                );
              });
            },
          ),
          onCompleteOrder: _amountAfterPoints <= 0
              ? () {
                  _createOrder().then((success) {
                    if (!mounted) return;
                    showTransactionStatusDialog(
                      context,
                      success: success,
                      onDone: () {
                        Navigator.pop(context, true);
                        widget.onOrderCreated?.call();
                      },
                    );
                  });
                }
              : null,
        ),
      ],
    );
  }

  Future<bool> _createOrder() async {
    setState(() { _loading = true; _error = null; });
    try {
      await _dio.post('/api/orders', data: {
        'order_type': 'rescue',
        'location_id': _selectedAddress!['id'],
        'rescue_service_id': _selectedService!['id'],
        'total_amount': _total,
        'points_used': _pointsToUse,
      });
      // Order created — always report success so dialog is correct even if setState fails
      if (!mounted) return false;
      try {
        if (mounted) setState(() => _loading = false);
      } catch (_) {}
      return true;
    } catch (e) {
      if (e is DioException && e.response?.statusCode == 401) widget.onUnauthorized();
      if (mounted) {
        setState(() {
          _loading = false;
          String msg = 'Failed to place order';
          if (e is DioException && e.response?.data is Map) {
            final data = e.response!.data as Map;
            final err = data['error'];
            if (err is Map && err['message'] != null) msg = err['message'].toString();
            else if (data['message'] != null) msg = data['message'].toString();
          }
          _error = msg;
        });
      }
      return false;
    }
  }
}

// ── Section label (design.json section_label) ─────────────────────────────────
class _SectionLabel extends StatelessWidget {
  final String text;
  const _SectionLabel(this.text);

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: const TextStyle(
        fontSize: 10,
        fontWeight: FontWeight.w600,
        letterSpacing: 2.5,
        color: _Brand.textMuted,
      ),
    );
  }
}

// ── Error banner (design.json error_banner) ────────────────────────────────────
class _ErrorBanner extends StatelessWidget {
  final String message;
  const _ErrorBanner(this.message);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
      decoration: BoxDecoration(
        color: _Brand.red.withOpacity(0.12),
        borderRadius: BorderRadius.circular(10),
        border: Border.all(color: _Brand.red.withOpacity(0.4)),
      ),
      child: Row(
        children: [
          const Icon(Icons.warning_amber_rounded, color: _Brand.red, size: 18),
          const SizedBox(width: 10),
          Expanded(
            child: Text(
              message,
              style: const TextStyle(color: _Brand.red, fontSize: 13, height: 1.4),
            ),
          ),
        ],
      ),
    );
  }
}

// ── Selectable tile (design.json: no RadioListTile, custom card) ──────────────
class _SelectableTile extends StatelessWidget {
  final bool selected;
  final Color accentColor;
  final Color glowColor;
  final VoidCallback onTap;
  final Widget leading;
  final String title;
  final String subtitle;

  const _SelectableTile({
    required this.selected,
    required this.accentColor,
    required this.glowColor,
    required this.onTap,
    required this.leading,
    required this.title,
    required this.subtitle,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        padding: const EdgeInsets.all(18),
        decoration: BoxDecoration(
          color: _Brand.card,
          borderRadius: BorderRadius.circular(_Brand.cardRadius),
          border: Border.all(
            color: selected ? accentColor.withOpacity(0.4) : _Brand.divider,
            width: selected ? 1.5 : 1,
          ),
        ),
        child: Row(
          children: [
            leading,
            const SizedBox(width: 12),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    title,
                    style: const TextStyle(
                      color: _Brand.textPrimary,
                      fontSize: 15,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    subtitle,
                    style: const TextStyle(
                      color: _Brand.textMuted,
                      fontSize: 12,
                      fontFamily: 'RobotoMono',
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ── Primary button (design.json primary_button) ───────────────────────────────
class _PrimaryButton extends StatelessWidget {
  final String label;
  final VoidCallback? onPressed;

  const _PrimaryButton({required this.label, required this.onPressed});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 54,
      width: double.infinity,
      child: FilledButton(
        onPressed: onPressed,
        style: FilledButton.styleFrom(
          backgroundColor: onPressed == null ? _Brand.amber.withOpacity(0.4) : _Brand.amber,
          foregroundColor: Colors.black,
          elevation: 0,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(_Brand.buttonRadius),
          ),
        ),
        child: Text(
          label,
          style: const TextStyle(
            fontSize: 14,
            fontWeight: FontWeight.w800,
            letterSpacing: 2,
          ),
        ),
      ),
    );
  }
}
