import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:intl/intl.dart';
import 'package:geolocator/geolocator.dart';

import 'package:environment_monitoring_app/auth_provider.dart';
import 'package:environment_monitoring_app/models/tarball_data.dart';
import 'package:environment_monitoring_app/screens/marine/manual/tarball_sampling_step2.dart';

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

  @override
  State<TarballSamplingStep1> createState() => _TarballSamplingStep1State();
}

class _TarballSamplingStep1State extends State<TarballSamplingStep1> {
  final _formKey = GlobalKey<FormState>();
  final _data = TarballSamplingData();
  bool _isLoading = false;

  // --- Controllers for UI fields ---
  final TextEditingController _firstSamplerController = TextEditingController();
  final TextEditingController _dateController = TextEditingController();
  final TextEditingController _timeController = TextEditingController();
  final TextEditingController _stationLatController = TextEditingController();
  final TextEditingController _stationLonController = TextEditingController();
  final TextEditingController _currentLatController = TextEditingController();
  final TextEditingController _currentLonController = TextEditingController();

  // --- State for Dropdowns and Location ---
  List<String> _statesList = [];
  List<String> _categoriesForState = [];
  List<Map<String, dynamic>> _stationsForCategory = [];
  double? _distanceDifference;

  @override
  void initState() {
    super.initState();
    _initializeForm();
  }

  @override
  void dispose() {
    // Dispose all controllers to prevent memory leaks
    _firstSamplerController.dispose();
    _dateController.dispose();
    _timeController.dispose();
    _stationLatController.dispose();
    _stationLonController.dispose();
    _currentLatController.dispose();
    _currentLonController.dispose();
    super.dispose();
  }

  void _initializeForm() {
    final auth = Provider.of<AuthProvider>(context, listen: false);

    // Set initial values for the data model and controllers
    // This relies on the AuthProvider having been populated with data,
    // which works offline if the data was fetched and cached previously.
    _data.firstSampler = auth.profileData?['first_name'] ?? 'Current User';
    _data.firstSamplerUserId = auth.profileData?['user_id'];
    _firstSamplerController.text = _data.firstSampler!;

    final now = DateTime.now();
    _data.samplingDate = DateFormat('yyyy-MM-dd').format(now);
    _data.samplingTime = DateFormat('HH:mm:ss').format(now);
    _dateController.text = _data.samplingDate!;
    _timeController.text = _data.samplingTime!;

    // Populate the initial list of unique states from all available stations.
    // This also relies on cached data in AuthProvider for offline use.
    final allStations = auth.tarballStations ?? [];
    if (allStations.isNotEmpty) {
      final states = allStations.map((s) => s['state_name'] as String?).whereType<String>().toSet().toList();
      states.sort();
      _statesList = states;
    }
  }

  /// Fetches the device's location with an offline-first approach.
  Future<void> _getCurrentLocation() async {
    bool serviceEnabled;
    LocationPermission permission;

    // Check if location services are enabled.
    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      _showSnackBar('Location services are disabled. Please enable them.');
      return;
    }

    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        _showSnackBar('Location permissions are denied.');
        return;
      }
    }

    if (permission == LocationPermission.deniedForever) {
      _showSnackBar('Location permissions are permanently denied. We cannot request permissions.');
      return;
    }

    setState(() => _isLoading = true);

    try {
      // --- OFFLINE-FIRST LOGIC ---
      // 1. Try to get the last known position. This is fast and works offline.
      Position? position = await Geolocator.getLastKnownPosition();

      // 2. If no last known position, get the current position using GPS.
      // This can work offline but may take longer.
      position ??= await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);

      if (mounted) {
        setState(() {
          _data.currentLatitude = position!.latitude.toString();
          _data.currentLongitude = position.longitude.toString();
          _currentLatController.text = _data.currentLatitude!;
          _currentLonController.text = _data.currentLongitude!;
          _calculateDistance();
        });
      }
    } catch (e) {
      _showSnackBar('Failed to get location: $e');
    } finally {
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  void _calculateDistance() {
    if (_stationLatController.text.isNotEmpty && _currentLatController.text.isNotEmpty) {
      final double lat1 = double.parse(_stationLatController.text);
      final double lon1 = double.parse(_stationLonController.text);
      final double lat2 = double.parse(_currentLatController.text);
      final double lon2 = double.parse(_currentLonController.text);

      double distanceInMeters = Geolocator.distanceBetween(lat1, lon1, lat2, lon2);
      setState(() {
        _distanceDifference = distanceInMeters / 1000;
        _data.distanceDifference = _distanceDifference;
      });
    }
  }

  void _goToNextStep() {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => TarballSamplingStep2(data: _data)),
      );
    }
  }

  void _showSnackBar(String message) {
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
    }
  }

  @override
  Widget build(BuildContext context) {
    // For offline functionality, all data used in the dropdowns (tarballStations, allUsers)
    // must be fetched and cached in the AuthProvider when the app is online.
    final auth = Provider.of<AuthProvider>(context, listen: false);
    final allStations = auth.tarballStations ?? [];

    final currentUser = auth.profileData;
    final allUsers = auth.allUsers ?? [];
    final secondSamplersList = allUsers.where((user) => user['user_id'] != currentUser?['user_id']).toList();

    return Scaffold(
      appBar: AppBar(title: const Text("Tarball Sampling (1/3)")),
      body: Form(
        key: _formKey,
        child: ListView(
          padding: const EdgeInsets.all(24.0),
          children: [
            Text("Sampling Information", style: Theme.of(context).textTheme.headlineSmall),
            const SizedBox(height: 24),
            TextFormField(controller: _firstSamplerController, readOnly: true, decoration: const InputDecoration(labelText: '1st Sampler')),
            const SizedBox(height: 16),

            DropdownSearch<Map<String, dynamic>>(
              // --- CORRECTED: Added a ValueKey to prevent the "Duplicate GlobalKey" error ---
              // This ensures the widget rebuilds cleanly when its item list changes.
              key: ValueKey(allUsers.length),
              items: secondSamplersList,
              itemAsString: (sampler) => "${sampler['first_name']} ${sampler['last_name']}",
              onChanged: (sampler) => setState(() => _data.secondSampler = sampler),
              popupProps: const PopupProps.menu(
                showSearchBox: true,
                searchFieldProps: TextFieldProps(decoration: InputDecoration(hintText: "Search Sampler...")),
              ),
              dropdownDecoratorProps: const DropDownDecoratorProps(
                dropdownSearchDecoration: InputDecoration(labelText: '2nd Sampler (Optional)'),
              ),
            ),

            const SizedBox(height: 16),
            Row(
              children: [
                Expanded(child: TextFormField(controller: _dateController, readOnly: true, decoration: const InputDecoration(labelText: 'Date'))),
                const SizedBox(width: 16),
                Expanded(child: TextFormField(controller: _timeController, readOnly: true, decoration: const InputDecoration(labelText: 'Time'))),
              ],
            ),
            const SizedBox(height: 16),
            DropdownSearch<String>(
              items: _statesList,
              popupProps: const PopupProps.menu(showSearchBox: true, searchFieldProps: TextFieldProps(decoration: InputDecoration(hintText: "Search State..."))),
              dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Select State *")),
              onChanged: (state) {
                setState(() {
                  _data.selectedStateName = state;
                  _data.selectedCategoryName = null;
                  _data.selectedStation = null;
                  _stationLatController.clear();
                  _stationLonController.clear();
                  _distanceDifference = null;

                  if (state != null) {
                    _categoriesForState = allStations.where((s) => s['state_name'] == state).map((s) => s['category_name'] as String?).whereType<String>().toSet().toList();
                    _categoriesForState.sort();
                  } else {
                    _categoriesForState = [];
                  }
                  _stationsForCategory = [];
                });
              },
              validator: (val) => val == null ? "State is required" : null,
            ),
            const SizedBox(height: 16),
            DropdownSearch<String>(
              items: _categoriesForState,
              enabled: _data.selectedStateName != null,
              popupProps: const PopupProps.menu(showSearchBox: true, searchFieldProps: TextFieldProps(decoration: InputDecoration(hintText: "Search Category..."))),
              dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Select Category *")),
              onChanged: (category) {
                setState(() {
                  _data.selectedCategoryName = category;
                  _data.selectedStation = null;
                  _stationLatController.clear();
                  _stationLonController.clear();
                  _distanceDifference = null;

                  if (category != null) {
                    _stationsForCategory = allStations.where((s) => s['state_name'] == _data.selectedStateName && s['category_name'] == category).toList();
                  } else {
                    _stationsForCategory = [];
                  }
                });
              },
              validator: (val) => _data.selectedStateName != null && val == null ? "Category is required" : null,
            ),
            const SizedBox(height: 16),
            DropdownSearch<Map<String, dynamic>>(
              items: _stationsForCategory,
              enabled: _data.selectedCategoryName != null,
              itemAsString: (station) => "${station['tbl_station_code']} - ${station['tbl_station_name']}",
              popupProps: const PopupProps.menu(showSearchBox: true, searchFieldProps: TextFieldProps(decoration: InputDecoration(hintText: "Search Station..."))),
              dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Select Station *")),
              onChanged: (station) => setState(() {
                _data.selectedStation = station;
                _data.stationLatitude = station?['tbl_latitude']?.toString();
                _data.stationLongitude = station?['tbl_longitude']?.toString();
                _stationLatController.text = _data.stationLatitude ?? '';
                _stationLonController.text = _data.stationLongitude ?? '';
                _calculateDistance();
              }),
              validator: (val) => _data.selectedCategoryName != null && val == null ? "Station is required" : null,
              onSaved: (station) => _data.selectedStation = station,
            ),
            const SizedBox(height: 16),
            TextFormField(controller: _stationLatController, readOnly: true, decoration: const InputDecoration(labelText: 'Station Latitude')),
            const SizedBox(height: 16),
            TextFormField(controller: _stationLonController, readOnly: true, decoration: const InputDecoration(labelText: 'Station Longitude')),
            const SizedBox(height: 24),
            Text("Location Verification", style: Theme.of(context).textTheme.titleLarge),
            const SizedBox(height: 16),
            TextFormField(controller: _currentLatController, readOnly: true, decoration: const InputDecoration(labelText: 'Current Latitude')),
            const SizedBox(height: 16),
            TextFormField(controller: _currentLonController, readOnly: true, decoration: const InputDecoration(labelText: 'Current Longitude')),
            if (_distanceDifference != null)
              Padding(
                padding: const EdgeInsets.only(top: 16.0),
                child: Text('Distance from Station: ${_distanceDifference!.toStringAsFixed(2)} km',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      color: _distanceDifference! > 1.0 ? Colors.red : Colors.green,
                    )
                ),
              ),
            const SizedBox(height: 16),
            OutlinedButton.icon(
              onPressed: _isLoading ? null : _getCurrentLocation,
              icon: _isLoading ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2)) : const Icon(Icons.location_searching),
              label: const Text("Get Current Location"),
            ),
            const SizedBox(height: 32),
            ElevatedButton(
              onPressed: _goToNextStep,
              style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
              child: const Text('Next'),
            ),
          ],
        ),
      ),
    );
  }
}
