// lib/screens/air/manual/air_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/air_installation_data.dart';
import 'package:environment_monitoring_app/models/air_collection_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/air_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 AirManualDataStatusLog extends StatefulWidget {
  const AirManualDataStatusLog({super.key});

  @override
  State<AirManualDataStatusLog> createState() => _AirManualDataStatusLogState();
}

class _AirManualDataStatusLogState extends State<AirManualDataStatusLog> {
  final LocalStorageService _localStorageService = LocalStorageService();
  late ApiService _apiService;
  late AirSamplingService _airSamplingService;

  List<SubmissionLogEntry> _allLogs = [];
  List<SubmissionLogEntry> _installationLogs = [];
  List<SubmissionLogEntry> _collectionLogs = [];
  List<SubmissionLogEntry> _filteredInstallationLogs = [];
  List<SubmissionLogEntry> _filteredCollectionLogs = [];

  final TextEditingController _installationSearchController = TextEditingController();
  final TextEditingController _collectionSearchController = TextEditingController();

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

  @override
  void initState() {
    super.initState();
    _apiService = Provider.of<ApiService>(context, listen: false);
    _airSamplingService = Provider.of<AirSamplingService>(context, listen: false);
    _installationSearchController.addListener(_filterLogs);
    _collectionSearchController.addListener(_filterLogs);
    _loadAllLogs();
  }

  @override
  void dispose() {
    _installationSearchController.dispose();
    _collectionSearchController.dispose();
    super.dispose();
  }

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

    final airLogs = await _localStorageService.getAllAirSamplingLogs();
    final List<SubmissionLogEntry> tempInstallationLogs = [];
    final List<SubmissionLogEntry> tempCollectionLogs = [];

    if (airLogs != null) {
      for (var log in airLogs) {
        if (log.containsKey('collectionData') && log['collectionData'] != null) {
          // This is a collection log
          final collectionData = log['collectionData'];
          final String dateStr = collectionData['air_man_collection_date'] ?? '';
          final String timeStr = collectionData['air_man_collection_time'] ?? '';

          tempCollectionLogs.add(SubmissionLogEntry(
            type: 'Collection',
            title: log['locationName'] ?? 'Unknown Location',
            stationCode: log['stationID'] ?? 'N/A',
            submissionDateTime: DateTime.tryParse('$dateStr $timeStr') ?? DateTime.now(),
            reportId: collectionData['air_man_id']?.toString(),
            status: collectionData['status'] ?? 'L3',
            message: collectionData['submissionMessage'] ?? 'No status message.',
            rawData: log,
            serverName: log['serverConfigName'] ?? 'Unknown Server',
            apiStatusRaw: collectionData['api_status'],
            ftpStatusRaw: collectionData['ftp_status'],
          ));
        } else {
          // This is an installation log
          final String dateStr = log['installationDate'] ?? '';
          final String timeStr = log['installationTime'] ?? '';

          tempInstallationLogs.add(SubmissionLogEntry(
            type: 'Installation',
            title: log['locationName'] ?? 'Unknown Location',
            stationCode: log['stationID'] ?? 'N/A',
            submissionDateTime: DateTime.tryParse('$dateStr $timeStr') ?? DateTime.now(),
            reportId: log['air_man_id']?.toString(),
            status: log['status'] ?? 'L1',
            message: log['submissionMessage'] ?? 'No status message.',
            rawData: log,
            serverName: log['serverConfigName'] ?? 'Unknown Server',
            apiStatusRaw: log['api_status'],
            ftpStatusRaw: log['ftp_status'],
          ));
        }
      }
    }

    tempInstallationLogs.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));
    tempCollectionLogs.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));

    if (mounted) {
      setState(() {
        _installationLogs = tempInstallationLogs;
        _collectionLogs = tempCollectionLogs;
        _isLoading = false;
      });
      _filterLogs();
    }
  }

  void _filterLogs() {
    final installationQuery = _installationSearchController.text.toLowerCase();
    final collectionQuery = _collectionSearchController.text.toLowerCase();

    setState(() {
      _filteredInstallationLogs = _installationLogs.where((log) => _logMatchesQuery(log, installationQuery)).toList();
      _filteredCollectionLogs = _collectionLogs.where((log) => _logMatchesQuery(log, collectionQuery)).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;
      final logData = log.rawData;
      Map<String, dynamic> result = {};

      if (log.type == 'Installation') {
        final dataToResubmit = AirInstallationData.fromJson(logData);
        final result = await _airSamplingService.submitInstallation(dataToResubmit, appSettings);
        // We only care about the high-level status here as granular status is handled by the service.
      } else if (log.type == 'Collection') {
        final installationData = AirInstallationData.fromJson(logData);
        final collectionData = AirCollectionData.fromMap(logData['collectionData']);
        final result = await _airSamplingService.submitCollection(collectionData, installationData, appSettings);
      }

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Resubmission successful!')),
        );
      }
    } 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 = _installationLogs.isNotEmpty || _collectionLogs.isNotEmpty;

    return Scaffold(
      appBar: AppBar(title: const Text('Air 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('Installation', _filteredInstallationLogs, _installationSearchController),
            _buildCategorySection('Collection', _filteredCollectionLogs, _collectionSearchController),
          ],
        ),
      ),
    );
  }

  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: IconButton(
                    icon: const Icon(Icons.clear),
                    onPressed: () {
                      searchController.clear();
                      _filterLogs();
                    },
                  ),
                ),
              ),
            ),
            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 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 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'] ?? 'Server N/A';
            final status = s['status'] ?? 'N/A';
            final bool isSuccess = status.toLowerCase().contains('success') || status.toLowerCase().contains('queued') || status.toLowerCase().contains('not_configured') || status.toLowerCase().contains('not_applicable') || status.toLowerCase().contains('not_required');
            final IconData icon = isSuccess ? Icons.check_circle_outline : (status.toLowerCase().contains('failed') ? Icons.error_outline : Icons.sync);
            final Color color = isSuccess ? Colors.green : (status.toLowerCase().contains('failed') ? Colors.red : Colors.grey);
            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)),
        ],
      ),
    );
  }
}