import "package:flutter/material.dart";

import "../i18n.dart";
import "../main.dart";
import "../models.dart";
import "../format.dart";
import "../theme.dart";

/// The fuel types a car can carry, in the order the API's models.go lists them.
/// Keys only: the labels live in enums.fuelType.*, which the car's Information
/// tab reads as well, so the two cannot disagree.
const List<String> kFuelTypes = [
  "petrol",
  "petrol_lpg",
  "diesel",
  "diesel_lpg",
  "hybrid",
  "electric",
  "hydrogen",
];

/// Bottom-sheet form to create or edit a car, mirroring the web CarFormModal.
/// Pops with the saved [Car] on success, or null if cancelled.
class CarFormSheet extends StatefulWidget {
  final Car? car; // null => create
  const CarFormSheet({super.key, this.car});

  @override
  State<CarFormSheet> createState() => _CarFormSheetState();
}

class _CarFormSheetState extends State<CarFormSheet> {
  late final Map<String, TextEditingController> _c;
  String _fuelType = "";
  // Held as the ISO string they arrived as, not as a DateTime. A build date may
  // be a year or a month rather than a day — the web app can enter one, this
  // sheet's date picker cannot — and parsing it into a DateTime would hand back
  // null, which on save would round somebody's "2015" down to nothing. Picking a
  // date replaces the value; the clear button empties it; anything else is
  // handed back exactly as it came.
  String _buildDate = "";
  String _firstRegistrationDate = "";
  bool _saving = false;
  String? _error;

  bool get _isEdit => widget.car != null;

  @override
  void initState() {
    super.initState();
    final car = widget.car;
    _fuelType = car?.fuelType ?? "";
    _buildDate = car?.buildDate ?? "";
    _firstRegistrationDate = car?.firstRegistrationDate ?? "";
    _c = {
      "name": TextEditingController(text: car?.name ?? ""),
      "make": TextEditingController(text: car?.make ?? ""),
      "model": TextEditingController(text: car?.model ?? ""),
      "year": TextEditingController(text: (car != null && car.year > 0) ? "${car.year}" : ""),
      "registration": TextEditingController(text: car?.registration ?? ""),
      "registrationCountry": TextEditingController(text: car?.registrationCountry ?? ""),
      "vin": TextEditingController(text: car?.vin ?? ""),
      "oilSpec": TextEditingController(text: car?.oilSpec ?? ""),
      "transmissionOilSpec": TextEditingController(text: car?.transmissionOilSpec ?? ""),
      "differentialOilSpec": TextEditingController(text: car?.differentialOilSpec ?? ""),
      "brakeFluidSpec": TextEditingController(text: car?.brakeFluidSpec ?? ""),
      "coolantSpec": TextEditingController(text: car?.coolantSpec ?? ""),
      // 0 is a reading, so it prints; only a car that does not exist yet is blank.
      "currentKm": TextEditingController(text: car == null ? "" : "${car.currentKm}"),
      "serviceIntervalDays": TextEditingController(text: "${car?.serviceIntervalDays ?? 365}"),
      "serviceIntervalKm": TextEditingController(text: "${car?.serviceIntervalKm ?? 15000}"),
      "technicalCheckIntervalDays": TextEditingController(
          text: "${(car?.technicalCheckIntervalDays ?? 0) > 0 ? car!.technicalCheckIntervalDays : 365}"),
    };
  }

  @override
  void dispose() {
    for (final c in _c.values) {
      c.dispose();
    }
    super.dispose();
  }

  int _int(String key, int fallback) => int.tryParse(_c[key]!.text.trim()) ?? fallback;

  Future<void> _save() async {
    final name = _c["name"]!.text.trim();
    if (name.isEmpty) {
      setState(() => _error = t("forms.validation.name"));
      return;
    }
    setState(() {
      _saving = true;
      _error = null;
    });
    final payload = {
      "name": name,
      "make": _c["make"]!.text.trim(),
      "model": _c["model"]!.text.trim(),
      "year": _int("year", 0),
      "registration": _c["registration"]!.text.trim(),
      "registrationCountry": _c["registrationCountry"]!.text.trim(),
      "vin": _c["vin"]!.text.trim(),
      "fuelType": _fuelType,
      "buildDate": _buildDate,
      "firstRegistrationDate": _firstRegistrationDate,
      "oilSpec": _c["oilSpec"]!.text.trim(),
      "transmissionOilSpec": _c["transmissionOilSpec"]!.text.trim(),
      "differentialOilSpec": _c["differentialOilSpec"]!.text.trim(),
      "brakeFluidSpec": _c["brakeFluidSpec"]!.text.trim(),
      "coolantSpec": _c["coolantSpec"]!.text.trim(),
      "currentKm": _int("currentKm", 0),
      "serviceIntervalDays": _int("serviceIntervalDays", 365),
      "serviceIntervalKm": _int("serviceIntervalKm", 15000),
      "technicalCheckIntervalDays": _int("technicalCheckIntervalDays", 365),
    };
    try {
      final saved = _isEdit
          ? await apiClient.updateCar(widget.car!.id, payload)
          : await apiClient.createCar(payload);
      if (mounted) Navigator.pop(context, saved);
    } catch (e) {
      setState(() => _error = e.toString());
    } finally {
      if (mounted) setState(() => _saving = false);
    }
  }

  static String _isoOrEmpty(DateTime? d) => d == null
      ? ""
      : "${d.year.toString().padLeft(4, '0')}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}";

  Widget _field(String key, String label,
      {TextInputType? keyboard,
      TextCapitalization caps = TextCapitalization.none,
      String? helper}) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 10),
      child: TextField(
        controller: _c[key],
        keyboardType: keyboard,
        textCapitalization: caps,
        decoration: InputDecoration(
          labelText: label,
          border: const OutlineInputBorder(),
          isDense: true,
          helperText: helper,
          helperMaxLines: 3,
        ),
      ),
    );
  }

  /// A tappable read-only field that opens a date picker. Shows a clear button
  /// when a date is set, otherwise a calendar icon.
  ///
  /// The value is an ISO string rather than a DateTime so that a half-known date
  /// entered on the web — "2015", "2015-03" — survives a save here: it is shown
  /// at the precision it has and handed back untouched unless the owner picks a
  /// new date, which this picker can only ever make a full one.
  Widget _dateField(String label, String value, ValueChanged<String> onChanged) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 10),
      child: InkWell(
        onTap: () async {
          final picked = await showDatePicker(
            context: context,
            initialDate: DateTime.tryParse(value) ?? DateTime.now(),
            firstDate: DateTime(1950),
            lastDate: DateTime.now().add(const Duration(days: 365)),
          );
          if (picked != null) setState(() => onChanged(_isoOrEmpty(picked)));
        },
        child: InputDecorator(
          decoration: InputDecoration(
            labelText: label,
            border: const OutlineInputBorder(),
            isDense: true,
            suffixIcon: value.isEmpty
                ? const Icon(Icons.calendar_today, size: 18)
                : IconButton(
                    icon: const Icon(Icons.clear, size: 18),
                    onPressed: () => setState(() => onChanged("")),
                  ),
          ),
          child: Text(formatPartialDate(value)),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(
        left: 16,
        right: 16,
        top: 16,
        bottom: DriverVault.sheetBottomInset(context),
      ),
      child: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(t(_isEdit ? "forms.car.editTitle" : "forms.car.addTitle"),
                style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600)),
            const SizedBox(height: 12),
            if (_error != null)
              Padding(
                padding: const EdgeInsets.only(bottom: 8),
                child: Text(_error!, style: const TextStyle(color: DriverVault.danger)),
              ),
            _field("name", t("forms.car.name"), caps: TextCapitalization.words),
            Row(children: [
              Expanded(child: _field("make", t("forms.car.make"))),
              const SizedBox(width: 8),
              Expanded(child: _field("model", t("forms.car.model"))),
            ]),
            Row(children: [
              Expanded(child: _field("year", t("forms.car.year"), keyboard: TextInputType.number)),
              const SizedBox(width: 8),
              Expanded(child: _field("registration", t("forms.car.registration"))),
            ]),
            _field("registrationCountry", t("forms.car.registrationCountry"),
                caps: TextCapitalization.words),
            _field("vin", t("forms.car.vin")),
            Padding(
              padding: const EdgeInsets.only(bottom: 10),
              child: DropdownButtonFormField<String>(
                initialValue: _fuelType.isEmpty ? null : _fuelType,
                decoration: InputDecoration(
                    labelText: t("forms.car.fuelType"),
                    border: const OutlineInputBorder(),
                    isDense: true),
                items: [
                  for (final key in kFuelTypes)
                    DropdownMenuItem(value: key, child: Text(t("enums.fuelType.$key"))),
                ],
                onChanged: (v) => setState(() => _fuelType = v ?? ""),
              ),
            ),
            Row(children: [
              Expanded(
                  child: _dateField(t("forms.car.buildDate"), _buildDate, (v) => _buildDate = v)),
              const SizedBox(width: 8),
              Expanded(
                  child: _dateField(t("forms.car.firstRegistration"), _firstRegistrationDate,
                      (v) => _firstRegistrationDate = v)),
            ]),
            _field("oilSpec", t("forms.car.oilSpec")),
            Row(children: [
              Expanded(child: _field("transmissionOilSpec", t("forms.car.transmissionOilSpec"))),
              const SizedBox(width: 8),
              Expanded(child: _field("differentialOilSpec", t("forms.car.differentialOilSpec"))),
            ]),
            Row(children: [
              Expanded(child: _field("brakeFluidSpec", t("forms.car.brakeFluidSpec"))),
              const SizedBox(width: 8),
              Expanded(child: _field("coolantSpec", t("forms.car.coolantSpec"))),
            ]),
            _field("currentKm", t("forms.car.currentKm"), keyboard: TextInputType.number),
            Row(children: [
              Expanded(
                  child: _field("serviceIntervalDays", t("forms.car.serviceIntervalDays"),
                      keyboard: TextInputType.number)),
              const SizedBox(width: 8),
              Expanded(
                  child: _field("serviceIntervalKm", t("forms.car.serviceIntervalKm"),
                      keyboard: TextInputType.number)),
            ]),
            _field("technicalCheckIntervalDays", t("forms.car.technicalCheckIntervalDays"),
                keyboard: TextInputType.number,
                helper: t("forms.car.technicalCheckHint")),
            const SizedBox(height: 8),
            SizedBox(
              width: double.infinity,
              child: FilledButton(
                onPressed: _saving ? null : _save,
                child: Text(_saving
                    ? t("common.saving")
                    : t(_isEdit ? "common.saveChanges" : "forms.car.submit")),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
