import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:nhance_partner/data/utils/toastNotification.dart';

import '../../../core/services/api_service.dart';
import '../../layouts/main_layout.dart';

class PayoutUploadScreen extends ConsumerStatefulWidget {
  const PayoutUploadScreen({super.key});

  @override
  ConsumerState<PayoutUploadScreen> createState() => _PayoutUploadScreenState();
}

class _PayoutUploadScreenState extends ConsumerState<PayoutUploadScreen> {
  late ApiService apiService;
  bool isLoading = false;
  String? uploadedFileName;
  List<Map<String, dynamic>> failedRows = [];
  /// Present when upload succeeded but `data.errors` was non-empty (partial success).
  Map<String, dynamic>? partialSuccessData;

  @override
  void initState() {
    super.initState();
    apiService = ApiService();
  }

  void _resetAll() {
    setState(() {
      uploadedFileName = null;
      failedRows = [];
      partialSuccessData = null;
    });
  }

  /// Parses `data.errors` (success-with-errors) or top-level error arrays.
  List<Map<String, dynamic>> _extractFailedRows(Map<String, dynamic> response) {
    final dynamic data = response['data'];
    if (data is Map) {
      final err = data['errors'];
      if (err is List) {
        return err.map((e) {
          if (e is Map<String, dynamic>) return Map<String, dynamic>.from(e);
          if (e is Map) return Map<String, dynamic>.from(e);
          return <String, dynamic>{'message': e.toString()};
        }).toList();
      }
    }
    final top = response['errors'] ?? response['failed_rows'];
    if (top is List) {
      return top.map((e) {
        if (e is Map<String, dynamic>) return Map<String, dynamic>.from(e);
        if (e is Map) return Map<String, dynamic>.from(e);
        return <String, dynamic>{'message': e.toString()};
      }).toList();
    }
    return [];
  }

  String _failureMessage(Map<String, dynamic> response) {
    final m = response['message']?.toString().trim();
    if (m != null && m.isNotEmpty) return m;
    final data = response['data'];
    if (data is String && data.trim().isNotEmpty) return data.trim();
    return 'Upload failed';
  }

  String _successSummary(Map<String, dynamic> data) {
    final updated = data['updated_rows'];
    final skipped = data['skipped_empty_payout'];
    final parts = <String>[];
    if (updated != null) parts.add('Updated $updated row(s)');
    if (skipped != null) parts.add('Skipped empty payout: $skipped');
    return parts.isEmpty ? 'Upload successful' : parts.join(' · ');
  }

  String _partialSummary(Map<String, dynamic> data) {
    final base = _successSummary(data);
    final ec = data['error_count'];
    if (ec != null) return '$base · $ec row(s) with errors';
    return base;
  }

  static const _errorIcon = Icon(Icons.error_outline, color: Colors.red, size: 16);

  Widget _messageWithLeadingIcon(String text) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.only(top: 2),
          child: _errorIcon,
        ),
        const SizedBox(width: 8),
        Expanded(
          child: Text(
            text,
            style: GoogleFonts.inter(fontSize: 12, height: 1.35),
          ),
        ),
      ],
    );
  }

  void _handleUploadResponse(Map<String, dynamic> response) {
    final status = response['status']?.toString();
    final code = response['code'];

    if (status == 'error' &&
        (response['message']?.toString().toLowerCase().contains('session') ?? false)) {
      ToastHelper.showErrorToast(context, response['message']?.toString() ?? 'Session expired');
      return;
    }

    final isHttpSuccess =
        status == 'success' ||
        status == '200' ||
        code == 200 ||
        code == '200';

    if (isHttpSuccess) {
      final data = response['data'];
      if (data is Map) {
        final map = Map<String, dynamic>.from(data);
        final errors = map['errors'];
        if (errors is List && errors.isNotEmpty) {
          setState(() {
            partialSuccessData = map;
            failedRows = errors.map((e) {
              if (e is Map<String, dynamic>) return Map<String, dynamic>.from(e);
              if (e is Map) return Map<String, dynamic>.from(e);
              return <String, dynamic>{'message': e.toString()};
            }).toList();
          });
          ToastHelper.showWarningToast(context, _partialSummary(map));
          return;
        }
        ToastHelper.showSuccessToast(context, _successSummary(map));
        _resetAll();
        return;
      }
      ToastHelper.showSuccessToast(
        context,
        response['message']?.toString() ?? 'Upload successful',
      );
      _resetAll();
      return;
    }

    if (status == 'failed' || status == 'error' || !isHttpSuccess) {
      final rows = _extractFailedRows(response);
      ToastHelper.showErrorToast(context, _failureMessage(response));
      if (rows.isNotEmpty) {
        setState(() {
          failedRows = rows;
          partialSuccessData = null;
        });
      }
      return;
    }

    ToastHelper.showErrorToast(context, 'Unexpected response');
  }

  Future<void> _uploadFile() async {
    final picked = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['xlsx', 'xls'],
      withData: true,
    );
    if (picked == null || picked.files.isEmpty) return;

    final file = picked.files.single;
    if (file.bytes == null || file.bytes!.isEmpty) {
      ToastHelper.showWarningToast(context, 'Unable to read selected file');
      return;
    }

    setState(() {
      isLoading = true;
      uploadedFileName = file.name;
    });
    try {
      final response = await apiService.uploadPolicyCommissionExcel(
        file: file,
      );
      _handleUploadResponse(response);
    } catch (e) {
      ToastHelper.showErrorToast(context, e.toString());
    } finally {
      if (mounted) setState(() => isLoading = false);
    }
  }

  bool get _isStandardErrorShape {
    if (failedRows.isEmpty) return false;
    for (final r in failedRows) {
      if (!r.containsKey('row') && !r.containsKey('policy_number')) return false;
    }
    return true;
  }

  List<String> _visibleColumns() {
    if (failedRows.isEmpty) return [];
    const preferred = ['row', 'policy_number', 'agent_code', 'expected_agent_code', 'message'];
    const hidden = <String>{};
    final keySet = <String>{};
    for (final row in failedRows) {
      keySet.addAll(row.keys);
    }
    final ordered = <String>[];
    for (final p in preferred) {
      if (keySet.contains(p) && !hidden.contains(p)) ordered.add(p);
    }
    for (final k in keySet) {
      if (!ordered.contains(k) && !hidden.contains(k)) ordered.add(k);
    }
    return ordered;
  }

  Widget _buildPartialSummaryBanner() {
    final d = partialSuccessData;
    if (d == null) return const SizedBox.shrink();
    final updated = d['updated_rows'];
    final skipped = d['skipped_empty_payout'];
    final errCount = d['error_count'];
    return Padding(
      padding: const EdgeInsets.only(bottom: 10),
      child: Wrap(
        spacing: 8,
        runSpacing: 6,
        crossAxisAlignment: WrapCrossAlignment.center,
        children: [
          if (updated != null)
            _summaryChip('Updated rows', updated.toString(), const Color(0xFF059669)),
          if (skipped != null)
            _summaryChip('Skipped empty payout', skipped.toString(), const Color(0xFF64748B)),
          if (errCount != null)
            _summaryChip('Errors', errCount.toString(), const Color(0xFFDC2626)),
        ],
      ),
    );
  }

  Widget _summaryChip(String label, String value, Color color) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
      decoration: BoxDecoration(
        color: color.withOpacity(0.1),
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: color.withOpacity(0.35)),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            '$label: ',
            style: GoogleFonts.inter(fontSize: 11, color: const Color(0xFF475569)),
          ),
          Text(
            value,
            style: GoogleFonts.inter(fontSize: 12, fontWeight: FontWeight.w700, color: color),
          ),
        ],
      ),
    );
  }

  Widget _buildErrorsTable() {
    if (_isStandardErrorShape) {
      return Column(
        children: [
          _buildTableHeaderRow(isStandard: true),
          Expanded(
            child: ListView.builder(
              itemCount: failedRows.length,
              itemBuilder: (context, index) {
                final row = failedRows[index];
                return Container(
                  decoration: const BoxDecoration(
                    border: Border(
                      bottom: BorderSide(color: Color(0xFFE5E7EB)),
                    ),
                  ),
                  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      SizedBox(
                        width: 52,
                        child: Text(
                          '${row['row'] ?? '-'}',
                          style: GoogleFonts.inter(fontSize: 12, fontWeight: FontWeight.w600),
                        ),
                      ),
                      SizedBox(
                        width: 160,
                        child: Text(
                          (row['policy_number'] ?? '-').toString(),
                          style: GoogleFonts.inter(fontSize: 12),
                        ),
                      ),
                      SizedBox(
                        width: 100,
                        child: Text(
                          (row['agent_code'] ?? '-').toString().isEmpty
                              ? '—'
                              : (row['agent_code'] ?? '').toString(),
                          style: GoogleFonts.inter(fontSize: 12),
                        ),
                      ),
                      SizedBox(
                        width: 120,
                        child: Text(
                          row['expected_agent_code'] != null &&
                                  row['expected_agent_code'].toString().trim().isNotEmpty
                              ? row['expected_agent_code'].toString()
                              : '—',
                          style: GoogleFonts.inter(fontSize: 12, color: const Color(0xFF64748B)),
                        ),
                      ),
                      Expanded(
                        child: _messageWithLeadingIcon((row['message'] ?? '-').toString()),
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ],
      );
    }

    final columns = _visibleColumns();
    return Column(
      children: [
        _buildTableHeaderRow(isStandard: false, columns: columns),
        Expanded(
          child: ListView.builder(
            itemCount: failedRows.length,
            itemBuilder: (context, index) {
              final row = failedRows[index];
              return Container(
                decoration: const BoxDecoration(
                  border: Border(
                    bottom: BorderSide(color: Color(0xFFE5E7EB)),
                  ),
                ),
                padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    for (final c in columns)
                      if (c == 'message')
                        Expanded(
                          child: _messageWithLeadingIcon((row[c] ?? '-').toString()),
                        )
                      else
                        SizedBox(
                          width: 140,
                          child: Text(
                            (row[c] ?? '-').toString(),
                            maxLines: 3,
                            overflow: TextOverflow.ellipsis,
                            style: GoogleFonts.inter(fontSize: 11),
                          ),
                        ),
                  ],
                ),
              );
            },
          ),
        ),
      ],
    );
  }

  Widget _buildTableHeaderRow({required bool isStandard, List<String>? columns}) {
    TextStyle h() => GoogleFonts.inter(
          fontSize: 11,
          fontWeight: FontWeight.w700,
          color: const Color(0xFF334155),
          letterSpacing: 0.3,
        );
    if (isStandard) {
      return Container(
        width: double.infinity,
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
        decoration: const BoxDecoration(
          color: Color(0xFFF1F5F9),
          border: Border(bottom: BorderSide(color: Color(0xFFE2E8F0))),
        ),
        child: Row(
          children: [
            SizedBox(width: 52, child: Text('ROW', style: h())),
            SizedBox(width: 160, child: Text('POLICY NUMBER', style: h())),
            SizedBox(width: 100, child: Text('AGENT CODE', style: h())),
            SizedBox(width: 120, child: Text('EXPECTED', style: h())),
            Expanded(child: Text('MESSAGE', style: h())),
          ],
        ),
      );
    }
    final cols = columns ?? [];
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
      decoration: const BoxDecoration(
        color: Color(0xFFF1F5F9),
        border: Border(bottom: BorderSide(color: Color(0xFFE2E8F0))),
      ),
      child: Row(
        children: [
          for (final c in cols)
            if (c == 'message')
              Expanded(
                child: Text(
                  c.toUpperCase().replaceAll('_', ' '),
                  style: h(),
                ),
              )
            else
              SizedBox(
                width: 140,
                child: Text(
                  c.toUpperCase().replaceAll('_', ' '),
                  style: h(),
                ),
              ),
        ],
      ),
    );
  }

  Future<void> _onTemplateFileTap() async {
    try {
      await apiService.downloadCommissionUploadSampleExcel();
    } catch (e) {
      if (mounted) {
        ToastHelper.showErrorToast(
          context,
          'Could not download template. Try again.',
        );
      }
    }
  }

  Widget _buildTemplateDownloadHint() {
    return Padding(
      padding: const EdgeInsets.only(top: 4),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text(
            'Please download the sample file to review the format.',
            textAlign: TextAlign.center,
            style: GoogleFonts.inter(
              fontSize: 12,
              height: 1.4,
              color: const Color(0xFF6B7280),
            ),
          ),
          const SizedBox(height: 8),
          MouseRegion(
            cursor: SystemMouseCursors.click,
            child: InkWell(
              onTap: () => _onTemplateFileTap(),
              borderRadius: BorderRadius.circular(4),
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                child: Text(
                  'Template File',
                  style: GoogleFonts.inter(
                    fontSize: 14,
                    fontWeight: FontWeight.w600,
                    color: const Color(0xFF2E7D6E),
                    decoration: TextDecoration.underline,
                    decorationColor: const Color(0xFF2E7D6E),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildUploadCard() {
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        InkWell(
          onTap: isLoading ? null : _uploadFile,
          borderRadius: BorderRadius.circular(10),
          child: Container(
            width: double.infinity,
            constraints: const BoxConstraints(maxWidth: 1050),
            padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 26),
            decoration: BoxDecoration(
              color: const Color(0xFFF8FAFA),
              borderRadius: BorderRadius.circular(10),
              border: Border.all(color: const Color(0xFF3AA69A), width: 1),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Container(
                  width: 30,
                  height: 30,
                  decoration: BoxDecoration(
                    color: const Color(0xFFE6F6F4),
                    borderRadius: BorderRadius.circular(8),
                    border: Border.all(color: const Color(0xFF7BCBC3)),
                  ),
                  child: isLoading
                      ? const Padding(
                          padding: EdgeInsets.all(6),
                          child: CircularProgressIndicator(
                            strokeWidth: 2,
                            valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF2E7D6E)),
                          ),
                        )
                      : const Icon(
                          Icons.upload_file_rounded,
                          size: 16,
                          color: Color(0xFF2E7D6E),
                        ),
                ),
                const SizedBox(height: 10),
                Text(
                  isLoading ? 'Uploading file...' : 'Upload Your Payout Documents',
                  style: GoogleFonts.inter(
                    fontSize: 18,
                    fontWeight: FontWeight.w600,
                    color: const Color(0xFF111827),
                  ),
                ),
                const SizedBox(height: 4),
                Text(
                  '(Supported Format: XLSX, XLS)',
                  style: GoogleFonts.inter(
                    fontSize: 12,
                    fontWeight: FontWeight.w400,
                    color: const Color(0xFF6B7280),
                  ),
                ),
                const SizedBox(height: 12),
                Text(
                  'Click here to choose an Excel file and upload.',
                  style: GoogleFonts.inter(
                    fontSize: 12,
                    color: const Color(0xFF4B5563),
                  ),
                ),
              ],
            ),
          ),
        ),
        const SizedBox(height: 16),
        ConstrainedBox(
          constraints: const BoxConstraints(maxWidth: 1050),
          child: SizedBox(
            width: double.infinity,
            child: _buildTemplateDownloadHint(),
          ),
        ),
      ],
    );
  }

  Widget _buildFailureGrid() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Expanded(
              child: Text(
                uploadedFileName == null
                    ? 'Validation errors'
                    : 'File: $uploadedFileName',
                style: GoogleFonts.inter(fontSize: 14, fontWeight: FontWeight.w600),
              ),
            ),
            OutlinedButton.icon(
              onPressed: isLoading ? null : _resetAll,
              icon: const Icon(Icons.refresh, size: 16),
              label: const Text('Re-upload'),
            ),
          ],
        ),
        _buildPartialSummaryBanner(),
        const SizedBox(height: 4),
        Text(
          'Error rows (${failedRows.length})',
          style: GoogleFonts.inter(fontSize: 12, color: const Color(0xFF64748B)),
        ),
        const SizedBox(height: 8),
        Expanded(
          child: Container(
            width: double.infinity,
            decoration: BoxDecoration(
              border: Border.all(color: const Color(0xFFE5E7EB)),
              borderRadius: BorderRadius.circular(8),
            ),
            clipBehavior: Clip.antiAlias,
            child: LayoutBuilder(
              builder: (context, constraints) {
                if (constraints.maxWidth < 720 && _isStandardErrorShape) {
                  return ListView.builder(
                    padding: const EdgeInsets.all(12),
                    itemCount: failedRows.length,
                    itemBuilder: (context, index) {
                      final row = failedRows[index];
                      return Container(
                        decoration: BoxDecoration(
                          color: const Color(0xFFF8FAFC),
                          borderRadius: BorderRadius.circular(8),
                          border: const Border(
                            bottom: BorderSide(color: Color(0xFFE5E7EB)),
                          ),
                        ),
                        child: Padding(
                          padding: const EdgeInsets.all(12),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                'Row ${row['row'] ?? '-'}',
                                style: GoogleFonts.inter(
                                  fontWeight: FontWeight.w700,
                                  fontSize: 12,
                                ),
                              ),
                              const SizedBox(height: 6),
                              _mobileLine('Policy', row['policy_number']),
                              _mobileLine('Agent code', row['agent_code']),
                              if (row['expected_agent_code'] != null &&
                                  row['expected_agent_code'].toString().trim().isNotEmpty)
                                _mobileLine('Expected', row['expected_agent_code']),
                              const SizedBox(height: 6),
                              _messageWithLeadingIcon((row['message'] ?? '').toString()),
                            ],
                          ),
                        ),
                      );
                    },
                  );
                }
                return _buildErrorsTable();
              },
            ),
          ),
        ),
      ],
    );
  }

  Widget _mobileLine(String label, dynamic value) {
    final v = value?.toString().trim() ?? '';
    return Padding(
      padding: const EdgeInsets.only(bottom: 4),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(
            width: 88,
            child: Text(
              '$label:',
              style: GoogleFonts.inter(fontSize: 11, color: const Color(0xFF64748B)),
            ),
          ),
          Expanded(
            child: Text(
              v.isEmpty ? '—' : v,
              style: GoogleFonts.inter(fontSize: 12),
            ),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MainLayout(
      title: 'Payout Upload',
      body: Container(
        width: double.infinity,
        color: Colors.white,
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Payout Upload',
              style: GoogleFonts.inter(
                fontSize: 13,
                fontWeight: FontWeight.w600,
                color: const Color(0xFF111827),
              ),
            ),
            const SizedBox(height: 10),
            Expanded(
              child: failedRows.isEmpty
                  ? Center(child: _buildUploadCard())
                  : _buildFailureGrid(),
            ),
          ],
        ),
      ),
    );
  }
}
