import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../l10n/app_localizations.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;
import '../models/delivery.dart';
import '../models/delivery_route.dart';
import '../models/delivery_commands.dart';
import '../providers/providers.dart';
import '../api/client.dart';
import '../utils/toast_helper.dart';
import '../api/openapi_config.dart';
import '../utils/http_client_factory.dart';
import '../components/collapsible_routes_sidebar.dart';
import '../components/dark_mode_map.dart';
import '../components/loading_dialog.dart';
import '../components/notes_dialog.dart';
import '../components/photo_capture_dialog.dart';
import '../components/mobile_map_with_overlay.dart';
import '../services/location_permission_service.dart';
import '../utils/breakpoints.dart';
import 'deliveries_page.dart';
import 'settings_page.dart';

class RoutesPage extends ConsumerStatefulWidget {
  const RoutesPage({super.key});

  @override
  ConsumerState<RoutesPage> createState() => _RoutesPageState();
}

class _RoutesPageState extends ConsumerState<RoutesPage> {
  late LocationPermissionService _permissionService;
  DeliveryRoute? _selectedRoute;
  Delivery? _selectedDelivery;

  @override
  void initState() {
    super.initState();
    _permissionService = LocationPermissionService();
    _requestLocationPermissionOnce();
  }

  Future<void> _requestLocationPermissionOnce() async {
    try {
      final hasPermission = await _permissionService.hasLocationPermission();
      if (!hasPermission && mounted) {
        final result = await _permissionService.requestLocationPermission();
        result.when(
          granted: () {
            debugPrint('Location permission granted');
          },
          denied: () {
            debugPrint('Location permission denied');
          },
          permanentlyDenied: () {
            debugPrint('Location permission permanently denied');
          },
          error: (message) {
            debugPrint('Location permission error: $message');
          },
        );
      }
    } catch (e) {
      debugPrint('Error requesting location permission: $e');
    }
  }

  void _selectRoute(DeliveryRoute route) {
    setState(() {
      _selectedRoute = route;
    });
  }

  void _backToRoutes() {
    setState(() {
      _selectedRoute = null;
      _selectedDelivery = null;
    });
  }

  Future<void> _handleDeliveryAction(
    String action,
    Delivery delivery,
    int routeFragmentId,
  ) async {
    // Capture l10n before async operations to avoid BuildContext across async gaps
    final l10n = AppLocalizations.of(context);
    final authService = ref.read(authServiceProvider);

    // Ensure we have a valid token (automatically refreshes if needed)
    final token = await authService.ensureValidToken();
    if (token == null) {
      if (mounted) {
        ToastHelper.showError(context, l10n.authenticationRequired);
      }
      return;
    }

    // Create API client with auth service for automatic token refresh
    final authClient = CqrsApiClient(
      config: ApiClientConfig.development,
      authService: authService,
    );

    switch (action) {
      case 'complete':
        if (mounted) {
          LoadingDialog.show(context, message: l10n.completingDelivery);
        }

        final result = await authClient.executeCommand(
          endpoint: 'completeDelivery',
          command: CompleteDeliveryCommand(
            deliveryId: delivery.id,
          ),
        );
        result.when(
          success: (_) async {
            if (mounted) {
              LoadingDialog.hide(context);
            }

            if (mounted) {
              // Invalidate both providers to force refresh
              ref.invalidate(deliveriesProvider(routeFragmentId));
              ref.invalidate(allDeliveriesProvider);
              ref.invalidate(deliveryRoutesProvider);

              // Wait for providers to refresh
              await Future.delayed(const Duration(milliseconds: 500));

              if (mounted) {
                // Get refreshed deliveries
                final allDeliveries = await ref.read(allDeliveriesProvider.future);
                final routeDeliveries = allDeliveries
                    .where((d) => d.routeFragmentId == routeFragmentId)
                    .toList();

                // Find the next incomplete delivery in the route
                final nextDelivery = routeDeliveries.firstWhere(
                  (d) => !d.delivered && !d.isSkipped,
                  orElse: () => routeDeliveries.firstWhere(
                    (d) => d.id == delivery.id,
                    orElse: () => delivery,
                  ),
                );

                setState(() {
                  _selectedDelivery = nextDelivery;
                });

                // Auto-show notes for the next delivery if needed
                _autoShowNotesIfNeeded(nextDelivery);

                // Small delay to let the UI update before map auto-navigates
                if (nextDelivery.id != delivery.id && mounted) {
                  await Future.delayed(const Duration(milliseconds: 200));
                }
              }

              if (mounted) {
                ToastHelper.showSuccess(context, l10n.deliverySuccessful);
              }
            }
          },
          onError: (error) {
            if (mounted) {
              LoadingDialog.hide(context);
            }

            debugPrint('Complete delivery failed - Type: ${error.type}, Message: ${error.message}');
            debugPrint('Error details: ${error.details}');
            if (mounted) {
              String errorMessage = l10n.error(error.message);
              if (error.statusCode == 500) {
                errorMessage = l10n.serverError;
              }
              ToastHelper.showError(context, errorMessage);
            }
          },
        );
        break;

      case 'uncomplete':
        if (mounted) {
          LoadingDialog.show(context, message: l10n.markingAsUncompleted);
        }

        final uncompleteResult = await authClient.executeCommand(
          endpoint: 'markDeliveryAsUncompleted',
          command: MarkDeliveryAsUncompletedCommand(deliveryId: delivery.id),
        );
        uncompleteResult.when(
          success: (_) async {
            if (mounted) {
              LoadingDialog.hide(context);
            }

            if (mounted) {
              // Invalidate both providers to force refresh
              ref.invalidate(deliveriesProvider(routeFragmentId));
              ref.invalidate(allDeliveriesProvider);
              ref.invalidate(deliveryRoutesProvider);

              // Wait for providers to refresh
              await Future.delayed(const Duration(milliseconds: 500));

              if (mounted) {
                // Get refreshed deliveries
                final allDeliveries = await ref.read(allDeliveriesProvider.future);
                final updatedDelivery = allDeliveries.firstWhere(
                  (d) => d.id == delivery.id,
                  orElse: () => delivery,
                );
                setState(() {
                  _selectedDelivery = updatedDelivery;
                });
              }

              if (mounted) {
                ToastHelper.showSuccess(context, l10n.deliveryMarkedUncompleted);
              }
            }
          },
          onError: (error) {
            if (mounted) {
              LoadingDialog.hide(context);
            }

            if (mounted) {
              ToastHelper.showError(context, l10n.error(error.message));
            }
          },
        );
        break;

      case 'photo':
        await _handlePhotoCapture(delivery);
        break;

      case 'note':
        await _showNotesDialog(delivery);
        break;
    }
  }

  Future<void> _handlePhotoCapture(
    Delivery delivery,
  ) async {
    final authService = ref.read(authServiceProvider);
    final l10n = AppLocalizations.of(context);

    // Ensure we have a valid token (automatically refreshes if needed)
    final token = await authService.ensureValidToken();
    if (token == null) {
      if (mounted) {
        ToastHelper.showError(context, l10n.authenticationRequired);
      }
      return;
    }
    final ImagePicker picker = ImagePicker();
    XFile? pickedFile;

    try {
      pickedFile = await picker.pickImage(
        source: ImageSource.camera,
        imageQuality: 85,
      );
    } catch (e) {
      if (mounted) {
        ToastHelper.showError(context, l10n.cameraError(e.toString()));
      }
      return;
    }

    if (pickedFile == null) {
      return;
    }

    if (!mounted) return;

    // Show photo confirmation dialog
    final bool? confirmed = await PhotoCaptureDialog.show(
      context,
      imageFile: File(pickedFile.path),
      deliveryName: delivery.name,
    );

    if (confirmed != true) {
      return;
    }

    if (!mounted) return;

    // Show uploading dialog
    LoadingDialog.show(context, message: l10n.uploadingPhoto);

    try {
      final Uri uploadUrl = Uri.parse(
        '${ApiClientConfig.development.baseUrl}/api/delivery/uploadDeliveryPicture?deliveryId=${delivery.id}',
      );

      // Create HTTP client that accepts self-signed certificates
      final client = HttpClientFactory.createClient(
        allowSelfSigned: ApiClientConfig.development.allowSelfSignedCertificate,
      );

      final http.MultipartRequest request = http.MultipartRequest('POST', uploadUrl);
      request.headers['Authorization'] = 'Bearer $token';
      request.files.add(await http.MultipartFile.fromPath('file', pickedFile.path));

      final http.StreamedResponse streamedResponse = await client.send(request);
      final http.Response response = await http.Response.fromStream(streamedResponse);
      client.close();

      if (mounted) {
        LoadingDialog.hide(context);
      }

      if (response.statusCode >= 200 && response.statusCode < 300) {
        if (mounted) {
          ToastHelper.showSuccess(context, l10n.photoUploadSuccess);
        }
        ref.invalidate(allDeliveriesProvider);
      } else {
        debugPrint('Photo upload failed - Status: ${response.statusCode}');
        debugPrint('Response body: ${response.body}');
        if (mounted) {
          String errorMessage = l10n.photoUploadFailed(response.statusCode);
          if (response.statusCode == 500) {
            errorMessage = l10n.serverError;
          } else if (response.statusCode == 401) {
            errorMessage = l10n.authenticationRequired;
          }
          ToastHelper.showError(context, errorMessage);
        }
      }
    } catch (e) {
      if (mounted) {
        LoadingDialog.hide(context);
        ToastHelper.showError(context, l10n.uploadError(e.toString()));
      }
    }
  }

  bool _shouldAutoShowNotes(Delivery? delivery) {
    // Only auto-show notes if delivery is not yet delivered and has notes
    if (delivery == null || delivery.delivered) return false;

    final hasNotes = delivery.orders.any(
      (order) => order.note != null && order.note!.isNotEmpty,
    );

    return hasNotes;
  }

  Future<void> _autoShowNotesIfNeeded(Delivery? delivery) async {
    if (delivery != null && _shouldAutoShowNotes(delivery)) {
      // Use post-frame callback to ensure UI is ready
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          _showNotesDialog(delivery);
        }
      });
    }
  }

  Future<void> _showNotesDialog(Delivery delivery) async {
    if (!mounted) return;

    final l10n = AppLocalizations.of(context);
    final hasNotes = await NotesDialog.show(context, delivery);

    if (!hasNotes && mounted) {
      ToastHelper.showInfo(context, l10n.noNotesMessage);
    }
  }

  @override
  Widget build(BuildContext context) {
    final routesData = ref.watch(deliveryRoutesProvider);
    final allDeliveriesData = ref.watch(allDeliveriesProvider);
    final userProfile = ref.watch(userProfileProvider);
    final l10n = AppLocalizations.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(l10n.deliveryRoutes),
        elevation: 0,
        scrolledUnderElevation: 0,
        actions: [
          IconButton(
            icon: (routesData.isLoading || allDeliveriesData.isLoading)
                ? const SizedBox(
                    width: 20,
                    height: 20,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  )
                : const Icon(Icons.refresh),
            onPressed: (routesData.isLoading || allDeliveriesData.isLoading)
                ? null
                : () {
                    ref.invalidate(deliveryRoutesProvider);
                    ref.invalidate(allDeliveriesProvider);
                  },
            tooltip: 'Refresh',
          ),
          userProfile.when(
            data: (profile) {
              String getInitials(String? fullName) {
                if (fullName == null || fullName.isEmpty) return 'U';
                final names = fullName.trim().split(' ');
                if (names.length == 1) {
                  return names[0][0].toUpperCase();
                }
                return '${names.first[0]}${names.last[0]}'.toUpperCase();
              }

              return GestureDetector(
                onTap: () {
                  Navigator.of(context).push(
                    MaterialPageRoute(
                      builder: (context) => const SettingsPage(),
                    ),
                  );
                },
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 12.0),
                  child: CircleAvatar(
                    radius: 16,
                    backgroundColor: Theme.of(context).colorScheme.primary,
                    child: Text(
                      getInitials(profile?.fullName),
                      style: TextStyle(
                        color: Theme.of(context).colorScheme.onPrimary,
                        fontSize: 14,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                ),
              );
            },
            loading: () => const Padding(
              padding: EdgeInsets.all(16.0),
              child: SizedBox(
                width: 16,
                height: 16,
                child: CircularProgressIndicator(strokeWidth: 2),
              ),
            ),
            error: (error, stackTrace) => const SizedBox(),
          ),
        ],
      ),
      body: routesData.when(
        data: (routes) {
          if (routes.isEmpty) {
            return Center(
              child: Text(l10n.noRoutes),
            );
          }
          return allDeliveriesData.when(
            data: (allDeliveries) {
              final isMobile = context.isMobile;

              // Mobile layout: Show routes list full-screen when no route selected
              if (isMobile && _selectedRoute == null) {
                return RefreshIndicator(
                  onRefresh: () async {
                    // ignore: unused_result
                    ref.refresh(deliveryRoutesProvider);
                    // ignore: unused_result
                    ref.refresh(allDeliveriesProvider);
                  },
                  child: CollapsibleRoutesSidebar(
                    routes: routes,
                    selectedRoute: null,
                    onRouteSelected: _selectRoute,
                  ),
                );
              }

              // Mobile layout: full-screen map with overlay when route is selected
              if (isMobile && _selectedRoute != null) {
                final routeDeliveries = allDeliveries
                    .where((d) => d.routeFragmentId == _selectedRoute!.id)
                    .toList();

                return RefreshIndicator(
                  onRefresh: () async {
                    // ignore: unused_result
                    ref.refresh(deliveryRoutesProvider);
                    // ignore: unused_result
                    ref.refresh(allDeliveriesProvider);
                  },
                  child: Stack(
                    children: [
                      MobileMapWithOverlay(
                        deliveries: routeDeliveries,
                        selectedDelivery: _selectedDelivery,
                        onDeliverySelected: (delivery) {
                          setState(() {
                            _selectedDelivery = delivery;
                          });
                          _autoShowNotesIfNeeded(delivery);
                        },
                        onDeliveryAction: (delivery, action) {
                          _handleDeliveryAction(action, delivery, _selectedRoute!.id);
                        },
                      ),
                      // Back button to return to routes list
                      Positioned(
                        top: 16,
                        left: 16,
                        child: FloatingActionButton.small(
                          onPressed: _backToRoutes,
                          backgroundColor: Theme.of(context).colorScheme.surface,
                          child: const Icon(Icons.arrow_back),
                        ),
                      ),
                    ],
                  ),
                );
              }

              // Tablet/Desktop layout: split view with map + sidebar
              return RefreshIndicator(
                onRefresh: () async {
                  // ignore: unused_result
                  ref.refresh(deliveryRoutesProvider);
                  // ignore: unused_result
                  ref.refresh(allDeliveriesProvider);
                },
                child: Row(
                  children: [
                    Expanded(
                      child: DarkModeMapComponent(
                        deliveries: allDeliveries,
                        selectedDelivery: _selectedDelivery,
                        onDeliverySelected: (delivery) {
                          setState(() {
                            _selectedDelivery = delivery;
                          });
                          _autoShowNotesIfNeeded(delivery);
                        },
                        onAction: (action) {
                          if (_selectedDelivery != null && _selectedRoute != null) {
                            _handleDeliveryAction(action, _selectedDelivery!, _selectedRoute!.id);
                          }
                        },
                      ),
                    ),
                    _selectedRoute == null
                        ? CollapsibleRoutesSidebar(
                            routes: routes,
                            selectedRoute: null,
                            onRouteSelected: _selectRoute,
                          )
                        : DeliveriesPage(
                            routeFragmentId: _selectedRoute!.id,
                            routeName: _selectedRoute!.name,
                            onBack: _backToRoutes,
                            showAsEmbedded: true,
                            selectedDelivery: _selectedDelivery,
                            onDeliverySelected: (delivery) {
                              setState(() {
                                _selectedDelivery = delivery;
                              });
                              _autoShowNotesIfNeeded(delivery);
                            },
                          ),
                  ],
                ),
              );
            },
            loading: () => const Center(
              child: CircularProgressIndicator(),
            ),
            error: (error, stackTrace) => Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(l10n.error(error.toString())),
                  const SizedBox(height: 16),
                  ElevatedButton(
                    onPressed: () => ref.refresh(allDeliveriesProvider),
                    child: Text(l10n.retry),
                  ),
                ],
              ),
            ),
          );
        },
        loading: () => const Center(
          child: CircularProgressIndicator(),
        ),
        error: (error, stackTrace) => Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(l10n.error(error.toString())),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: () => ref.refresh(deliveryRoutesProvider),
                child: Text(l10n.retry),
              ),
            ],
          ),
        ),
      ),
    );
  }

}
