import 'dart:async';
import 'dart:io' show Platform;
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:url_launcher/url_launcher.dart';
import '../api_client.dart';
import '../auth_storage.dart';
import '../map_utils.dart';
import 'order_detail_screen.dart';

// ── Brand (match order_detail_screen) ────────────────────────────────────────
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 error = Color(0xFFFF4545);
}

/// Returns a short "what was ordered" line from order_summary + order_type.
String _orderSummaryLine(Map o) {
  final summary = o['order_summary'];
  if (summary == null || summary is! Map) return o['order_type']?.toString() ?? 'Order';
  final m = summary;
  final orderType = o['order_type']?.toString() ?? '';
  if (orderType == 'gas') {
    final type = m['type']?.toString() ?? '—';
    final brand = m['brand']?.toString() ?? '—';
    final size = m['size']?.toString() ?? '—';
    return '$type · $brand · $size';
  }
  if (orderType == 'fuel') {
    final brand = m['brand']?.toString() ?? '—';
    final fuelType = m['fuel_type']?.toString() ?? '—';
    final liters = m['liters'];
    final L = liters != null ? (liters is num ? liters.toInt() : liters.toString()) : '—';
    return '$brand · $fuelType · ${L}L';
  }
  if (orderType == 'rescue') return m['service']?.toString() ?? '—';
  if (orderType == 'shop') {
    final n = m['items_count'];
    final count = n != null ? (n is num ? n.toInt() : n.toString()) : '0';
    return '$count item(s)';
  }
  return orderType.isNotEmpty ? orderType : 'Order';
}

class DashboardScreen extends StatefulWidget {
  const DashboardScreen({super.key});

  @override
  State<DashboardScreen> createState() => _DashboardScreenState();
}

class _DashboardScreenState extends State<DashboardScreen> with SingleTickerProviderStateMixin {
  late Dio _dio;
  late TabController _tabController;
  bool _online = false;
  Timer? _locationTimer;
  List<dynamic> _newTasks = [];
  List<dynamic> _completedTasks = [];
  bool _loading = true;
  String? _error;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
    _dio = createApiClient(_onUnauthorized);
    _loadTasks();
    _initDriverStatus();
  }

  @override
  void dispose() {
    _locationTimer?.cancel();
    _tabController.dispose();
    super.dispose();
  }

  void _onUnauthorized() {
    AuthStorage.clearToken();
    if (mounted) {
      Navigator.of(context).pushNamedAndRemoveUntil('/login', (r) => false);
    }
  }

  Future<void> _loadTasks() async {
    setState(() {
      _loading = true;
      _error = null;
    });
    try {
      final r = await _dio.get('/api/orders');
      final data = r.data;
      if (data is Map && data['data'] is List) {
        final all = List<dynamic>.from(data['data'] as List);
        if (mounted) {
          setState(() {
            _newTasks = all.where((o) => o is Map && !_isCompleted(o['status'])).toList();
            _completedTasks = all.where((o) => o is Map && _isCompleted(o['status'])).toList();
            _loading = false;
          });
        }
        return;
      }
    } catch (e) {
      if (e is DioException && e.response?.statusCode == 401) {
        _onUnauthorized();
        return;
      }
    }
    if (mounted) setState(() {
      _loading = false;
      _error = 'Failed to load tasks';
    });
  }

  bool _isCompleted(dynamic status) {
    return status == 'delivered' || status == 'cancelled';
  }

  /// Restore toggle from storage then sync with backend.
  Future<void> _initDriverStatus() async {
    final stored = await AuthStorage.getDriverOnline();
    if (mounted && stored != null) {
      setState(() => _online = stored);
      if (stored) _startLocationPings();
    }
    await _loadDriverStatus();
  }

  /// Sync online state from backend. If user had chosen "online" and we restored it,
  /// do not overwrite with backend false (e.g. after restart before first ping).
  Future<void> _loadDriverStatus() async {
    try {
      final r = await _dio.get('/api/driver/status');
      if (!mounted) return;
      final data = r.data;
      if (data is Map && data['data'] is Map) {
        final backendOnline = (data['data'] as Map)['online'] == true;
        final stored = await AuthStorage.getDriverOnline();
        final wasRestoredOnline = stored == true && _online == true;
        final applyOnline = backendOnline || (wasRestoredOnline && !backendOnline);
        if (applyOnline) {
          await AuthStorage.setDriverOnline(true);
          if (mounted) {
            setState(() => _online = true);
            _startLocationPings();
          }
        } else {
          await AuthStorage.setDriverOnline(false);
          if (mounted) {
            _locationTimer?.cancel();
            _locationTimer = null;
            setState(() => _online = false);
          }
        }
      }
    } catch (_) {
      // Leave state as-is on error (stored value already applied in _initDriverStatus)
    }
  }

  Future<void> _setOnline(bool value) async {
    if (value) {
      setState(() => _online = true);
      await AuthStorage.setDriverOnline(true);
      _startLocationPings();
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('You\'re online — sharing location with dispatch'),
            duration: Duration(seconds: 2),
            behavior: SnackBarBehavior.floating,
          ),
        );
      }
    } else {
      _locationTimer?.cancel();
      _locationTimer = null;
      setState(() => _online = false);
      await AuthStorage.setDriverOnline(false);
      try {
        await _dio.post('/api/driver/offline');
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text('You\'re offline — not available for new orders'),
              duration: Duration(seconds: 2),
              behavior: SnackBarBehavior.floating,
            ),
          );
        }
      } catch (e) {
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text(e is DioException && e.response?.data is Map
                  ? (e.response!.data as Map)['message']?.toString() ?? 'Could not go offline'
                  : 'Could not go offline'),
              backgroundColor: _Brand.error,
              behavior: SnackBarBehavior.floating,
            ),
          );
        }
      }
    }
  }

  void _startLocationPings() {
    _locationTimer?.cancel();
    void sendLocation() async {
      try {
        final pos = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium);
        await _dio.post('/api/driver/location', data: {
          'latitude': pos.latitude,
          'longitude': pos.longitude,
        });
      } catch (_) {}
    }
    sendLocation();
    _locationTimer = Timer.periodic(const Duration(seconds: 120), (_) => sendLocation());
  }

  void _openMaps(double? lat, double? lng, String? address, String? plusCode) async {
    Uri? uri;
    // Prefer stored Plus Code (set by user app) so directions match what user saved
    final destination = (plusCode?.trim().isNotEmpty == true)
        ? plusCode!.trim()
        : (lat != null && lng != null)
            ? buildMapDestination(lat, lng)
            : null;
    if (destination != null && destination.isNotEmpty) {
      final encoded = Uri.encodeComponent(destination);
      if (Platform.isAndroid) {
        uri = Uri.parse('google.navigation:q=$encoded');
      } else {
        uri = Uri.parse('https://www.google.com/maps/dir/?api=1&destination=$encoded&travelmode=driving');
      }
    } else if (address != null && address.isNotEmpty) {
      uri = Uri.parse('https://www.google.com/maps/search/?api=1&query=${Uri.encodeComponent(address)}');
    }
    if (uri == null) return;
    try {
      await launchUrl(uri, mode: LaunchMode.externalApplication);
    } catch (_) {}
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: _Brand.bg,
      appBar: AppBar(
        backgroundColor: _Brand.bg,
        foregroundColor: _Brand.textPrimary,
        elevation: 0,
        title: const Text('Jambo Driver', style: TextStyle(fontWeight: FontWeight.w700)),
        bottom: TabBar(
          controller: _tabController,
          indicatorColor: _Brand.amber,
          labelColor: _Brand.amber,
          unselectedLabelColor: _Brand.textMuted,
          tabs: const [
            Tab(text: 'New Tasks'),
            Tab(text: 'Completed'),
          ],
        ),
        actions: [
          Text(
            _online ? 'Online' : 'Offline',
            style: TextStyle(
              color: _online ? _Brand.amber : _Brand.textMuted,
              fontSize: 12,
              fontWeight: _online ? FontWeight.w600 : FontWeight.normal,
            ),
          ),
          Switch(
            value: _online,
            onChanged: _setOnline,
            activeColor: _Brand.amber,
          ),
          IconButton(
            icon: const Icon(Icons.logout_rounded),
            onPressed: () async {
              _setOnline(false);
              await AuthStorage.clearToken();
              if (mounted) Navigator.of(context).pushNamedAndRemoveUntil('/login', (r) => false);
            },
          ),
        ],
      ),
      body: _loading
          ? Center(
              child: SizedBox(
                width: 32,
                height: 32,
                child: CircularProgressIndicator(
                  strokeWidth: 2.5,
                  valueColor: AlwaysStoppedAnimation(_Brand.amber),
                ),
              ),
            )
          : TabBarView(
              controller: _tabController,
              children: [
                _taskList(_newTasks, false),
                _taskList(_completedTasks, true),
              ],
            ),
    );
  }

  Widget _taskList(List<dynamic> tasks, bool completed) {
    if (_error != null) {
      return Center(
        child: Text(_error!, style: const TextStyle(color: _Brand.error, fontSize: 14)),
      );
    }
    if (tasks.isEmpty) {
      return Center(
        child: Text(
          'No tasks',
          style: TextStyle(color: _Brand.textMuted, fontSize: 15),
        ),
      );
    }
    return RefreshIndicator(
      color: _Brand.amber,
      onRefresh: _loadTasks,
      child: ListView.builder(
        padding: const EdgeInsets.all(16),
        itemCount: tasks.length,
        itemBuilder: (context, i) {
          final t = tasks[i] as Map;
          final orderId = t['id'] is int
              ? t['id'] as int
              : int.tryParse(t['id']?.toString() ?? '') ?? 0;
          return _TaskCard(
            order: t,
            completed: completed,
            onTap: orderId > 0
                ? () async {
                    await Navigator.of(context).push<bool>(
                      MaterialPageRoute(
                        builder: (context) => OrderDetailScreen(
                          orderId: orderId,
                          onUnauthorized: _onUnauthorized,
                          onComplete: _loadTasks,
                        ),
                      ),
                    );
                    if (mounted) _loadTasks();
                  }
                : null,
            onCall: () => _launchPhone(t['user_phone']?.toString()),
            onMap: () {
              final loc = t['location'];
              if (loc != null) {
                final lat = (loc['latitude'] as num?)?.toDouble();
                final lng = (loc['longitude'] as num?)?.toDouble();
                _openMaps(lat, lng, loc['address_name']?.toString(), loc['plus_code']?.toString());
              } else {
                _openMaps(null, null, null, null);
              }
            },
          );
        },
      ),
    );
  }

  Future<void> _launchPhone(String? phone) async {
    if (phone == null || phone.isEmpty) return;
    final uri = Uri(scheme: 'tel', path: phone);
    if (await canLaunchUrl(uri)) await launchUrl(uri);
  }

}

class _TaskCard extends StatelessWidget {
  const _TaskCard({
    required this.order,
    required this.completed,
    required this.onCall,
    required this.onMap,
    this.onTap,
  });

  final Map order;
  final bool completed;
  final VoidCallback onCall;
  final VoidCallback onMap;
  final VoidCallback? onTap;

  @override
  Widget build(BuildContext context) {
    final t = order;

    Widget content = Padding(
      padding: const EdgeInsets.all(14),
      child: Row(
        children: [
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Order #${t['id']}',
                  style: const TextStyle(
                    color: _Brand.textPrimary,
                    fontSize: 16,
                    fontWeight: FontWeight.w600,
                  ),
                ),
                const SizedBox(height: 2),
                Text(
                  _orderSummaryLine(t),
                  style: const TextStyle(color: _Brand.textMuted, fontSize: 13),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
          if (!completed) ...[
            if (t['user_phone'] != null)
              IconButton(
                icon: const Icon(Icons.phone_rounded, color: _Brand.amber),
                onPressed: onCall,
                tooltip: 'Call',
              ),
            IconButton(
              icon: const Icon(Icons.map_rounded, color: _Brand.amber),
              onPressed: onMap,
              tooltip: 'Open Maps',
            ),
          ],
          if (onTap != null)
            const Padding(
              padding: EdgeInsets.only(left: 4),
              child: Icon(Icons.chevron_right_rounded, color: _Brand.textMuted),
            ),
        ],
      ),
    );

    final cardChild = onTap != null
        ? InkWell(
            onTap: onTap,
            borderRadius: BorderRadius.circular(16),
            child: content,
          )
        : content;

    return Container(
      margin: const EdgeInsets.only(bottom: 12),
      decoration: BoxDecoration(
        color: _Brand.card,
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: _Brand.divider),
      ),
      child: cardChild,
    );
  }
}
