import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:cashumit/models/submission_task.dart';
import 'package:cashumit/models/group_submission_result.dart';
import 'package:cashumit/services/receipt_service.dart';
import 'package:cashumit/utils/currency_format.dart';

/// Popup card yang menampilkan daftar transaksi yang sedang dikirim ke
/// Firefly III (satu baris per task: grup deposit atau tip).
///
/// Menerima [tasks] (sudah berisi konteks lengkap per-grup: group, destination,
/// date, tip) plus [baseUrl] & [accessToken].
/// Pengiriman dilakukan satu per satu (sequential). Jika ada yang gagal,
/// user dapat me-retry per-item atau "Retry Semua yang Gagal".
/// Tombol "Selesai" menutup dialog dan mengembalikan list hasil.
class TransactionSubmissionDialog extends StatefulWidget {
  final List<SubmissionTask> tasks;
  final String baseUrl;
  final String accessToken;

  const TransactionSubmissionDialog({
    super.key,
    required this.tasks,
    required this.baseUrl,
    required this.accessToken,
  });

  @override
  State<TransactionSubmissionDialog> createState() =>
      _TransactionSubmissionDialogState();
}

class _TransactionSubmissionDialogState
    extends State<TransactionSubmissionDialog> {
  late List<GroupSubmissionResult> _results;
  bool _isSubmitting = false;

  @override
  void initState() {
    super.initState();
    _results = _buildInitialResults();
    // Mulai kirim semua otomatis
    WidgetsBinding.instance.addPostFrameCallback((_) => _submitAll());
  }

  List<GroupSubmissionResult> _buildInitialResults() {
    return widget.tasks.map((t) {
      return GroupSubmissionResult(
        groupId: t.taskId,
        label: t.label,
        amount: t.amount,
        isTip: t.isTip,
        status: SubmissionStatus.pending,
      );
    }).toList();
  }

  /// Kirim satu task, return hasilnya.
  Future<GroupSubmissionResult> _submitTask(SubmissionTask task) async {
    if (task.isTip) {
      return ReceiptService.submitTip(
        tipSourceAccountId: task.tipSourceAccountId!,
        tipSourceAccountName: task.tipSourceAccountName ?? '',
        tipAmount: task.tipAmount!,
        destinationAccountId: task.destinationAccountId,
        transactionDate: task.transactionDate,
        baseUrl: widget.baseUrl,
        accessToken: widget.accessToken,
      );
    }
    return ReceiptService.submitSingleGroup(
      group: task.group!,
      destinationAccountId: task.destinationAccountId,
      transactionDate: task.transactionDate,
      baseUrl: widget.baseUrl,
      accessToken: widget.accessToken,
    );
  }

  /// Kirim semua entry yang masih pending/gagal, sequential.
  Future<void> _submitAll() async {
    if (_isSubmitting) return;
    setState(() => _isSubmitting = true);

    for (int i = 0; i < _results.length; i++) {
      if (_results[i].status != SubmissionStatus.pending &&
          _results[i].status != SubmissionStatus.failed) {
        continue;
      }

      // Set sending
      setState(() {
        _results[i] = _results[i].copyWith(
          status: SubmissionStatus.sending,
          error: null,
        );
      });

      final task = widget.tasks[i];
      final res = await _submitTask(task);

      if (!mounted) return;
      setState(() {
        _results[i] = GroupSubmissionResult(
          groupId: _results[i].groupId,
          label: _results[i].label,
          amount: _results[i].amount,
          isTip: _results[i].isTip,
          status: res.status,
          transactionId: res.transactionId,
          error: res.error,
        );
      });
    }

    setState(() => _isSubmitting = false);
  }

  /// Retry satu entry.
  Future<void> _retryOne(int index) async {
    if (_isSubmitting) return;
    setState(() => _isSubmitting = true);

    setState(() {
      _results[index] = _results[index].copyWith(
        status: SubmissionStatus.sending,
        error: null,
      );
    });

    final task = widget.tasks[index];
    final res = await _submitTask(task);

    if (!mounted) return;
    setState(() {
      _results[index] = GroupSubmissionResult(
        groupId: _results[index].groupId,
        label: _results[index].label,
        amount: _results[index].amount,
        isTip: _results[index].isTip,
        status: res.status,
        transactionId: res.transactionId,
        error: res.error,
      );
      _isSubmitting = false;
    });
  }

  /// Retry semua yang gagal.
  Future<void> _retryAllFailed() async {
    setState(() {
      for (int i = 0; i < _results.length; i++) {
        if (_results[i].isFailed) {
          _results[i] = _results[i].copyWith(status: SubmissionStatus.pending);
        }
      }
    });
    await _submitAll();
  }

  int get _failedCount => _results.where((r) => r.isFailed).length;
  int get _successCount => _results.where((r) => r.isSuccess).length;
  bool get _allDone =>
      _results.every((r) => r.isSuccess || r.isFailed);

  @override
  Widget build(BuildContext context) {
    return Dialog(
      insetPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 420, maxHeight: 560),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Header
              Row(
                children: [
                  Icon(Icons.cloud_upload,
                      color: Theme.of(context).colorScheme.primary),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      _isSubmitting
                          ? 'Mengirim transaksi...'
                          : _allDone
                              ? 'Pengiriman selesai ($_successCount/${_successCount + _failedCount})'
                              : 'Pengiriman transaksi',
                      style: const TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                  if (_isSubmitting)
                    const SizedBox(
                      width: 18,
                      height: 18,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    ),
                ],
              ),
              const Divider(height: 16),

              // Daftar transaksi
              Flexible(
                child: ListView.separated(
                  shrinkWrap: true,
                  itemCount: _results.length,
                  separatorBuilder: (_, __) => const Divider(height: 1),
                  itemBuilder: (context, index) {
                    final r = _results[index];
                    return _SubmissionTile(
                      result: r,
                      baseUrl: widget.baseUrl,
                      onRetry: r.isFailed && !_isSubmitting
                          ? () => _retryOne(index)
                          : null,
                    );
                  },
                ),
              ),

              const SizedBox(height: 12),

              // Aksi bawah
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  if (_allDone && _failedCount > 0 && !_isSubmitting)
                    TextButton.icon(
                      onPressed: _retryAllFailed,
                      icon: const Icon(Icons.refresh, size: 18),
                      label: const Text('Retry Semua Gagal'),
                    ),
                  const SizedBox(width: 8),
                  ElevatedButton(
                    onPressed: _isSubmitting
                        ? null
                        : () => Navigator.of(context).pop(_results),
                    style: ElevatedButton.styleFrom(
                      backgroundColor: Theme.of(context).colorScheme.primary,
                      foregroundColor: Colors.white,
                    ),
                    child: const Text('Selesai'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

/// Satu baris transaksi dalam popup.
class _SubmissionTile extends StatelessWidget {
  final GroupSubmissionResult result;
  final String baseUrl;
  final VoidCallback? onRetry;

  const _SubmissionTile({
    required this.result,
    required this.baseUrl,
    this.onRetry,
  });

  String get _url => '$baseUrl/transactions/show/${result.transactionId}';

  Future<void> _copyLink(BuildContext context) async {
    await Clipboard.setData(ClipboardData(text: _url));
    if (!context.mounted) return;
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('Link disalin'),
        duration: Duration(seconds: 1),
      ),
    );
  }

  Future<void> _openLink(BuildContext context) async {
    try {
      final uri = Uri.parse(_url);
      final launched =
          await launchUrl(uri, mode: LaunchMode.externalApplication);
      if (!launched) {
        throw 'Tidak dapat membuka URL';
      }
    } catch (e) {
      if (!context.mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Gagal membuka link: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return ListTile(
      dense: true,
      contentPadding:
          const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      leading: _buildLeading(),
      title: Text(
        result.label,
        style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600),
        maxLines: 1,
        overflow: TextOverflow.ellipsis,
      ),
      subtitle: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            CurrencyFormat.formatRupiah(result.amount),
            style: TextStyle(
              fontSize: 12,
              color: Colors.grey[700],
            ),
          ),
          if (result.isFailed && result.error != null)
            Text(
              result.error!.replaceFirst('Exception: ', ''),
              style: const TextStyle(fontSize: 11, color: Colors.red),
              maxLines: 2,
              overflow: TextOverflow.ellipsis,
            ),
          if (result.isSuccess && result.transactionId != null)
            Text(
              _url,
              style: TextStyle(
                fontSize: 10,
                color: Colors.grey[500],
              ),
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
            ),
        ],
      ),
      trailing: _buildTrailing(context),
    );
  }

  Widget _buildLeading() {
    if (result.isSending) {
      return const SizedBox(
        width: 20,
        height: 20,
        child: CircularProgressIndicator(strokeWidth: 2),
      );
    }
    if (result.isSuccess) {
      return const Icon(Icons.check_circle, color: Colors.green, size: 22);
    }
    if (result.isFailed) {
      return const Icon(Icons.cancel, color: Colors.red, size: 22);
    }
    return Icon(Icons.hourglass_empty, color: Colors.grey[400], size: 22);
  }

  Widget? _buildTrailing(BuildContext context) {
    // Baris sukses dengan ID: tombol copy + open link
    if (result.isSuccess && result.transactionId != null) {
      return Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          IconButton(
            icon: const Icon(Icons.copy, size: 18),
            padding: EdgeInsets.zero,
            constraints: const BoxConstraints(),
            tooltip: 'Salin link',
            onPressed: () => _copyLink(context),
          ),
          const SizedBox(width: 4),
          IconButton(
            icon: const Icon(Icons.open_in_new, size: 18),
            padding: EdgeInsets.zero,
            constraints: const BoxConstraints(),
            tooltip: 'Buka di browser',
            color: Theme.of(context).colorScheme.primary,
            onPressed: () => _openLink(context),
          ),
        ],
      );
    }
    // Baris gagal: tombol retry
    if (result.isFailed && onRetry != null) {
      return TextButton(
        onPressed: onRetry,
        style: TextButton.styleFrom(
          padding: const EdgeInsets.symmetric(horizontal: 8),
          minimumSize: const Size(0, 30),
          tapTargetSize: MaterialTapTargetSize.shrinkWrap,
        ),
        child: const Text('Retry', style: TextStyle(fontSize: 12)),
      );
    }
    return null;
  }
}
