import 'dart:convert';

import 'package:flutter/material.dart';
import 'base_field.dart';
import '../ui/entity_form.dart';

/// One-to-many subform builder
/// - Renders repeatable group of sub-fields
/// - Stores JSON array (as string) in controller
class OneToManyField extends BaseField {
  final String fieldKey;
  final String label;
  final String hint;
  final bool isRequired;
  final List<BaseField> subFields;

  OneToManyField({
    required this.fieldKey,
    required this.label,
    this.hint = '',
    this.isRequired = false,
    required this.subFields,
  });

  @override
  String? Function(String?)? get validator => (value) {
        if (isRequired && (value == null || value.isEmpty)) {
          return '$label is required';
        }
        return null;
      };
  @override
  Map<String, dynamic>? get customProperties => const {
        // Keep submission optional/safe until backend expects JSON
        'excludeFromSubmit': true,
      };
  @override
  Widget buildField({
    required TextEditingController controller,
    required ColorScheme colorScheme,
    VoidCallback? onChanged,
  }) {
    return _OneToManyWidget(
      label: label,
      controller: controller,
      colorScheme: colorScheme,
      subFields: subFields,
      validate: validator,
      onChanged: onChanged,
    );
  }
}

class _OneToManyWidget extends StatefulWidget {
  final String label;
  final TextEditingController controller;
  final ColorScheme colorScheme;
  final List<BaseField> subFields;
  final String? Function(String?)? validate;
  final VoidCallback? onChanged;

  const _OneToManyWidget({
    required this.label,
    required this.controller,
    required this.colorScheme,
    required this.subFields,
    required this.validate,
    required this.onChanged,
  });

  @override
  State<_OneToManyWidget> createState() => _OneToManyWidgetState();
}

class _OneToManyWidgetState extends State<_OneToManyWidget> {
  final List<Map<String, TextEditingController>> _rows = [];

  @override
  void initState() {
    super.initState();
    if (widget.controller.text.isNotEmpty) {
      // Attempt to parse initial JSON array
      try {
        final decoded = const JsonDecoder().convert(widget.controller.text);
        if (decoded is List) {
          for (final item in decoded) {
            _addRow(
                prefill: (item as Map).map(
                    (k, v) => MapEntry(k.toString(), v?.toString() ?? '')));
          }
        }
      } catch (_) {}
    }
    if (_rows.isEmpty) _addRow();
  }

  void _addRow({Map<String, String>? prefill}) {
    final row = <String, TextEditingController>{};
    for (final f in widget.subFields) {
      row[f.fieldKey] = TextEditingController(text: prefill?[f.fieldKey] ?? '');
    }
    setState(() => _rows.add(row));
    _syncToParent();
  }

  void _removeRow(int index) {
    if (index < 0 || index >= _rows.length) return;
    final removed = _rows.removeAt(index);
    for (final c in removed.values) {
      c.dispose();
    }
    setState(() {});
    _syncToParent();
  }

  void _syncToParent() {
    final list = <Map<String, String>>[];
    for (final row in _rows) {
      final map = <String, String>{};
      row.forEach((k, c) => map[k] = c.text.trim());
      list.add(map);
    }
    widget.controller.text = const JsonEncoder().convert(list);
    widget.onChanged?.call();
    EntityFormScope.of(context)?.notifyParent();
  }

  @override
  Widget build(BuildContext context) {
    final cs = widget.colorScheme;
    return Container(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: cs.primary.withOpacity(0.15)),
      ),
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Text(widget.label,
                    style: TextStyle(
                        color: cs.onSurface, fontWeight: FontWeight.w700)),
                const Spacer(),
                IconButton(
                  icon: Icon(Icons.add_circle, color: cs.primary),
                  tooltip: 'Add',
                  onPressed: () => _addRow(),
                ),
              ],
            ),
            const SizedBox(height: 8),
            ..._rows.asMap().entries.map((entry) {
              final index = entry.key;
              final ctrls = entry.value;
              return Card(
                elevation: 0,
                color: cs.surface,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                  side: BorderSide(color: cs.outline.withOpacity(0.12)),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(12),
                  child: Column(
                    children: [
                      ...widget.subFields.map((f) => Padding(
                            padding: const EdgeInsets.only(bottom: 12),
                            child: f.buildField(
                              controller: ctrls[f.fieldKey]!,
                              colorScheme: cs,
                              onChanged: _syncToParent,
                            ),
                          )),
                      Align(
                        alignment: Alignment.centerRight,
                        child: IconButton(
                          icon: Icon(Icons.delete_outline, color: cs.error),
                          tooltip: 'Remove',
                          onPressed: () => _removeRow(index),
                        ),
                      ),
                    ],
                  ),
                ),
              );
            }),
            if (widget.validate != null)
              Builder(
                builder: (context) {
                  final error = widget.validate!(widget.controller.text);
                  return error != null
                      ? Padding(
                          padding: const EdgeInsets.only(top: 6),
                          child: Text(error,
                              style: TextStyle(color: cs.error, fontSize: 12)),
                        )
                      : const SizedBox.shrink();
                },
              )
          ],
        ),
      ),
    );
  }
}
