// lib/screens/marine/manual/marine_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/tarball_data.dart';
import 'package:environment_monitoring_app/models/in_situ_sampling_data.dart';
import 'package:environment_monitoring_app/services/local_storage_service.dart';
import 'package:environment_monitoring_app/services/api_service.dart';
// START CHANGE: Import the new dedicated services
import 'package:environment_monitoring_app/services/marine_in_situ_sampling_service.dart';
import 'package:environment_monitoring_app/services/marine_tarball_sampling_service.dart';
// END CHANGE
import 'dart:convert';


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 MarineManualDataStatusLog extends StatefulWidget {
  const MarineManualDataStatusLog({super.key});

  @override
  State<MarineManualDataStatusLog> createState() => _MarineManualDataStatusLogState();
}

class _MarineManualDataStatusLogState extends State<MarineManualDataStatusLog> {
  final LocalStorageService _localStorageService = LocalStorageService();
  // MODIFIED: Declare the service variables but do not instantiate them here.
  late MarineInSituSamplingService _marineInSituService;
  late MarineTarballSamplingService _marineTarballService;

  List<SubmissionLogEntry> _manualLogs = [];
  List<SubmissionLogEntry> _tarballLogs = [];
  List<SubmissionLogEntry> _filteredManualLogs = [];
  List<SubmissionLogEntry> _filteredTarballLogs = [];

  final TextEditingController _manualSearchController = TextEditingController();
  final TextEditingController _tarballSearchController = TextEditingController();

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

  @override
  void initState() {
    super.initState();
    // MODIFIED: Service instantiations are removed from initState.
    // They will be initialized in didChangeDependencies.
    _manualSearchController.addListener(_filterLogs);
    _tarballSearchController.addListener(_filterLogs);
    _loadAllLogs();
  }

  // ADDED: didChangeDependencies to safely get services from the Provider.
  // This is the correct lifecycle method for this purpose.
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // Fetch the single, global instances of the services from the Provider tree.
    _marineInSituService = Provider.of<MarineInSituSamplingService>(context);
    _marineTarballService = Provider.of<MarineTarballSamplingService>(context);
  }

  @override
  void dispose() {
    _manualSearchController.dispose();
    _tarballSearchController.dispose();
    super.dispose();
  }

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

    final tarballLogs = await _localStorageService.getAllTarballLogs();
    final inSituLogs = await _localStorageService.getAllInSituLogs();

    final List<SubmissionLogEntry> tempManual = [];
    final List<SubmissionLogEntry> tempTarball = [];

    for (var log in inSituLogs) {
      // START FIX: Use backward-compatible keys to read the timestamp
      final String dateStr = log['sampling_date'] ?? log['man_date'] ?? '';
      final String timeStr = log['sampling_time'] ?? log['man_time'] ?? '';
      // END FIX

      // --- START FIX: Prevent fallback to DateTime.now() to make errors visible ---
      final dt = DateTime.tryParse('$dateStr $timeStr');
      // --- END FIX ---

      tempManual.add(SubmissionLogEntry(
        type: 'Manual Sampling',
        title: log['selectedStation']?['man_station_name'] ?? 'Unknown Station',
        stationCode: log['selectedStation']?['man_station_code'] ?? 'N/A',
        // --- START FIX: Use the parsed date or a placeholder for invalid entries ---
        submissionDateTime: dt ?? DateTime.fromMillisecondsSinceEpoch(0),
        // --- END FIX ---
        reportId: log['reportId']?.toString(),
        status: log['submissionStatus'] ?? 'L1',
        message: log['submissionMessage'] ?? 'No status message.',
        rawData: log,
        serverName: log['serverConfigName'] ?? 'Unknown Server',
        apiStatusRaw: log['api_status'],
        ftpStatusRaw: log['ftp_status'],
      ));
    }

    for (var log in tarballLogs) {
      final dateStr = log['sampling_date'] ?? '';
      final timeStr = log['sampling_time'] ?? '';

      tempTarball.add(SubmissionLogEntry(
        type: 'Tarball Sampling',
        title: log['selectedStation']?['tbl_station_name'] ?? 'Unknown Station',
        stationCode: log['selectedStation']?['tbl_station_code'] ?? 'N/A',
        submissionDateTime: DateTime.tryParse('$dateStr $timeStr') ?? DateTime.fromMillisecondsSinceEpoch(0),
        reportId: log['reportId']?.toString(),
        status: log['submissionStatus'] ?? 'L1',
        message: log['submissionMessage'] ?? 'No status message.',
        rawData: log,
        serverName: log['serverConfigName'] ?? 'Unknown Server',
        apiStatusRaw: log['api_status'],
        ftpStatusRaw: log['ftp_status'],
      ));
    }

    tempManual.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));
    tempTarball.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));

    if (mounted) {
      setState(() {
        _manualLogs = tempManual;
        _tarballLogs = tempTarball;
        _isLoading = false;
      });
      _filterLogs();
    }
  }

  void _filterLogs() {
    final manualQuery = _manualSearchController.text.toLowerCase();
    final tarballQuery = _tarballSearchController.text.toLowerCase();

    setState(() {
      _filteredManualLogs = _manualLogs.where((log) => _logMatchesQuery(log, manualQuery)).toList();
      _filteredTarballLogs = _tarballLogs.where((log) => _logMatchesQuery(log, tarballQuery)).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);
  }

  File? _createFileFromPath(String? path) {
    if (path != null && path.isNotEmpty) {
      return File(path);
    }
    return null;
  }

  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 == 'Manual Sampling') {
        // --- START FIX: Rely on the now-robust fromJson factory for cleaner reconstruction ---
        final dataToResubmit = InSituSamplingData.fromJson(log.rawData);
        // --- END FIX ---

        result = await _marineInSituService.submitInSituSample(
          data: dataToResubmit,
          appSettings: appSettings,
          context: context,
          authProvider: authProvider,
          logDirectory: log.rawData['logDirectory'] as String?,
        );
      } else if (log.type == 'Tarball Sampling') {
        final dataToResubmit = TarballSamplingData();
        final logData = log.rawData;

        dataToResubmit.firstSampler = logData['first_sampler_name'];
        dataToResubmit.firstSamplerUserId = int.tryParse(logData['first_sampler_user_id']?.toString() ?? '');
        dataToResubmit.secondSampler = logData['secondSampler'];
        dataToResubmit.samplingDate = logData['sampling_date'];
        dataToResubmit.samplingTime = logData['sampling_time'];
        dataToResubmit.selectedStateName = logData['selectedStation']?['state_name'];
        dataToResubmit.selectedCategoryName = logData['selectedStation']?['category_name'];
        dataToResubmit.selectedStation = logData['selectedStation'];
        dataToResubmit.stationLatitude = logData['selectedStation']?['tbl_latitude']?.toString();
        dataToResubmit.stationLongitude = logData['selectedStation']?['tbl_longitude']?.toString();
        dataToResubmit.currentLatitude = logData['current_latitude'];
        dataToResubmit.currentLongitude = logData['current_longitude'];
        dataToResubmit.distanceDifference = double.tryParse(logData['distance_difference']?.toString() ?? '');
        dataToResubmit.distanceDifferenceRemarks = logData['distance_remarks'];
        dataToResubmit.classificationId = int.tryParse(logData['classification_id']?.toString() ?? '');
        dataToResubmit.selectedClassification = logData['selectedClassification'];
        dataToResubmit.optionalRemark1 = logData['optional_photo_remark_01'];
        dataToResubmit.optionalRemark2 = logData['optional_photo_remark_02'];
        dataToResubmit.optionalRemark3 = logData['optional_photo_remark_03'];
        dataToResubmit.optionalRemark4 = logData['optional_photo_remark_04'];
        dataToResubmit.leftCoastalViewImage = _createFileFromPath(logData['left_side_coastal_view']);
        dataToResubmit.rightCoastalViewImage = _createFileFromPath(logData['right_side_coastal_view']);
        dataToResubmit.verticalLinesImage = _createFileFromPath(logData['drawing_vertical_lines']);
        dataToResubmit.horizontalLineImage = _createFileFromPath(logData['drawing_horizontal_line']);
        dataToResubmit.optionalImage1 = _createFileFromPath(logData['optional_photo_01']);
        dataToResubmit.optionalImage2 = _createFileFromPath(logData['optional_photo_02']);
        dataToResubmit.optionalImage3 = _createFileFromPath(logData['optional_photo_03']);
        dataToResubmit.optionalImage4 = _createFileFromPath(logData['optional_photo_04']);

        result = await _marineTarballService.submitTarballSample(
          data: dataToResubmit,
          appSettings: appSettings,
          context: context,
        );
      }

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(result['message'] ?? 'Resubmission process completed.')),
        );
      }
    } 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 = _manualLogs.isNotEmpty || _tarballLogs.isNotEmpty;

    return Scaffold(
      appBar: AppBar(title: const Text('Marine 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('Manual Sampling', _filteredManualLogs, _manualSearchController),
            _buildCategorySection('Tarball Sampling', _filteredTarballLogs, _tarballSearchController),
          ],
        ),
      ),
    );
  }

  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)
              const Padding(
                  padding: EdgeInsets.all(16.0),
                  child: Center(child: Text('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 logKey = log.reportId ?? log.submissionDateTime.toIso8601String();
    final isResubmitting = _isResubmitting[logKey] ?? false;

    // --- START: MODIFICATION FOR GRANULAR STATUS ICONS ---
    // Define the different states based on the detailed status code.
    final bool isFullSuccess = log.status == 'S4';
    final bool isPartialSuccess = log.status == 'S3' || log.status == 'L4';
    final bool canResubmit = !isFullSuccess; // Allow resubmission for partial success or failure.

    // Determine the icon and color based on the state.
    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;
    }
    // --- END: MODIFICATION FOR GRANULAR STATUS ICONS ---

    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),
            ],
          ),
        )
      ],
    );
  }

  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)),
        ],
      ),
    );
  }
}