import 'dart:io';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import '../../../../models/river_in_situ_sampling_data.dart';
import '../../../../services/local_storage_service.dart';
import '../../../../services/river_api_service.dart';

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;
  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,
    this.isResubmitting = false,
  });
}

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

  @override
  State<RiverDataStatusLog> createState() => _RiverDataStatusLogState();
}

class _RiverDataStatusLogState extends State<RiverDataStatusLog> {
  final LocalStorageService _localStorageService = LocalStorageService();
  final RiverApiService _riverApiService = RiverApiService();

  // Raw data lists
  List<SubmissionLogEntry> _scheduleLogs = [];
  List<SubmissionLogEntry> _triennialLogs = [];
  List<SubmissionLogEntry> _otherLogs = [];

  // Filtered lists for the UI
  List<SubmissionLogEntry> _filteredScheduleLogs = [];
  List<SubmissionLogEntry> _filteredTriennialLogs = [];
  List<SubmissionLogEntry> _filteredOtherLogs = [];

  // Per-category search controllers
  final Map<String, TextEditingController> _searchControllers = {};

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

  @override
  void initState() {
    super.initState();
    _searchControllers['Schedule'] = TextEditingController()..addListener(_filterLogs);
    _searchControllers['Triennial'] = TextEditingController()..addListener(_filterLogs);
    _searchControllers['Others'] = TextEditingController()..addListener(_filterLogs);
    _loadAllLogs();
  }

  @override
  void dispose() {
    _searchControllers['Schedule']?.dispose();
    _searchControllers['Triennial']?.dispose();
    _searchControllers['Others']?.dispose();
    super.dispose();
  }

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

    final riverLogs = await _localStorageService.getAllRiverInSituLogs();

    final List<SubmissionLogEntry> tempSchedule = [];
    final List<SubmissionLogEntry> tempTriennial = [];
    final List<SubmissionLogEntry> tempOthers = [];

    for (var log in riverLogs) {
      final entry = SubmissionLogEntry(
        type: log['r_man_type'] as String? ?? 'Others',
        title: log['selectedStation']?['sampling_river'] ?? 'Unknown Station',
        stationCode: log['selectedStation']?['sampling_station_code'] ?? 'N/A',
        submissionDateTime: DateTime.tryParse('${log['r_man_date']} ${log['r_man_time']}') ?? DateTime.now(),
        reportId: log['reportId']?.toString(),
        status: log['submissionStatus'] ?? 'L1',
        message: log['submissionMessage'] ?? 'No status message.',
        rawData: log,
      );

      switch (entry.type) {
        case 'Schedule':
          tempSchedule.add(entry);
          break;
        case 'Triennial':
          tempTriennial.add(entry);
          break;
        default:
          tempOthers.add(entry);
          break;
      }
    }

    tempSchedule.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));
    tempTriennial.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));
    tempOthers.sort((a, b) => b.submissionDateTime.compareTo(a.submissionDateTime));

    if (mounted) {
      setState(() {
        _scheduleLogs = tempSchedule;
        _triennialLogs = tempTriennial;
        _otherLogs = tempOthers;
        _isLoading = false;
      });
      _filterLogs(); // Perform initial filter
    }
  }

  void _filterLogs() {
    final scheduleQuery = _searchControllers['Schedule']?.text.toLowerCase() ?? '';
    final triennialQuery = _searchControllers['Triennial']?.text.toLowerCase() ?? '';
    final otherQuery = _searchControllers['Others']?.text.toLowerCase() ?? '';

    setState(() {
      _filteredScheduleLogs = _scheduleLogs.where((log) => _logMatchesQuery(log, scheduleQuery)).toList();
      _filteredTriennialLogs = _triennialLogs.where((log) => _logMatchesQuery(log, triennialQuery)).toList();
      _filteredOtherLogs = _otherLogs.where((log) => _logMatchesQuery(log, otherQuery)).toList();
    });
  }

  bool _logMatchesQuery(SubmissionLogEntry log, String query) {
    if (query.isEmpty) return true;
    return log.title.toLowerCase().contains(query) ||
        log.stationCode.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 logData = log.rawData;
      final dataToResubmit = RiverInSituSamplingData.fromJson(logData);
      final Map<String, File?> imageFiles = {};

      final imageApiKeys = dataToResubmit.toApiImageFiles().keys;
      for (var key in imageApiKeys) {
        final imagePath = logData[key];
        if (imagePath is String && imagePath.isNotEmpty) {
          final file = File(imagePath);
          if (await file.exists()) {
            imageFiles[key] = file;
          }
        }
      }

      final result = await _riverApiService.submitInSituSample(
        formData: dataToResubmit.toApiFormData(),
        imageFiles: imageFiles,
      );

      logData['submissionStatus'] = result['status'];
      logData['submissionMessage'] = result['message'];
      logData['reportId'] = result['reportId']?.toString() ?? logData['reportId'];
      await _localStorageService.updateRiverInSituLog(logData);

      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);
        });
        await _loadAllLogs();
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final hasAnyLogs = _scheduleLogs.isNotEmpty || _triennialLogs.isNotEmpty || _otherLogs.isNotEmpty;
    final hasFilteredLogs = _filteredScheduleLogs.isNotEmpty || _filteredTriennialLogs.isNotEmpty || _filteredOtherLogs.isNotEmpty;

    final logCategories = {
      'Schedule': _filteredScheduleLogs,
      'Triennial': _filteredTriennialLogs,
      'Others': _filteredOtherLogs,
    };

    return Scaffold(
      appBar: AppBar(title: const Text('River 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: [
            ...logCategories.entries
                .where((entry) => entry.value.isNotEmpty)
                .map((entry) => _buildCategorySection(entry.key, entry.value)),
            if (!hasFilteredLogs && hasAnyLogs)
              const Center(
                child: Padding(
                  padding: EdgeInsets.all(24.0),
                  child: Text('No logs match your search.'),
                ),
              )
          ],
        ),
      ),
    );
  }

  Widget _buildCategorySection(String category, List<SubmissionLogEntry> logs) {
    final listHeight = (logs.length > 5 ? 5.5 : logs.length.toDouble()) * 75.0;

    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: _searchControllers[category],
                decoration: InputDecoration(
                  hintText: 'Search in $category...',
                  prefixIcon: const Icon(Icons.search, size: 20),
                  isDense: true,
                  border: const OutlineInputBorder(),
                ),
              ),
            ),
            const Divider(),
            logs.isEmpty
                ? const Padding(
                padding: EdgeInsets.all(16.0),
                child: Center(child: Text('No logs match your search in this category.')))
                : ConstrainedBox(
              constraints: BoxConstraints(maxHeight: listHeight),
              child: ListView.builder(
                shrinkWrap: true,
                itemCount: logs.length,
                itemBuilder: (context, index) {
                  return _buildLogListItem(logs[index]);
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildLogListItem(SubmissionLogEntry log) {
    final isFailed = log.status != 'L3';
    final logKey = log.reportId ?? log.submissionDateTime.toIso8601String();
    final isResubmitting = _isResubmitting[logKey] ?? false;
    final title = '${log.title} (${log.stationCode})';
    final subtitle = DateFormat('yyyy-MM-dd HH:mm').format(log.submissionDateTime);

    return ExpansionTile(
      leading: Icon(
        isFailed ? Icons.error_outline : Icons.check_circle_outline,
        color: isFailed ? Colors.red : Colors.green,
      ),
      title: Text(title, style: const TextStyle(fontWeight: FontWeight.w500)),
      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('Report ID:', log.reportId ?? 'N/A'),
              _buildDetailRow('Status:', log.message),
              _buildDetailRow('Submission Type:', log.type),
            ],
          ),
        )
      ],
    );
  }

  Widget _buildDetailRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 2.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('$label ', style: const TextStyle(fontWeight: FontWeight.bold)),
          Expanded(child: Text(value)),
        ],
      ),
    );
  }
}