// lib/screens/river/manual/river_manual_data_status_log.dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:environment_monitoring_app/auth_provider.dart';
import 'package:environment_monitoring_app/models/river_in_situ_sampling_data.dart';
import 'package:environment_monitoring_app/models/river_manual_triennial_sampling_data.dart';
import 'package:environment_monitoring_app/models/river_inves_manual_sampling_data.dart';
import 'package:environment_monitoring_app/services/local_storage_service.dart';
import 'package:environment_monitoring_app/services/river_in_situ_sampling_service.dart';
import 'package:environment_monitoring_app/services/river_manual_triennial_sampling_service.dart';
import 'package:environment_monitoring_app/services/river_investigative_sampling_service.dart';
import 'dart:convert';

/// A simple class to hold an image file and its associated remark.
class ImageLogEntry {
  final File file;
  final String? remark;
  ImageLogEntry({required this.file, this.remark});
}

class SubmissionLogEntry {
  final String type;
  final String title;
  final String stationCode;
  final DateTime submissionDateTime;
  final String? reportId;
  final String status;
  final String message;
  final Map<String, dynamic> rawData;
  final String serverName;
  final String? apiStatusRaw;
  final String? ftpStatusRaw;
  bool isResubmitting;

  SubmissionLogEntry({
    required this.type,
    required this.title,
    required this.stationCode,
    required this.submissionDateTime,
    this.reportId,
    required this.status,
    required this.message,
    required this.rawData,
    required this.serverName,
    this.apiStatusRaw,
    this.ftpStatusRaw,
    this.isResubmitting = false,
  });
}

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

  @override
  State<RiverManualDataStatusLog> createState() => _RiverManualDataStatusLogState();
}

class _RiverManualDataStatusLogState extends State<RiverManualDataStatusLog> {
  final LocalStorageService _localStorageService = LocalStorageService();

  late RiverInSituSamplingService _riverInSituService;
  late RiverManualTriennialSamplingService _riverTriennialService;
  late RiverInvestigativeSamplingService _riverInvestigativeService;

  List<SubmissionLogEntry> _inSituLogs = [];
  List<SubmissionLogEntry> _triennialLogs = [];
  List<SubmissionLogEntry> _investigativeLogs = [];
  List<SubmissionLogEntry> _filteredInSituLogs = [];
  List<SubmissionLogEntry> _filteredTriennialLogs = [];
  List<SubmissionLogEntry> _filteredInvestigativeLogs = [];

  final TextEditingController _inSituSearchController = TextEditingController();
  final TextEditingController _triennialSearchController = TextEditingController();
  final TextEditingController _investigativeSearchController = TextEditingController();

  bool _isLoading = true;
  final Map<String, bool> _isResubmitting = {};

  @override
  void initState() {
    super.initState();
    _inSituSearchController.addListener(_filterLogs);
    _triennialSearchController.addListener(_filterLogs);
    _investigativeSearchController.addListener(_filterLogs);
    _loadAllLogs();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _riverInSituService = Provider.of<RiverInSituSamplingService>(context);
    _riverTriennialService = Provider.of<RiverManualTriennialSamplingService>(context);
    _riverInvestigativeService = Provider.of<RiverInvestigativeSamplingService>(context);
  }

  @override
  void dispose() {
    _inSituSearchController.dispose();
    _triennialSearchController.dispose();
    _investigativeSearchController.dispose();
    super.dispose();
  }

  Future<void> _loadAllLogs() async {
    setState(() => _isLoading = true);

    final inSituLogs = await _localStorageService.getAllRiverInSituLogs();
    final triennialLogs = await _localStorageService.getAllRiverManualTriennialLogs();
    final investigativeLogs = await _localStorageService.getAllRiverInvestigativeLogs();

    final List<SubmissionLogEntry> tempInSitu = [];
    final List<SubmissionLogEntry> tempTriennial = [];
    final List<SubmissionLogEntry> tempInvestigative = [];

    for (var log in inSituLogs) {
      final entry = _createInSituLogEntry(log);
      if (entry != null) {
        tempInSitu.add(entry);
      }
    }

    for (var log in triennialLogs) {
      final entry = _createTriennialLogEntry(log);
      if (entry != null) {
        tempTriennial.add(entry);
      }
    }

    for (var log in investigativeLogs) {
      final entry = _createInvestigativeLogEntry(log);
      if (entry != null) {
        tempInvestigative.add(entry);
      }
    }

    tempInSitu.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));
    tempTriennial.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));
    tempInvestigative.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));

    if (mounted) {
      setState(() {
        _inSituLogs = tempInSitu;
        _triennialLogs = tempTriennial;
        _investigativeLogs = tempInvestigative;
        _isLoading = false;
      });
      _filterLogs();
    }
  }

  SubmissionLogEntry? _createInSituLogEntry(Map<String, dynamic> log) {
    final String type = log['samplingType'] ?? 'In-Situ Sampling';
    final String title = log['selectedStation']?['sampling_river'] ?? 'Unknown River';
    final String stationCode = log['selectedStation']?['sampling_station_code'] ?? 'N/A';

    final String? dateStr = log['samplingDate'] ?? log['r_man_date'];
    final String? timeStr = log['samplingTime'] ?? log['r_man_time'];

    DateTime submissionDateTime = DateTime.fromMillisecondsSinceEpoch(0); // Default to invalid
    try {
      if (dateStr != null && timeStr != null && dateStr.isNotEmpty && timeStr.isNotEmpty) {
        final String fullDateString = '$dateStr ${timeStr.length == 5 ? "$timeStr:00" : timeStr}';
        submissionDateTime = DateTime.tryParse(fullDateString) ?? DateTime.fromMillisecondsSinceEpoch(0);
      }
    } catch (_) {
      // Keep default invalid date
    }

    String? apiStatusRaw;
    if (log['api_status'] != null) {
      apiStatusRaw = log['api_status'] is String ? log['api_status'] : jsonEncode(log['api_status']);
    }
    String? ftpStatusRaw;
    if (log['ftp_status'] != null) {
      ftpStatusRaw = log['ftp_status'] is String ? log['ftp_status'] : jsonEncode(log['ftp_status']);
    }

    return SubmissionLogEntry(
      type: type,
      title: title,
      stationCode: stationCode,
      submissionDateTime: submissionDateTime,
      reportId: log['reportId']?.toString(),
      status: log['submissionStatus'] ?? 'L1',
      message: log['submissionMessage'] ?? 'No status message.',
      rawData: log,
      serverName: log['serverConfigName'] ?? 'Unknown Server',
      apiStatusRaw: apiStatusRaw,
      ftpStatusRaw: ftpStatusRaw,
    );
  }

  SubmissionLogEntry? _createTriennialLogEntry(Map<String, dynamic> log) {
    final String type = log['samplingType'] ?? 'Triennial';
    final String title = log['selectedStation']?['sampling_river'] ?? 'Unknown River';
    final String stationCode = log['selectedStation']?['sampling_station_code'] ?? 'N/A';

    final String? dateStr = log['samplingDate'] ?? log['r_tri_date'];
    final String? timeStr = log['samplingTime'] ?? log['r_tri_time'];

    DateTime submissionDateTime = DateTime.fromMillisecondsSinceEpoch(0); // Default to invalid
    try {
      if (dateStr != null && timeStr != null && dateStr.isNotEmpty && timeStr.isNotEmpty) {
        final String fullDateString = '$dateStr ${timeStr.length == 5 ? "$timeStr:00" : timeStr}';
        submissionDateTime = DateTime.tryParse(fullDateString) ?? DateTime.fromMillisecondsSinceEpoch(0);
      }
    } catch (_) {
      // Keep default invalid date
    }

    String? apiStatusRaw;
    if (log['api_status'] != null) {
      apiStatusRaw = log['api_status'] is String ? log['api_status'] : jsonEncode(log['api_status']);
    }
    String? ftpStatusRaw;
    if (log['ftp_status'] != null) {
      ftpStatusRaw = log['ftp_status'] is String ? log['ftp_status'] : jsonEncode(log['ftp_status']);
    }

    return SubmissionLogEntry(
      type: type,
      title: title,
      stationCode: stationCode,
      submissionDateTime: submissionDateTime,
      reportId: log['reportId']?.toString(),
      status: log['submissionStatus'] ?? 'L1',
      message: log['submissionMessage'] ?? 'No status message.',
      rawData: log,
      serverName: log['serverConfigName'] ?? 'Unknown Server',
      apiStatusRaw: apiStatusRaw,
      ftpStatusRaw: ftpStatusRaw,
    );
  }

  SubmissionLogEntry? _createInvestigativeLogEntry(Map<String, dynamic> log) {
    // Use the data model to correctly determine station name/code
    final data = RiverInvesManualSamplingData.fromJson(log);

    final String type = data.samplingType ?? 'Investigative';
    final String title = data.getDeterminedStationName() ?? 'Unknown River';
    final String stationCode = data.getDeterminedStationCode() ?? 'N/A';

    final String? dateStr = data.samplingDate;
    final String? timeStr = data.samplingTime;

    DateTime submissionDateTime = DateTime.fromMillisecondsSinceEpoch(0); // Default to invalid
    try {
      if (dateStr != null && timeStr != null && dateStr.isNotEmpty && timeStr.isNotEmpty) {
        final String fullDateString = '$dateStr ${timeStr.length == 5 ? "$timeStr:00" : timeStr}';
        submissionDateTime = DateTime.tryParse(fullDateString) ?? DateTime.fromMillisecondsSinceEpoch(0);
      }
    } catch (_) {
      // Keep default invalid date
    }

    String? apiStatusRaw;
    if (log['api_status'] != null) {
      apiStatusRaw = log['api_status'] is String ? log['api_status'] : jsonEncode(log['api_status']);
    }
    String? ftpStatusRaw;
    if (log['ftp_status'] != null) {
      ftpStatusRaw = log['ftp_status'] is String ? log['ftp_status'] : jsonEncode(log['ftp_status']);
    }

    return SubmissionLogEntry(
      type: type,
      title: title,
      stationCode: stationCode,
      submissionDateTime: submissionDateTime,
      reportId: data.reportId,
      status: data.submissionStatus ?? 'L1',
      message: data.submissionMessage ?? 'No status message.',
      rawData: log, // Store the original raw map
      serverName: log['serverConfigName'] ?? 'Unknown Server',
      apiStatusRaw: apiStatusRaw,
      ftpStatusRaw: ftpStatusRaw,
    );
  }

  void _filterLogs() {
    final inSituQuery = _inSituSearchController.text.toLowerCase();
    final triennialQuery = _triennialSearchController.text.toLowerCase();
    final investigativeQuery = _investigativeSearchController.text.toLowerCase();

    setState(() {
      _filteredInSituLogs = _inSituLogs.where((log) => _logMatchesQuery(log, inSituQuery)).toList();
      _filteredTriennialLogs = _triennialLogs.where((log) => _logMatchesQuery(log, triennialQuery)).toList();
      _filteredInvestigativeLogs = _investigativeLogs.where((log) => _logMatchesQuery(log, investigativeQuery)).toList();
    });
  }

  bool _logMatchesQuery(SubmissionLogEntry log, String query) {
    if (query.isEmpty) return true;
    return log.title.toLowerCase().contains(query) ||
        log.stationCode.toLowerCase().contains(query) ||
        log.serverName.toLowerCase().contains(query) ||
        (log.reportId?.toLowerCase() ?? '').contains(query);
  }

  Future<void> _resubmitData(SubmissionLogEntry log) async {
    final logKey = log.reportId ?? log.submissionDateTime.toIso8601String();
    if (mounted) {
      setState(() {
        _isResubmitting[logKey] = true;
      });
    }

    try {
      final authProvider = Provider.of<AuthProvider>(context, listen: false);
      final appSettings = authProvider.appSettings;
      Map<String, dynamic> result = {};

      if (log.type == 'In-Situ Sampling' || log.type == 'Schedule') {
        final dataToResubmit = RiverInSituSamplingData.fromJson(log.rawData);

        result = await _riverInSituService.submitData(
          data: dataToResubmit,
          appSettings: appSettings,
          authProvider: authProvider,
          logDirectory: log.rawData['logDirectory'],
        );
      } else if (log.type == 'Triennial') {
        final dataToResubmit = RiverManualTriennialSamplingData.fromJson(log.rawData);

        result = await _riverTriennialService.submitData(
          data: dataToResubmit,
          appSettings: appSettings,
          authProvider: authProvider,
          logDirectory: log.rawData['logDirectory'],
        );
      } else if (log.type == 'Investigative') {
        final dataToResubmit = RiverInvesManualSamplingData.fromJson(log.rawData);

        result = await _riverInvestigativeService.submitData(
          data: dataToResubmit,
          appSettings: appSettings,
          authProvider: authProvider,
          logDirectory: log.rawData['logDirectory'],
        );
      }

      if (mounted) {
        final message = result['message'] ?? 'Resubmission process completed.';
        final isSuccess = result['success'] as bool? ?? false;
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(message),
            backgroundColor: isSuccess ? Colors.green : (result['status'] == 'L1' ? Colors.red : Colors.orange),
          ),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Resubmission failed: $e')),
        );
      }
    } finally {
      if (mounted) {
        setState(() {
          _isResubmitting.remove(logKey);
        });
        _loadAllLogs();
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final hasAnyLogs = _inSituLogs.isNotEmpty || _triennialLogs.isNotEmpty || _investigativeLogs.isNotEmpty;

    return Scaffold(
      appBar: AppBar(title: const Text('River Manual Data Status Log')),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : RefreshIndicator(
        onRefresh: _loadAllLogs,
        child: !hasAnyLogs
            ? const Center(child: Text('No submission logs found.'))
            : ListView(
          padding: const EdgeInsets.all(8.0),
          children: [
            _buildCategorySection(
                'In-Situ Sampling',
                _filteredInSituLogs,
                _inSituSearchController
            ),
            _buildCategorySection(
                'Triennial Sampling',
                _filteredTriennialLogs,
                _triennialSearchController
            ),
            _buildCategorySection(
                'Investigative Sampling',
                _filteredInvestigativeLogs,
                _investigativeSearchController
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildCategorySection(String category, List<SubmissionLogEntry> logs, TextEditingController searchController) {
    return Card(
      margin: const EdgeInsets.symmetric(vertical: 8.0),
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(category, style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold)),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 8.0),
              child: TextField(
                controller: searchController,
                decoration: InputDecoration(
                  hintText: 'Search in $category...',
                  prefixIcon: const Icon(Icons.search, size: 20),
                  isDense: true,
                  border: const OutlineInputBorder(),
                  suffixIcon: searchController.text.isNotEmpty ? IconButton(
                    icon: const Icon(Icons.clear),
                    onPressed: () {
                      searchController.clear();
                    },
                  ) : null,
                ),
              ),
            ),
            const Divider(),
            if (logs.isEmpty)
              Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Center(child: Text(
                      searchController.text.isEmpty
                          ? 'No logs found in this category.'
                          : 'No logs match your search in this category.'
                  )))
            else
              ListView.builder(
                shrinkWrap: true,
                physics: const NeverScrollableScrollPhysics(),
                itemCount: logs.length,
                itemBuilder: (context, index) {
                  return _buildLogListItem(logs[index]);
                },
              ),
          ],
        ),
      ),
    );
  }

  Widget _buildLogListItem(SubmissionLogEntry log) {
    final bool isFullSuccess = log.status == 'S4';
    final bool isPartialSuccess = log.status == 'S3' || log.status == 'L4';
    final bool canResubmit = !isFullSuccess;

    IconData statusIcon;
    Color statusColor;

    if (isFullSuccess) {
      statusIcon = Icons.check_circle_outline;
      statusColor = Colors.green;
    } else if (isPartialSuccess) {
      statusIcon = Icons.warning_amber_rounded;
      statusColor = Colors.orange;
    } else {
      statusIcon = Icons.error_outline;
      statusColor = Colors.red;
    }

    final logKey = log.reportId ?? log.submissionDateTime.toIso8601String();
    final isResubmitting = _isResubmitting[logKey] ?? false;

    final titleWidget = RichText(
      text: TextSpan(
        style: Theme.of(context).textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500),
        children: <TextSpan>[
          TextSpan(text: '${log.title} '),
          TextSpan(
            text: '(${log.stationCode})',
            style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.normal),
          ),
        ],
      ),
    );

    final bool isDateValid = !log.submissionDateTime.isAtSameMomentAs(DateTime.fromMillisecondsSinceEpoch(0));
    final subtitle = isDateValid
        ? '${log.serverName} - ${DateFormat('yyyy-MM-dd HH:mm').format(log.submissionDateTime)}'
        : '${log.serverName} - Invalid Date';

    return ExpansionTile(
      key: PageStorageKey(logKey),
      leading: Icon(statusIcon, color: statusColor),
      title: titleWidget,
      subtitle: Text(subtitle),
      trailing: canResubmit
          ? (isResubmitting
          ? const SizedBox(height: 24, width: 24, child: CircularProgressIndicator(strokeWidth: 3))
          : IconButton(icon: const Icon(Icons.sync, color: Colors.blue), tooltip: 'Resubmit', onPressed: () => _resubmitData(log)))
          : null,
      children: [
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              _buildDetailRow('High-Level Status:', log.status),
              _buildDetailRow('Server:', log.serverName),
              _buildDetailRow('Report ID:', log.reportId ?? 'N/A'),
              _buildDetailRow('Submission Type:', log.type),

              Padding(
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    TextButton.icon(
                      icon: Icon(Icons.list_alt, color: Theme.of(context).colorScheme.primary),
                      label: Text('View Data', style: TextStyle(color: Theme.of(context).colorScheme.primary)),
                      onPressed: () => _showDataDialog(context, log),
                    ),
                    TextButton.icon(
                      icon: Icon(Icons.photo_library_outlined, color: Theme.of(context).colorScheme.secondary),
                      label: Text('View Images', style: TextStyle(color: Theme.of(context).colorScheme.secondary)),
                      onPressed: () => _showImageDialog(context, log),
                    ),
                  ],
                ),
              ),

              const Divider(height: 10),
              _buildGranularStatus('API', log.apiStatusRaw),
              _buildGranularStatus('FTP', log.ftpStatusRaw),
            ],
          ),
        )
      ],
    );
  }

  /// Builds a formatted category header row for the data table.
  TableRow _buildCategoryRow(BuildContext context, String title, IconData icon) {
    return TableRow(
      decoration: BoxDecoration(
        color: Colors.grey.shade100,
      ),
      children: [
        Padding(
          padding: const EdgeInsets.only(top: 16.0, bottom: 8.0, left: 8.0, right: 8.0),
          child: Row(
            children: [
              Icon(icon, size: 20, color: Theme.of(context).primaryColor),
              const SizedBox(width: 8),
              Text(
                title,
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 16,
                  color: Theme.of(context).primaryColor,
                ),
              ),
            ],
          ),
        ),
        const SizedBox.shrink(), // Empty cell for the second column
      ],
    );
  }

  /// Builds a formatted row for the data dialog, gracefully handling null/empty values.
  TableRow _buildDataTableRow(String label, String? value) {
    String displayValue = (value == null || value.isEmpty || value == 'null') ? 'N/A' : value;

    // Format special "missing" values
    if (displayValue == '-999.0' || displayValue == '-999') {
      displayValue = 'N/A';
    }

    return TableRow(
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
          child: Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
        ),
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
          child: Text(displayValue), // Use Text, NOT SelectableText
        ),
      ],
    );
  }

  /// Formats a camelCase or snake_case key into a readable label.
  String _formatLabel(String key) {
    if (key.isEmpty) return '';

    // Specific overrides for known keys
    const keyOverrides = {
      'sondeId': 'Sonde ID',
      'ph': 'pH',
      'tds': 'TDS',
      'selectedStation': 'Station Details',
      'secondSampler': '2nd Sampler Details',
    };

    if (keyOverrides.containsKey(key)) {
      return keyOverrides[key]!;
    }

    // Handle snake_case (e.g., r_man_date)
    key = key.replaceAllMapped(RegExp(r'_(.)'), (match) => ' ${match.group(1)!.toUpperCase()}');
    // Handle camelCase (e.g., firstSamplerName)
    key = key.replaceAllMapped(RegExp(r'([A-Z])'), (match) => ' ${match.group(1)}');

    // Remove common prefixes
    key = key.replaceAll('r man ', '').replaceAll('r tri ', '').replaceAll('r inv ', '');
    key = key.replaceAll('selected ', '');

    // Capitalize first letter and trim
    key = key.trim();
    key = key.substring(0, 1).toUpperCase() + key.substring(1);

    return key;
  }

  /// Helper to safely get a string value from the raw data map.
  String? _getString(Map<String, dynamic> data, String key) {
    final value = data[key];
    if (value == null) return null;
    if (value is double && value == -999.0) return 'N/A';
    return value.toString();
  }

  /// Shows the categorized and formatted data log in a dialog
  void _showDataDialog(BuildContext context, SubmissionLogEntry log) {
    final Map<String, dynamic> data = log.rawData;
    final List<TableRow> tableRows = [];

    // --- 1. Sampling Info ---
    tableRows.add(_buildCategoryRow(context, 'Sampling Info', Icons.calendar_today));
    tableRows.add(_buildDataTableRow('Date', _getString(data, 'samplingDate')));
    tableRows.add(_buildDataTableRow('Time', _getString(data, 'samplingTime')));
    tableRows.add(_buildDataTableRow('1st Sampler', _getString(data, 'firstSamplerName')));

    String? secondSamplerName;
    if (data['secondSampler'] is Map) {
      secondSamplerName = (data['secondSampler'] as Map)['first_name']?.toString();
    }
    tableRows.add(_buildDataTableRow('2nd Sampler', secondSamplerName));
    tableRows.add(_buildDataTableRow('Sample ID', _getString(data, 'sampleIdCode')));

    // --- 2. Station & Location ---
    tableRows.add(_buildCategoryRow(context, 'Station & Location', Icons.location_on_outlined));

    if (log.type == 'Investigative') {
      tableRows.add(_buildDataTableRow('Station Type', _getString(data, 'stationTypeSelection')));
      if (data['stationTypeSelection'] == 'New Location') {
        tableRows.add(_buildDataTableRow('New State', _getString(data, 'newStateName')));
        tableRows.add(_buildDataTableRow('New Basin', _getString(data, 'newBasinName')));
        tableRows.add(_buildDataTableRow('New River', _getString(data, 'newRiverName')));
        tableRows.add(_buildDataTableRow('New Station Name', _getString(data, 'newStationName')));
        tableRows.add(_buildDataTableRow('New Station Code', _getString(data, 'newStationCode')));
        tableRows.add(_buildDataTableRow('Station Latitude', _getString(data, 'stationLatitude')));
        tableRows.add(_buildDataTableRow('Station Longitude', _getString(data, 'stationLongitude')));
      } else {
        // Show existing station info if it's not a new location
        tableRows.add(_buildDataTableRow('Station', '${log.stationCode} - ${log.title}'));
      }
    } else {
      // For In-Situ and Triennial
      tableRows.add(_buildDataTableRow('Station', '${log.stationCode} - ${log.title}'));
    }

    tableRows.add(_buildDataTableRow('Current Latitude', _getString(data, 'currentLatitude')));
    tableRows.add(_buildDataTableRow('Current Longitude', _getString(data, 'currentLongitude')));
    tableRows.add(_buildDataTableRow('Distance (km)', _getString(data, 'distanceDifferenceInKm')));
    tableRows.add(_buildDataTableRow('Distance Remarks', _getString(data, 'distanceDifferenceRemarks')));

    // --- 3. Site Conditions ---
    tableRows.add(_buildCategoryRow(context, 'Site Conditions', Icons.wb_sunny_outlined));
    tableRows.add(_buildDataTableRow('Weather', _getString(data, 'weather')));
    tableRows.add(_buildDataTableRow('Event Remarks', _getString(data, 'eventRemarks')));
    tableRows.add(_buildDataTableRow('Lab Remarks', _getString(data, 'labRemarks')));

    // --- 4. Parameters ---
    tableRows.add(_buildCategoryRow(context, 'Parameters', Icons.bar_chart));
    tableRows.add(_buildDataTableRow('Sonde ID', _getString(data, 'sondeId')));
    tableRows.add(_buildDataTableRow('Capture Date', _getString(data, 'dataCaptureDate')));
    tableRows.add(_buildDataTableRow('Capture Time', _getString(data, 'dataCaptureTime')));
    tableRows.add(_buildDataTableRow('Oxygen Conc (mg/L)', _getString(data, 'oxygenConcentration')));
    tableRows.add(_buildDataTableRow('Oxygen Sat (%)', _getString(data, 'oxygenSaturation')));
    tableRows.add(_buildDataTableRow('pH', _getString(data, 'ph')));
    tableRows.add(_buildDataTableRow('Salinity (ppt)', _getString(data, 'salinity')));
    tableRows.add(_buildDataTableRow('Conductivity (µS/cm)', _getString(data, 'electricalConductivity')));
    tableRows.add(_buildDataTableRow('Temperature (°C)', _getString(data, 'temperature')));
    tableRows.add(_buildDataTableRow('TDS (mg/L)', _getString(data, 'tds')));
    tableRows.add(_buildDataTableRow('Turbidity (NTU)', _getString(data, 'turbidity')));
    tableRows.add(_buildDataTableRow('Ammonia (mg/L)', _getString(data, 'ammonia')));
    tableRows.add(_buildDataTableRow('Battery (V)', _getString(data, 'batteryVoltage')));

    // --- 5. Flowrate ---
    if (data['flowrateMethod'] != null || data['flowrateValue'] != null) {
      tableRows.add(_buildCategoryRow(context, 'Flowrate', Icons.waves_outlined));
      tableRows.add(_buildDataTableRow('Method', _getString(data, 'flowrateMethod')));
      tableRows.add(_buildDataTableRow('Flowrate (m/s)', _getString(data, 'flowrateValue')));
      if (data['flowrateMethod'] == 'Surface Drifter') {
        tableRows.add(_buildDataTableRow('  Height (m)', _getString(data, 'flowrateSurfaceDrifterHeight')));
        tableRows.add(_buildDataTableRow('  Distance (m)', _getString(data, 'flowrateSurfaceDrifterDistance')));
        tableRows.add(_buildDataTableRow('  Time First', _getString(data, 'flowrateSurfaceDrifterTimeFirst')));
        tableRows.add(_buildDataTableRow('  Time Last', _getString(data, 'flowrateSurfaceDrifterTimeLast')));
      }
    }

    showDialog(
      context: context,
      builder: (context) {
        return AlertDialog(
          // --- MODIFIED: Use Station Code + Name for title ---
          title: Text('${log.stationCode} - ${log.title}'),
          content: SizedBox(
            width: double.maxFinite,
            child: SingleChildScrollView(
              child: Table(
                columnWidths: const {
                  0: IntrinsicColumnWidth(),
                  1: FlexColumnWidth(),
                },
                border: TableBorder(
                  horizontalInside: BorderSide(
                    color: Colors.grey.shade300,
                    width: 0.5,
                  ),
                ),
                children: tableRows,
              ),
            ),
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('Close'),
            ),
          ],
        );
      },
    );
  }

  void _showImageDialog(BuildContext context, SubmissionLogEntry log) {
    // These are the standard keys used in toMap() for all river models
    // We map the image key to its corresponding remark key.
    const imageRemarkMap = {
      'backgroundStationImage': null, // No remark for this
      'upstreamRiverImage': null, // No remark for this
      'downstreamRiverImage': null, // No remark for this
      'sampleTurbidityImage': null, // No remark for this
      'optionalImage1': 'optionalRemark1',
      'optionalImage2': 'optionalRemark2',
      'optionalImage3': 'optionalRemark3',
      'optionalImage4': 'optionalRemark4',
    };

    final List<ImageLogEntry> imageEntries = [];
    for (final entry in imageRemarkMap.entries) {
      final imageKey = entry.key;
      final remarkKey = entry.value;

      final path = log.rawData[imageKey];
      if (path != null && path is String && path.isNotEmpty) {
        final file = File(path);
        if (file.existsSync()) {
          // Now, find the remark
          final remark = (remarkKey != null ? log.rawData[remarkKey] as String? : null)
              // Also check for API-style remark keys just in case
              ?? log.rawData['${imageKey}Remark'] as String?
              ?? log.rawData['${imageKey}_remarks'] as String?;

          imageEntries.add(ImageLogEntry(file: file, remark: remark));
        }
      }
    }


    if (imageEntries.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('No images are attached to this log.'),
          backgroundColor: Colors.orange,
        ),
      );
      return;
    }

    showDialog(
      context: context,
      builder: (context) {
        return AlertDialog(
          // --- START: MODIFIED TITLE ---
          title: Text('Images for ${log.stationCode} - ${log.title}'),
          // --- END: MODIFIED TITLE ---
          content: SizedBox(
            width: double.maxFinite,
            child: GridView.builder(
              shrinkWrap: true,
              itemCount: imageEntries.length,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                crossAxisSpacing: 8,
                mainAxisSpacing: 8,
              ),
              itemBuilder: (context, index) {
                final imageEntry = imageEntries[index];
                final bool hasRemark = imageEntry.remark != null && imageEntry.remark!.isNotEmpty;

                return Card(
                  clipBehavior: Clip.antiAlias,
                  elevation: 2,
                  child: Stack(
                    fit: StackFit.expand,
                    children: [
                      Image.file(
                        imageEntry.file,
                        fit: BoxFit.cover,
                        errorBuilder: (context, error, stack) {
                          return const Center(
                            child: Icon(
                              Icons.broken_image,
                              color: Colors.grey,
                              size: 40,
                            ),
                          );
                        },
                      ),
                      if (hasRemark)
                        Positioned(
                          bottom: 0,
                          left: 0,
                          right: 0,
                          child: Container(
                            padding: const EdgeInsets.all(6.0),
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                begin: Alignment.bottomCenter,
                                end: Alignment.topCenter,
                                colors: [
                                  Colors.black.withOpacity(0.8),
                                  Colors.black.withOpacity(0.0)
                                ],
                              ),
                            ),
                            child: Text(
                              imageEntry.remark!,
                              style: const TextStyle(
                                color: Colors.white,
                                fontSize: 12,
                                fontWeight: FontWeight.bold,
                              ),
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                            ),
                          ),
                        ),
                    ],
                  ),
                );
              },
            ),
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('Close'),
            ),
          ],
        );
      },
    );
  }

  Widget _buildGranularStatus(String type, String? jsonStatus) {
    if (jsonStatus == null || jsonStatus.isEmpty) {
      return Container();
    }

    List<dynamic> statuses;
    try {
      statuses = jsonDecode(jsonStatus);
    } catch (_) {
      return _buildDetailRow('$type Status:', jsonStatus);
    }

    if (statuses.isEmpty) {
      return Container();
    }

    return Padding(
      padding: const EdgeInsets.only(top: 8.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('$type Status:', style: const TextStyle(fontWeight: FontWeight.bold)),
          ...statuses.map((s) {
            final serverName = s['server_name'] ?? s['config_name'] ?? 'Server N/A';
            final status = s['message'] ?? 'N/A';
            final bool isSuccess = s['success'] as bool? ?? false;
            final IconData icon = isSuccess ? Icons.check_circle_outline : Icons.error_outline;
            final Color color = isSuccess ? Colors.green : Colors.red;
            String detailLabel = (s['type'] != null) ? '(${s['type']})' : '';

            return Padding(
              padding: const EdgeInsets.symmetric(vertical: 3.0, horizontal: 8.0),
              child: Row(
                children: [
                  Icon(icon, size: 16, color: color),
                  const SizedBox(width: 5),
                  Expanded(child: Text('$serverName $detailLabel: $status')),
                ],
              ),
            );
          }).toList(),
        ],
      ),
    );
  }

  Widget _buildDetailRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Expanded(flex: 2, child: Text(label, style: const TextStyle(fontWeight: FontWeight.bold))),
          const SizedBox(width: 8),
          Expanded(flex: 3, child: Text(value)), // <-- This is the fixed line
        ],
      ),
    );
  }
}