import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../api_client.dart';
import '../map_utils.dart';
import 'map_picker_screen.dart';

// ── Design tokens (design.json) ───────────────────────────────────────────────
class _Brand {
  static const bg = Color(0xFF0F1114);
  static const surface = Color(0xFF1A1D22);
  static const card = Color(0xFF21252D);
  static const amber = Color(0xFFFF9500);
  static const amberGlow = Color(0x33FF9500);
  static const textPrimary = Color(0xFFF2F2F2);
  static const textMuted = Color(0xFF8A8F99);
  static const divider = Color(0xFF2C3040);
  static const green = Color(0xFF34C759);
  static const red = Color(0xFFFF4545);

  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;
  static const chipRadius = 8.0;
}

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

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

  final VoidCallback onUnauthorized;

  @override
  State<AddressesScreen> createState() => _AddressesScreenState();
}

class _AddressesScreenState extends State<AddressesScreen> {
  late Dio _dio;
  List<dynamic> _list = [];
  bool _loading = true;
  String? _error;

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

  Future<void> _load() async {
    setState(() {
      _loading = true;
      _error = null;
    });
    try {
      final r = await _dio.get('/api/addresses');
      if (mounted) {
        setState(() {
          _list = (r.data is Map && r.data['data'] is List)
              ? List.from(r.data['data'] as List)
              : [];
          _loading = false;
        });
      }
    } catch (e) {
      if (e is DioException && e.response?.statusCode == 401) {
        widget.onUnauthorized();
        return;
      }
      if (mounted) {
        setState(() {
          _loading = false;
          _error = 'Failed to load addresses';
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      statusBarIconBrightness: Brightness.light,
    ));
    return Scaffold(
      backgroundColor: _Brand.bg,
      appBar: AppBar(
        backgroundColor: _Brand.surface,
        elevation: 0,
        scrolledUnderElevation: 0,
        title: const Text(
          'ADDRESSES',
          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 && _list.isEmpty
          ? const Center(
              child: SizedBox(
                width: 32,
                height: 32,
                child: CircularProgressIndicator(
                  strokeWidth: 2.5,
                  valueColor: AlwaysStoppedAnimation(_Brand.amber),
                ),
              ),
            )
          : RefreshIndicator(
              onRefresh: _load,
              color: _Brand.amber,
              backgroundColor: _Brand.card,
              child: ListView(
                padding: const EdgeInsets.fromLTRB(
                  _Brand.screenPadding,
                  8,
                  _Brand.screenPadding,
                  40,
                ),
                children: [
                  if (_error != null) ...[
                    _ErrorBanner(_error!),
                    const SizedBox(height: _Brand.sectionGap),
                  ],
                  const _SectionLabel('SAVED ADDRESSES'),
                  const SizedBox(height: 12),
                  if (_list.isEmpty)
                    _EmptyAddressState(onAdd: () => _showAddDialog(context))
                  else ...[
                    ..._list.map((a) {
                          final m = a as Map;
                          return Padding(
                            padding: const EdgeInsets.only(bottom: 12),
                            child: _AddressCard(
                              address: m,
                              onSetDefault: () => _setDefault(m['id']),
                              onEdit: () => _showEditTitle(context, m),
                              onDelete: () => _showDeleteConfirm(context, m),
                            ),
                          );
                        }),
                    const SizedBox(height: _Brand.sectionGap),
                    _PrimaryButton(
                      label: 'ADD ADDRESS',
                      onPressed: () => _showAddDialog(context),
                      icon: Icons.add_rounded,
                    ),
                  ],
                ],
              ),
            ),
    );
  }

  void _showAddDialog(BuildContext context) async {
    final result = await Navigator.push<Map<String, dynamic>>(
      context,
      MaterialPageRoute(builder: (_) => const MapPickerScreen()),
    );
    if (result == null || result['lat'] == null || result['lng'] == null || !mounted) return;
    final lat = (result['lat'] as num).toDouble();
    final lng = (result['lng'] as num).toDouble();
    final name = result['name'] as String?;
    // Use only real locality (e.g. Kampala) for plus_code so map directions work; address title is for display only
    final plusCode = buildPlusCodeWithLocality(lat, lng);
    try {
      await _dio.post('/api/addresses', data: {
        'latitude': lat,
        'longitude': lng,
        'address_name': name?.trim().isEmpty == true ? null : name?.trim(),
        'plus_code': plusCode,
        'is_default': _list.isEmpty,
      });
      if (!mounted) return;
      _load();
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text('Address added'),
          backgroundColor: _Brand.green,
          behavior: SnackBarBehavior.floating,
        ),
      );
    } catch (_) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('Failed to save address'),
            backgroundColor: _Brand.red,
            behavior: SnackBarBehavior.floating,
          ),
        );
      }
    }
  }

  Future<void> _setDefault(dynamic id) async {
    try {
      await _dio.patch('/api/addresses/$id', data: {'is_default': true});
      _load();
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('Default address updated'),
            backgroundColor: _Brand.green,
            behavior: SnackBarBehavior.floating,
          ),
        );
      }
    } catch (_) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('Failed to set default'),
            backgroundColor: _Brand.red,
            behavior: SnackBarBehavior.floating,
          ),
        );
      }
    }
  }

  Future<void> _showEditTitle(BuildContext context, Map address) async {
    final id = address['id'];
    if (id == null) return;
    final nameController = TextEditingController(
      text: address['address_name']?.toString() ?? '',
    );
    final result = await showDialog<String>(
      context: context,
      builder: (ctx) => AlertDialog(
        backgroundColor: _Brand.card,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
        title: const Text('Edit address name', style: TextStyle(color: _Brand.textPrimary, fontSize: 18)),
        content: TextField(
          controller: nameController,
          autofocus: true,
          style: const TextStyle(color: _Brand.textPrimary),
          decoration: InputDecoration(
            hintText: 'e.g. Home, Office',
            hintStyle: TextStyle(color: _Brand.textMuted),
            filled: true,
            fillColor: _Brand.surface,
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(_Brand.buttonRadius),
              borderSide: const BorderSide(color: _Brand.divider),
            ),
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(),
            child: Text('Cancel', style: TextStyle(color: _Brand.textMuted)),
          ),
          FilledButton(
            onPressed: () => Navigator.of(ctx).pop(nameController.text.trim()),
            style: FilledButton.styleFrom(backgroundColor: _Brand.amber, foregroundColor: Colors.black),
            child: const Text('Save'),
          ),
        ],
      ),
    );
    nameController.dispose();
    if (result == null || !mounted) return;
    try {
      await _dio.patch('/api/addresses/$id', data: {
        'address_name': result.isEmpty ? null : result,
      });
      if (!mounted) return;
      _load();
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text('Address name updated'),
          backgroundColor: _Brand.green,
          behavior: SnackBarBehavior.floating,
        ),
      );
    } catch (_) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('Failed to update'),
            backgroundColor: _Brand.red,
            behavior: SnackBarBehavior.floating,
          ),
        );
      }
    }
  }

  Future<void> _showDeleteConfirm(BuildContext context, Map address) async {
    final id = address['id'];
    if (id == null) return;
    final name = address['address_name']?.toString() ?? 'Saved location';
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        backgroundColor: _Brand.card,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
        title: const Text('Delete address?', style: TextStyle(color: _Brand.textPrimary, fontSize: 18)),
        content: Text(
          'Remove "$name" from your addresses?',
          style: const TextStyle(color: _Brand.textMuted, fontSize: 14),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(ctx).pop(false),
            child: Text('Cancel', style: TextStyle(color: _Brand.textMuted)),
          ),
          FilledButton(
            onPressed: () => Navigator.of(ctx).pop(true),
            style: FilledButton.styleFrom(backgroundColor: _Brand.red, foregroundColor: Colors.white),
            child: const Text('Delete'),
          ),
        ],
      ),
    );
    if (confirmed != true || !mounted) return;
    try {
      await _dio.delete('/api/addresses/$id');
      if (!mounted) return;
      _load();
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text('Address removed'),
          backgroundColor: _Brand.green,
          behavior: SnackBarBehavior.floating,
        ),
      );
    } catch (_) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('Failed to delete'),
            backgroundColor: _Brand.red,
            behavior: SnackBarBehavior.floating,
          ),
        );
      }
    }
  }
}

// ── Section label (design.json) ────────────────────────────────────────────────
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) ─────────────────────────────────────────────────
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),
            ),
          ),
        ],
      ),
    );
  }
}

// ── Address card (Container, not Card; design.json card + info_card style) ─────
class _AddressCard extends StatelessWidget {
  final Map address;
  final VoidCallback onSetDefault;
  final VoidCallback onEdit;
  final VoidCallback onDelete;

  const _AddressCard({
    required this.address,
    required this.onSetDefault,
    required this.onEdit,
    required this.onDelete,
  });

  @override
  Widget build(BuildContext context) {
    final name = address['address_name']?.toString();
    final lat = address['latitude'];
    final lng = address['longitude'];
    final plusCode = address['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 coords = plusCode?.isNotEmpty == true ? plusCode! : '$latStr, $lngStr';
    final isDefault = address['is_default'] == true;

    return Container(
      padding: const EdgeInsets.all(18),
      decoration: BoxDecoration(
        color: _Brand.card,
        borderRadius: BorderRadius.circular(_Brand.cardRadius),
        border: Border.all(
          color: isDefault ? _Brand.amber.withOpacity(0.4) : _Brand.divider,
          width: isDefault ? 1.5 : 1,
        ),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                width: 40,
                height: 40,
                decoration: BoxDecoration(
                  color: _Brand.amberGlow,
                  borderRadius: BorderRadius.circular(_Brand.iconBadgeRadius),
                  border: Border.all(color: _Brand.amber.withOpacity(0.35)),
                ),
                child: const Icon(Icons.location_on_rounded, color: _Brand.amber, size: 20),
              ),
              const SizedBox(width: 14),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      name?.isNotEmpty == true ? name! : 'Saved location',
                      style: const TextStyle(
                        color: _Brand.textPrimary,
                        fontSize: 15,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      coords,
                      style: const TextStyle(
                        color: _Brand.textMuted,
                        fontSize: 12,
                        fontFamily: 'RobotoMono',
                      ),
                    ),
                    if (isDefault) ...[
                      const SizedBox(height: 10),
                      Container(
                        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                        decoration: BoxDecoration(
                          color: _Brand.green.withOpacity(0.15),
                          borderRadius: BorderRadius.circular(6),
                          border: Border.all(color: _Brand.green.withOpacity(0.4)),
                        ),
                        child: const Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            SizedBox(
                              width: 6,
                              height: 6,
                              child: DecoratedBox(
                                decoration: BoxDecoration(
                                  color: _Brand.green,
                                  shape: BoxShape.circle,
                                ),
                              ),
                            ),
                            SizedBox(width: 5),
                            Text(
                              'DEFAULT',
                              style: TextStyle(
                                color: _Brand.green,
                                fontSize: 10,
                                fontWeight: FontWeight.w700,
                                letterSpacing: 1,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ],
                ),
              ),
              Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  if (!isDefault)
                    GestureDetector(
                      onTap: onSetDefault,
                      child: Container(
                        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                        decoration: BoxDecoration(
                          color: _Brand.amberGlow,
                          borderRadius: BorderRadius.circular(_Brand.chipRadius),
                          border: Border.all(color: _Brand.amber.withOpacity(0.4)),
                        ),
                        child: const Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            Icon(Icons.check_circle_outline_rounded, color: _Brand.amber, size: 14),
                            SizedBox(width: 6),
                            Text(
                              'Set default',
                              style: TextStyle(
                                color: _Brand.amber,
                                fontSize: 12,
                                fontWeight: FontWeight.w600,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  if (!isDefault) const SizedBox(width: 8),
                  IconButton(
                    onPressed: onEdit,
                    icon: const Icon(Icons.edit_outlined, size: 20),
                    color: _Brand.textMuted,
                    style: IconButton.styleFrom(
                      minimumSize: const Size(40, 40),
                      padding: EdgeInsets.zero,
                    ),
                    tooltip: 'Edit name',
                  ),
                  IconButton(
                    onPressed: onDelete,
                    icon: const Icon(Icons.delete_outline_rounded, size: 20),
                    color: _Brand.red,
                    style: IconButton.styleFrom(
                      minimumSize: const Size(40, 40),
                      padding: EdgeInsets.zero,
                    ),
                    tooltip: 'Delete address',
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
    );
  }
}

// ── Empty state (design.json empty_state) ──────────────────────────────────────
class _EmptyAddressState extends StatelessWidget {
  final VoidCallback onAdd;

  const _EmptyAddressState({required this.onAdd});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 24, bottom: _Brand.sectionGap),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 72,
            height: 72,
            decoration: BoxDecoration(
              color: _Brand.amberGlow,
              shape: BoxShape.circle,
              border: Border.all(color: _Brand.amber, width: 1.5),
            ),
            child: const Icon(Icons.location_off_rounded, color: _Brand.amber, size: 34),
          ),
          const SizedBox(height: 20),
          const Text(
            'No addresses yet',
            style: TextStyle(
              color: _Brand.textPrimary,
              fontSize: 16,
              fontWeight: FontWeight.w600,
            ),
          ),
          const SizedBox(height: 8),
          Text(
            'Add a delivery address to get started',
            style: TextStyle(color: _Brand.textMuted, fontSize: 13),
            textAlign: TextAlign.center,
          ),
          const SizedBox(height: 24),
          _PrimaryButton(
            label: 'ADD ADDRESS',
            onPressed: onAdd,
            icon: Icons.add_rounded,
          ),
        ],
      ),
    );
  }
}

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

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

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 54,
      width: double.infinity,
      child: FilledButton(
        onPressed: onPressed,
        style: FilledButton.styleFrom(
          backgroundColor: _Brand.amber,
          foregroundColor: Colors.black,
          elevation: 0,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(_Brand.buttonRadius),
          ),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (icon != null) ...[
              Icon(icon, size: 18, color: Colors.black),
              const SizedBox(width: 10),
            ],
            Text(
              label,
              style: const TextStyle(
                fontSize: 14,
                fontWeight: FontWeight.w800,
                letterSpacing: 2,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
