import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import '../../../core/api/api_error_mapper.dart';
import '../../../core/api/api_exception.dart';
import '../../../core/l10n/l10n.dart';
import '../../auth/data/auth_providers.dart';
import '../data/recipe_providers.dart';
import '../domain/parsed_recipe.dart';

enum _Step { input, review }

class CreateRecipeScreen extends ConsumerStatefulWidget {
  /// Optional markdown to pre-fill the input field, e.g. from import.
  final String? initialMarkdown;

  /// Optional image URL pre-filled from a quick-import result.
  final String? initialImageUrl;

  const CreateRecipeScreen({
    super.key,
    this.initialMarkdown,
    this.initialImageUrl,
  });

  @override
  ConsumerState<CreateRecipeScreen> createState() =>
      _CreateRecipeScreenState();
}

class _CreateRecipeScreenState extends ConsumerState<CreateRecipeScreen> {
  _Step _step = _Step.input;

  // Step 1 — markdown input
  late final TextEditingController _markdownCtrl;
  bool _isParsing = false;
  String? _parseError;

  @override
  void initState() {
    super.initState();
    _markdownCtrl = TextEditingController(text: widget.initialMarkdown ?? '');
  }

  // Step 2 — review state
  ParsedRecipe? _parsed;
  late TextEditingController _nameCtrl;
  late TextEditingController _servingsCtrl;
  late List<bool> _included;
  late Map<int, int?> _selectedProductIds;
  late Map<int, String?> _selectedProductNames;

  bool _isSaving = false;
  String? _saveError;

  @override
  void dispose() {
    _markdownCtrl.dispose();  // always non-null after initState
    if (_step == _Step.review) {
      _nameCtrl.dispose();
      _servingsCtrl.dispose();
    }
    super.dispose();
  }

  void _initReviewState(ParsedRecipe parsed) {
    _nameCtrl = TextEditingController(text: parsed.name);
    _servingsCtrl = TextEditingController();
    _included = List.generate(parsed.ingredients.length, (_) => true);
    _selectedProductIds = {};
    _selectedProductNames = {};
    for (var i = 0; i < parsed.ingredients.length; i++) {
      final suggestions = parsed.ingredients[i].suggestions;
      if (suggestions.isNotEmpty) {
        _selectedProductIds[i] = suggestions.first.productId;
        _selectedProductNames[i] = suggestions.first.productName;
      } else {
        _selectedProductIds[i] = null;
        _selectedProductNames[i] = null;
      }
    }
  }

  Future<void> _parseMarkdown() async {
    final markdown = _markdownCtrl.text.trim();
    if (markdown.isEmpty) {
      setState(() => _parseError = context.l10n.recipeCreateMarkdownHint);
      return;
    }
    setState(() {
      _isParsing = true;
      _parseError = null;
    });
    try {
      final token = await ref.read(authStateProvider.future);
      final parsed = await ref
          .read(recipeRepositoryProvider)
          .parseMarkdown(markdown, token: token);
      _initReviewState(parsed);
      setState(() {
        _parsed = parsed;
        _step = _Step.review;
        _isParsing = false;
      });
    } on ApiException catch (e) {
      if (e.type == ApiErrorType.unauthorized) {
        await ref.read(authStateProvider.notifier).logout();
        return;
      }
      setState(() {
        _parseError = mapErrorToUserMessage(e, context);
        _isParsing = false;
      });
    }
  }

  Future<void> _save() async {
    final name = _nameCtrl.text.trim();
    if (name.isEmpty) {
      setState(() => _saveError = context.l10n.recipeCreateNameRequired);
      return;
    }

    final ingredients = <Map<String, dynamic>>[];
    for (var i = 0; i < _parsed!.ingredients.length; i++) {
      if (!_included[i]) continue;
      final productId = _selectedProductIds[i];
      if (productId == null) continue;
      final ing = _parsed!.ingredients[i];
      ingredients.add({
        'productId': productId,
        'quantity': ing.quantity,
        'unit': ing.unit,
        if (ing.note != null) 'note': ing.note,
      });
    }

    setState(() {
      _isSaving = true;
      _saveError = null;
    });

    try {
      final token = await ref.read(authStateProvider.future);
      final servingsRaw = int.tryParse(_servingsCtrl.text.trim());
      final created = await ref.read(recipeRepositoryProvider).createRecipe(
        {
          'name': name,
          if (_parsed!.description != null) 'description': _parsed!.description,
          if (servingsRaw != null) 'servings': servingsRaw,
          if (_parsed!.instructions != null)
            'instructions': _parsed!.instructions,
          if (widget.initialImageUrl != null && widget.initialImageUrl!.isNotEmpty)
            'imageUrl': widget.initialImageUrl,
          'ingredients': ingredients,
        },
        token: token,
      );
      ref.invalidate(recipesProvider);
      if (mounted) context.go('/recipes/${created.id}');
    } on ApiException catch (e) {
      if (e.type == ApiErrorType.unauthorized) {
        await ref.read(authStateProvider.notifier).logout();
        return;
      }
      setState(() {
        _saveError = mapErrorToUserMessage(e, context);
        _isSaving = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title:
            Text(_step == _Step.input ? context.l10n.recipeCreateTitle : context.l10n.recipeCreateReviewIngredients),
        leading: _step == _Step.review
            ? IconButton(
                icon: const Icon(Icons.arrow_back),
                onPressed: () => setState(() {
                  _step = _Step.input;
                  _nameCtrl.dispose();
                  _servingsCtrl.dispose();
                }),
              )
            : null,
      ),
      body: _step == _Step.input ? _buildInputStep() : _buildReviewStep(),
    );
  }

  Widget _buildInputStep() {
    return Column(
      children: [
        Expanded(
          child: Padding(
            padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
            child: TextField(
              controller: _markdownCtrl,
              maxLines: null,
              expands: true,
              textAlignVertical: TextAlignVertical.top,
              decoration: InputDecoration(
                hintText: context.l10n.recipeCreateMarkdownPlaceholder,
                border: const OutlineInputBorder(),
                alignLabelWithHint: true,
              ),
            ),
          ),
        ),
        if (_parseError != null)
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Text(
              _parseError!,
              style: TextStyle(color: Theme.of(context).colorScheme.error),
            ),
          ),
        Padding(
          padding: const EdgeInsets.all(16),
          child: SizedBox(
            width: double.infinity,
            child: FilledButton(
              onPressed: _isParsing ? null : _parseMarkdown,
              child: _isParsing
                  ? const SizedBox(
                      height: 18,
                      width: 18,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : Text(context.l10n.recipeCreateReviewIngredients),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildReviewStep() {
    final parsed = _parsed!;
    return Column(
      children: [
        Expanded(
          child: ListView(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            children: [
              TextField(
                controller: _nameCtrl,
                decoration: InputDecoration(labelText: context.l10n.recipeEditNameLabel),
              ),
              const SizedBox(height: 12),
              TextField(
                controller: _servingsCtrl,
                decoration: InputDecoration(
                    labelText: context.l10n.recipeEditServingsLabel),
                keyboardType: TextInputType.number,
              ),
              if (parsed.ingredients.isNotEmpty) ...[
                const SizedBox(height: 20),
                Text(context.l10n.recipeEditIngredientsLabel,
                    style: Theme.of(context).textTheme.titleMedium),
                const SizedBox(height: 4),
                Text(
                  context.l10n.recipeCreateIngredientsHint,
                  style: Theme.of(context).textTheme.bodySmall,
                ),
                const SizedBox(height: 8),
                ...List.generate(
                    parsed.ingredients.length,
                    (i) => _buildIngredientRow(i, parsed.ingredients[i])),
              ],
              const SizedBox(height: 8),
            ],
          ),
        ),
        if (_saveError != null)
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Text(
              _saveError!,
              style: TextStyle(color: Theme.of(context).colorScheme.error),
            ),
          ),
        Padding(
          padding: const EdgeInsets.all(16),
          child: SizedBox(
            width: double.infinity,
            child: FilledButton(
              onPressed: _isSaving ? null : _save,
              child: _isSaving
                  ? const SizedBox(
                      height: 18,
                      width: 18,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : Text(context.l10n.recipeCreateSaveAction),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildIngredientRow(int index, ParsedIngredient ing) {
    final qtyStr = ing.quantity > 0
        ? (ing.quantity == ing.quantity.truncateToDouble()
            ? '${ing.quantity.toInt()} '
            : '${ing.quantity} ')
        : '';
    final unitStr = ing.unit.isNotEmpty ? '${ing.unit} ' : '';
    final noteStr = ing.note != null ? ' (${ing.note})' : '';
    final label = '$qtyStr$unitStr${ing.rawName}$noteStr';

    return Card(
      margin: const EdgeInsets.symmetric(vertical: 4),
      child: CheckboxListTile(
        value: _included[index],
        onChanged: (v) => setState(() => _included[index] = v ?? false),
        title: Text(label),
        subtitle: ing.suggestions.isEmpty
            ? Text(
                context.l10n.recipeCreateNoProductFound,
                style: TextStyle(
                    color: Theme.of(context).colorScheme.onSurfaceVariant,
                    fontSize: 12),
              )
            : DropdownButton<int>(
                value: _selectedProductIds[index],
                isExpanded: true,
                onChanged: _included[index]
                    ? (id) {
                        if (id == null) return;
                        setState(() {
                          _selectedProductIds[index] = id;
                          _selectedProductNames[index] = ing.suggestions
                              .firstWhere((s) => s.productId == id)
                              .productName;
                        });
                      }
                    : null,
                items: ing.suggestions
                    .map((s) => DropdownMenuItem(
                          value: s.productId,
                          child: Text(s.productName),
                        ))
                    .toList(),
              ),
      ),
    );
  }
}
