import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lunchpick/core/constants/app_colors.dart';
import 'package:lunchpick/core/constants/app_typography.dart';
import 'package:lunchpick/domain/entities/restaurant.dart';
import 'package:lunchpick/presentation/providers/restaurant_provider.dart';
import 'package:lunchpick/presentation/providers/di_providers.dart';
import 'package:lunchpick/presentation/providers/location_provider.dart';

import 'add_restaurant_form.dart';

/// 기존 맛집 정보를 편집하는 다이얼로그
class EditRestaurantDialog extends ConsumerStatefulWidget {
  final Restaurant restaurant;

  const EditRestaurantDialog({super.key, required this.restaurant});

  @override
  ConsumerState<EditRestaurantDialog> createState() =>
      _EditRestaurantDialogState();
}

class _EditRestaurantDialogState extends ConsumerState<EditRestaurantDialog> {
  final _formKey = GlobalKey<FormState>();

  late final TextEditingController _nameController;
  late final TextEditingController _categoryController;
  late final TextEditingController _subCategoryController;
  late final TextEditingController _descriptionController;
  late final TextEditingController _phoneController;
  late final TextEditingController _roadAddressController;
  late final TextEditingController _jibunAddressController;
  late final TextEditingController _latitudeController;
  late final TextEditingController _longitudeController;

  bool _isSaving = false;
  late final String _originalRoadAddress;
  late final String _originalJibunAddress;

  @override
  void initState() {
    super.initState();
    final restaurant = widget.restaurant;
    _nameController = TextEditingController(text: restaurant.name);
    _categoryController = TextEditingController(text: restaurant.category);
    _subCategoryController = TextEditingController(
      text: restaurant.subCategory,
    );
    _descriptionController = TextEditingController(
      text: restaurant.description ?? '',
    );
    _phoneController = TextEditingController(
      text: restaurant.phoneNumber ?? '',
    );
    _roadAddressController = TextEditingController(
      text: restaurant.roadAddress,
    );
    _jibunAddressController = TextEditingController(
      text: restaurant.jibunAddress,
    );
    _latitudeController = TextEditingController(
      text: restaurant.latitude.toString(),
    );
    _longitudeController = TextEditingController(
      text: restaurant.longitude.toString(),
    );
    _originalRoadAddress = restaurant.roadAddress;
    _originalJibunAddress = restaurant.jibunAddress;
  }

  @override
  void dispose() {
    _nameController.dispose();
    _categoryController.dispose();
    _subCategoryController.dispose();
    _descriptionController.dispose();
    _phoneController.dispose();
    _roadAddressController.dispose();
    _jibunAddressController.dispose();
    _latitudeController.dispose();
    _longitudeController.dispose();
    super.dispose();
  }

  void _onFieldChanged(String _) {
    setState(() {});
  }

  Future<void> _save() async {
    if (_formKey.currentState?.validate() != true) {
      return;
    }

    setState(() => _isSaving = true);

    final addressChanged =
        _roadAddressController.text.trim() != _originalRoadAddress ||
        _jibunAddressController.text.trim() != _originalJibunAddress;
    final coords = await _resolveCoordinates(
      latitudeText: _latitudeController.text.trim(),
      longitudeText: _longitudeController.text.trim(),
      roadAddress: _roadAddressController.text.trim(),
      jibunAddress: _jibunAddressController.text.trim(),
      forceRecalculate: addressChanged,
    );

    _latitudeController.text = coords.latitude.toString();
    _longitudeController.text = coords.longitude.toString();

    final updatedRestaurant = widget.restaurant.copyWith(
      name: _nameController.text.trim(),
      category: _categoryController.text.trim(),
      subCategory: _subCategoryController.text.trim().isEmpty
          ? _categoryController.text.trim()
          : _subCategoryController.text.trim(),
      description: _descriptionController.text.trim().isEmpty
          ? null
          : _descriptionController.text.trim(),
      phoneNumber: _phoneController.text.trim().isEmpty
          ? null
          : _phoneController.text.trim(),
      roadAddress: _roadAddressController.text.trim(),
      jibunAddress: _jibunAddressController.text.trim().isEmpty
          ? _roadAddressController.text.trim()
          : _jibunAddressController.text.trim(),
      latitude: coords.latitude,
      longitude: coords.longitude,
      updatedAt: DateTime.now(),
      needsAddressVerification: coords.usedCurrentLocation,
    );

    try {
      await ref
          .read(restaurantNotifierProvider.notifier)
          .updateRestaurant(updatedRestaurant);
      if (!mounted) return;
      final messenger = ScaffoldMessenger.of(context);
      Navigator.of(context).pop(true);
      messenger.showSnackBar(
        SnackBar(
          content: Row(
            children: const [
              Icon(Icons.check_circle, color: Colors.white, size: 20),
              SizedBox(width: 8),
              Text('맛집 정보가 업데이트되었습니다'),
            ],
          ),
          backgroundColor: Colors.green,
        ),
      );
    } catch (e) {
      if (!mounted) return;
      setState(() => _isSaving = false);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('수정에 실패했습니다: $e'),
          backgroundColor: AppColors.lightError,
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final categories = ref
        .watch(categoriesProvider)
        .maybeWhen(data: (list) => list, orElse: () => const <String>[]);
    final subCategories = ref
        .watch(subCategoriesProvider)
        .maybeWhen(data: (list) => list, orElse: () => const <String>[]);

    return Dialog(
      backgroundColor: isDark ? AppColors.darkSurface : AppColors.lightSurface,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 420),
        child: SingleChildScrollView(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Text(
                '맛집 정보 수정',
                style: AppTypography.heading1(isDark),
                textAlign: TextAlign.center,
              ),
              const SizedBox(height: 16),
              AddRestaurantForm(
                formKey: _formKey,
                nameController: _nameController,
                categoryController: _categoryController,
                subCategoryController: _subCategoryController,
                descriptionController: _descriptionController,
                phoneController: _phoneController,
                roadAddressController: _roadAddressController,
                jibunAddressController: _jibunAddressController,
                latitudeController: _latitudeController,
                longitudeController: _longitudeController,
                onFieldChanged: _onFieldChanged,
                categories: categories,
                subCategories: subCategories,
              ),
              const SizedBox(height: 24),
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  TextButton(
                    onPressed: _isSaving
                        ? null
                        : () => Navigator.of(context).pop(),
                    child: const Text('취소'),
                  ),
                  const SizedBox(width: 8),
                  ElevatedButton(
                    onPressed: _isSaving ? null : _save,
                    child: _isSaving
                        ? const SizedBox(
                            width: 18,
                            height: 18,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                              valueColor: AlwaysStoppedAnimation<Color>(
                                Colors.white,
                              ),
                            ),
                          )
                        : const Text('저장'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<({double latitude, double longitude, bool usedCurrentLocation})>
  _resolveCoordinates({
    required String latitudeText,
    required String longitudeText,
    required String roadAddress,
    required String jibunAddress,
    bool forceRecalculate = false,
  }) async {
    if (!forceRecalculate) {
      final parsedLat = double.tryParse(latitudeText);
      final parsedLon = double.tryParse(longitudeText);
      if (parsedLat != null && parsedLon != null) {
        return (
          latitude: parsedLat,
          longitude: parsedLon,
          usedCurrentLocation: false,
        );
      }
    }

    final geocodingService = ref.read(geocodingServiceProvider);
    final address = roadAddress.isNotEmpty ? roadAddress : jibunAddress;
    if (address.isNotEmpty) {
      final result = await geocodingService.geocode(address);
      if (result != null) {
        return (
          latitude: result.latitude,
          longitude: result.longitude,
          usedCurrentLocation: false,
        );
      }
    }

    try {
      final position = await ref.read(currentLocationProvider.future);
      if (position != null) {
        return (
          latitude: position.latitude,
          longitude: position.longitude,
          usedCurrentLocation: true,
        );
      }
    } catch (_) {}

    final fallback = geocodingService.defaultCoordinates();
    return (
      latitude: fallback.latitude,
      longitude: fallback.longitude,
      usedCurrentLocation: true,
    );
  }
}
