import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'package:hl_lieferservice/domain/entity/delivery.dart';
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
import 'package:hl_lieferservice/domain/entity/service.dart';
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart';
import 'package:hl_lieferservice/feature/car_selection/bloc/state.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';

/// Step 4 — Services (früher „Lieferoptionen").
///
/// Rendert die aktiven Service-Definitionen (`TourDetails.services`,
/// admin-konfigurierbar) und lässt den Fahrer sie pro Lieferung auswählen:
/// `boolean` → Checkbox, `numeric` → Zahlenfeld mit min/max. Werte landen
/// über den `TourBloc` (`SetDeliveryServiceValue`/`RemoveDeliveryServiceValue`)
/// im Backend. Setzen nur bei aktiver Lieferung.
class StepServices extends StatelessWidget {
  const StepServices({super.key, required this.delivery, required this.details});

  final Delivery delivery;
  final TourDetails details;

  String _actorCarId(BuildContext context) {
    final state = context.read<CarSelectBloc>().state;
    if (state is CarSelectComplete) return state.selectedCar.id;
    return '00000000-0000-0000-0000-000000000000';
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final active = delivery.state == DeliveryState.active;

    return BlocBuilder<TourBloc, TourState>(
      buildWhen: (a, b) {
        if (a is! TourLoaded || b is! TourLoaded) return true;
        return a.details.services != b.details.services ||
            a.details.serviceValuesByDeliveryId[delivery.id] !=
                b.details.serviceValuesByDeliveryId[delivery.id];
      },
      builder: (context, state) {
        final d = state is TourLoaded ? state.details : details;
        final services = d.services;

        if (services.isEmpty) {
          return Center(
            child: Padding(
              padding: const EdgeInsets.all(24),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(Icons.construction_outlined,
                      size: 56, color: theme.colorScheme.onSurfaceVariant),
                  const SizedBox(height: 12),
                  Text('Keine Checkliste konfiguriert',
                      style: theme.textTheme.titleMedium),
                  const SizedBox(height: 4),
                  Text(
                    'Ein Administrator kann eine Checkliste anlegen.',
                    style: theme.textTheme.bodySmall?.copyWith(
                      color: theme.colorScheme.onSurfaceVariant,
                    ),
                  ),
                ],
              ),
            ),
          );
        }

        // Wie im alten `delivery_options.dart`: zwei Kategorien —
        // „Auswählbare Optionen" (Checkboxen) und „Zahlenwerte".
        final bools =
            services.where((s) => s.kind == ServiceKind.boolean).toList();
        final numerics =
            services.where((s) => s.kind == ServiceKind.numeric).toList();

        _ServiceTile tileFor(Service service) => _ServiceTile(
              service: service,
              value: d.serviceValueOf(delivery.id, service.id),
              enabled: active,
              onSetBool: (v) => context.read<TourBloc>().add(
                    SetDeliveryServiceValue(
                      deliveryId: delivery.id,
                      serviceId: service.id,
                      boolValue: v,
                      actorCarId: _actorCarId(context),
                    ),
                  ),
              onSetNumeric: (n) => context.read<TourBloc>().add(
                    SetDeliveryServiceValue(
                      deliveryId: delivery.id,
                      serviceId: service.id,
                      numericValue: n,
                      actorCarId: _actorCarId(context),
                    ),
                  ),
              onClear: () => context.read<TourBloc>().add(
                    RemoveDeliveryServiceValue(
                      deliveryId: delivery.id,
                      serviceId: service.id,
                    ),
                  ),
            );

        Widget sectionCard(List<Service> items) => Card(
              margin: EdgeInsets.zero,
              child: Column(
                children: [
                  for (int i = 0; i < items.length; i++) ...[
                    tileFor(items[i]),
                    if (i < items.length - 1)
                      const Divider(height: 1, indent: 16, endIndent: 16),
                  ],
                ],
              ),
            );

        return ListView(
          padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
          children: [
            if (!active)
              Padding(
                padding: const EdgeInsets.only(bottom: 12),
                child: Row(
                  children: [
                    Icon(Icons.lock_outline,
                        size: 16, color: theme.colorScheme.onSurfaceVariant),
                    const SizedBox(width: 6),
                    Text(
                      'Nur bei aktiver Lieferung änderbar.',
                      style: TextStyle(
                        fontSize: 12,
                        color: theme.colorScheme.onSurfaceVariant,
                      ),
                    ),
                  ],
                ),
              ),
            if (bools.isNotEmpty) ...[
              const _CategoryHeader(
                icon: Icons.check_box_outlined,
                text: 'Auswählbare Optionen',
              ),
              const SizedBox(height: 8),
              sectionCard(bools),
            ],
            if (bools.isNotEmpty && numerics.isNotEmpty)
              const SizedBox(height: 24),
            if (numerics.isNotEmpty) ...[
              const _CategoryHeader(
                icon: Icons.pin_outlined,
                text: 'Zahlenwerte',
              ),
              const SizedBox(height: 8),
              sectionCard(numerics),
            ],
          ],
        );
      },
    );
  }
}

/// Kategorie-Überschrift (Icon + Titel) — trennt Checkboxen von Zahlenwerten.
class _CategoryHeader extends StatelessWidget {
  const _CategoryHeader({required this.icon, required this.text});
  final IconData icon;
  final String text;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Row(
      children: [
        Icon(icon, size: 18, color: theme.colorScheme.primary),
        const SizedBox(width: 8),
        Text(
          text,
          style: theme.textTheme.titleMedium?.copyWith(
            fontWeight: FontWeight.w700,
          ),
        ),
      ],
    );
  }
}

/// Eine Service-Zeile — Checkbox (boolean) oder Zahlenfeld (numeric).
class _ServiceTile extends StatelessWidget {
  const _ServiceTile({
    required this.service,
    required this.value,
    required this.enabled,
    required this.onSetBool,
    required this.onSetNumeric,
    required this.onClear,
  });

  final Service service;
  final DeliveryServiceValue? value;
  final bool enabled;
  final ValueChanged<bool> onSetBool;
  final ValueChanged<int> onSetNumeric;
  final VoidCallback onClear;

  @override
  Widget build(BuildContext context) {
    switch (service.kind) {
      case ServiceKind.boolean:
        return CheckboxListTile(
          value: value?.boolValue ?? false,
          onChanged: enabled ? (v) => onSetBool(v ?? false) : null,
          title: Text(service.name),
          controlAffinity: ListTileControlAffinity.leading,
          dense: true,
        );
      case ServiceKind.numeric:
        return _NumericServiceField(
          key: ValueKey(service.id),
          service: service,
          initial: value?.numericValue,
          enabled: enabled,
          onSetNumeric: onSetNumeric,
          onClear: onClear,
        );
    }
  }
}

/// Zahlenfeld eines numerischen Service — eigener Controller, persistiert beim
/// Verlassen/Submit, klemmt auf [min,max]. Leeres Feld → Wert entfernen.
class _NumericServiceField extends StatefulWidget {
  const _NumericServiceField({
    super.key,
    required this.service,
    required this.initial,
    required this.enabled,
    required this.onSetNumeric,
    required this.onClear,
  });

  final Service service;
  final int? initial;
  final bool enabled;
  final ValueChanged<int> onSetNumeric;
  final VoidCallback onClear;

  @override
  State<_NumericServiceField> createState() => _NumericServiceFieldState();
}

class _NumericServiceFieldState extends State<_NumericServiceField> {
  late final TextEditingController _controller =
      TextEditingController(text: widget.initial?.toString() ?? '');

  @override
  void didUpdateWidget(_NumericServiceField old) {
    super.didUpdateWidget(old);
    // Server-Stand übernehmen, wenn er sich geändert hat (z. B. nach
    // Reconcile) und sich vom angezeigten Text unterscheidet.
    final incoming = widget.initial?.toString() ?? '';
    if (old.initial != widget.initial && _controller.text != incoming) {
      _controller.text = incoming;
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _commit() {
    final raw = _controller.text.trim();
    if (raw.isEmpty) {
      widget.onClear();
      return;
    }
    final parsed = int.tryParse(raw);
    if (parsed == null) {
      _controller.text = widget.initial?.toString() ?? '';
      return;
    }
    var n = parsed;
    final min = widget.service.minValue;
    final max = widget.service.maxValue;
    if (min != null && n < min) n = min;
    if (max != null && n > max) n = max;
    if (n.toString() != _controller.text) {
      _controller.text = n.toString();
    }
    widget.onSetNumeric(n);
  }

  @override
  Widget build(BuildContext context) {
    final s = widget.service;
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
      child: TextField(
        controller: _controller,
        enabled: widget.enabled,
        keyboardType: TextInputType.number,
        inputFormatters: [FilteringTextInputFormatter.digitsOnly],
        textInputAction: TextInputAction.done,
        decoration: InputDecoration(
          labelText: s.name,
          border: const OutlineInputBorder(),
          isDense: true,
        ),
        onTapOutside: (_) {
          FocusScope.of(context).unfocus();
          _commit();
        },
        onSubmitted: (_) => _commit(),
      ),
    );
  }
}
