// 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/services/local_storage_service.dart';
import 'package:environment_monitoring_app/services/api_service.dart';
import 'package:environment_monitoring_app/services/river_in_situ_sampling_service.dart';
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 RiverManualDataStatusLog extends StatefulWidget {
  const RiverManualDataStatusLog({super.key});

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

class _RiverManualDataStatusLogState extends State<RiverManualDataStatusLog> {
  final LocalStorageService _localStorageService = LocalStorageService();
  late ApiService _apiService;
  late RiverInSituSamplingService _riverInSituService;

  List<SubmissionLogEntry> _allLogs = [];
  List<SubmissionLogEntry> _filteredLogs = [];
  final TextEditingController _searchController = TextEditingController();
  bool _isLoading = true;
  final Map<String, bool> _isResubmitting = {};

  @override
  void initState() {
    super.initState();
    _apiService = Provider.of<ApiService>(context, listen: false);
    _riverInSituService = Provider.of<RiverInSituSamplingService>(context, listen: false);
    _searchController.addListener(_filterLogs);
    _loadAllLogs();
  }

  @override
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }

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

    final riverLogs = await _localStorageService.getAllRiverInSituLogs();
    final List<SubmissionLogEntry> tempLogs = [];

    for (var log in riverLogs) {
      final entry = _createLogEntry(log);
      if (entry != null) {
        tempLogs.add(entry);
      }
    }

    tempLogs.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));
    if (mounted) {
      setState(() {
        _allLogs = tempLogs;
        _isLoading = false;
      });
      _filterLogs();
    }
  }

  SubmissionLogEntry? _createLogEntry(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';
    DateTime submissionDateTime = DateTime.now();
    final String? dateStr = log['samplingDate'] ?? log['r_man_date'];
    final String? timeStr = log['samplingTime'] ?? log['r_man_time'];

    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.now();
      }
    } catch (_) {
      submissionDateTime = DateTime.now();
    }

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

  void _filterLogs() {
    final query = _searchController.text.toLowerCase();
    setState(() {
      _filteredLogs = _allLogs.where((log) => _logMatchesQuery(log, query)).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.type.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;

      final dataToResubmit = RiverInSituSamplingData.fromJson(log.rawData);

      final result = await _riverInSituService.submitData(
        data: dataToResubmit,
        appSettings: appSettings,
        authProvider: authProvider,
        logDirectory: log.rawData['logDirectory'], // Pass the log directory for updating
      );

      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 : 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 = _allLogs.isNotEmpty;
    final hasFilteredLogs = _filteredLogs.isNotEmpty;

    final Map<String, List<SubmissionLogEntry>> groupedLogs = {};
    for (var log in _filteredLogs) {
      if (!groupedLogs.containsKey(log.type)) {
        groupedLogs[log.type] = [];
      }
      groupedLogs[log.type]!.add(log);
    }

    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: [
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
              child: TextField(
                controller: _searchController,
                decoration: InputDecoration(
                  hintText: 'Search river, station code, or server name...',
                  prefixIcon: const Icon(Icons.search, size: 20),
                  isDense: true,
                  border: const OutlineInputBorder(),
                  suffixIcon: IconButton(
                    icon: const Icon(Icons.clear),
                    onPressed: () {
                      _searchController.clear();
                      _filterLogs();
                    },
                  ),
                ),
              ),
            ),
            const Divider(),
            if (!hasFilteredLogs && hasAnyLogs && _searchController.text.isNotEmpty)
              const Center(
                child: Padding(
                  padding: EdgeInsets.all(24.0),
                  child: Text('No logs match your search.'),
                ),
              )
            else
              ...groupedLogs.entries.map((entry) => _buildCategorySection(entry.key, entry.value)),
          ],
        ),
      ),
    );
  }

  Widget _buildCategorySection(String category, List<SubmissionLogEntry> logs) {
    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)),
            const Divider(),
            ListView.builder(
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemCount: logs.length,
              itemBuilder: (context, index) {
                return _buildLogListItem(logs[index]);
              },
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildLogListItem(SubmissionLogEntry log) {
    final isFailed = !log.status.startsWith('S') && !log.status.startsWith('L4');
    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 subtitle = '${log.serverName} - ${DateFormat('yyyy-MM-dd HH:mm').format(log.submissionDateTime)}';

    return Card(
      margin: const EdgeInsets.symmetric(vertical: 4.0),
      child: ExpansionTile(
        key: PageStorageKey(logKey),
        leading: Icon(
          isFailed ? Icons.error_outline : Icons.check_circle_outline,
          color: isFailed ? Colors.red : Colors.green,
        ),
        title: titleWidget,
        subtitle: Text(subtitle),
        trailing: isFailed
            ? (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),
                const Divider(height: 10),
                _buildGranularStatus('API', log.apiStatusRaw),
                _buildGranularStatus('FTP', log.ftpStatusRaw),
              ],
            ),
          )
        ],
      ),
    );
  }

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