import 'package:flutter/material.dart';

import 'package:pshared/provider/account.dart';

import 'package:pweb/models/state/edit_state.dart';


class AccountNameController extends ChangeNotifier {
  AccountNameController({
    required this.initialFirstName,
    required this.initialLastName,
    required this.errorMessage,
  }) {
    _firstNameController = TextEditingController(text: initialFirstName);
    _lastNameController = TextEditingController(text: initialLastName);
    _lastSyncedFirstName = initialFirstName;
    _lastSyncedLastName = initialLastName;
  }

  AccountProvider? _accountProvider;
  final String initialFirstName;
  final String initialLastName;
  final String errorMessage;

  late final TextEditingController _firstNameController;
  late final TextEditingController _lastNameController;
  EditState _editState = EditState.view;
  String _errorText = '';
  bool _disposed = false;
  String _lastSyncedFirstName = '';
  String _lastSyncedLastName = '';

  TextEditingController get firstNameController => _firstNameController;
  TextEditingController get lastNameController => _lastNameController;
  EditState get editState => _editState;
  String get errorText => _errorText;
  bool get isEditing => _editState != EditState.view;
  bool get isSaving => _editState == EditState.saving;
  bool get isBusy => (_accountProvider?.isLoading ?? false) || isSaving;

  String get currentFirstName =>
      _accountProvider?.account?.name ?? initialFirstName;
  String get currentLastName =>
      _accountProvider?.account?.lastName ?? initialLastName;
  String get currentFullName {
    final first = currentFirstName.trim();
    final last = currentLastName.trim();
    if (first.isEmpty && last.isEmpty) return '';
    if (first.isEmpty) return last;
    if (last.isEmpty) return first;
    return '$first $last';
  }

  void update(AccountProvider accountProvider) {
    _accountProvider = accountProvider;
    final changed = _syncNamesFromProvider();
    if (changed) {
      notifyListeners();
    }
  }

  void startEditing() => _setState(EditState.edit);

  void cancelEditing() {
    _firstNameController.text = currentFirstName;
    _lastNameController.text = currentLastName;
    _setError('');
    _setState(EditState.view);
  }

  Future<bool> save() async {
    final accountProvider = _accountProvider;
    if (accountProvider == null) return false;

    final newFirstName = _firstNameController.text.trim();
    final newLastName = _lastNameController.text.trim();
    final currentFirst = currentFirstName;
    final currentLast = currentLastName;

    if (newFirstName.isEmpty ||
        (newFirstName == currentFirst && newLastName == currentLast)) {
      cancelEditing();
      return false;
    }

    _setError('');
    _setState(EditState.saving);

    try {
      await accountProvider.resetUsername(
        newFirstName,
        lastName: newLastName,
      );
      _setState(EditState.view);
      return true;
    } catch (_) {
      _setError(errorMessage);
      _setState(EditState.edit);
      return false;
    } finally {
      if (_editState == EditState.saving) {
        _setState(EditState.edit);
      }
    }
  }

  bool _syncNamesFromProvider() {
    if (isEditing) return false;
    final latestFirstName = currentFirstName;
    final latestLastName = currentLastName;
    final didChange = latestFirstName != _lastSyncedFirstName ||
        latestLastName != _lastSyncedLastName;
    if (_firstNameController.text != latestFirstName) {
      _firstNameController.text = latestFirstName;
    }
    if (_lastNameController.text != latestLastName) {
      _lastNameController.text = latestLastName;
    }
    _lastSyncedFirstName = latestFirstName;
    _lastSyncedLastName = latestLastName;
    return didChange;
  }

  void _setState(EditState value) {
    if (_disposed || _editState == value) return;
    _editState = value;
    notifyListeners();
  }

  void _setError(String value) {
    if (_disposed) return;
    _errorText = value;
    notifyListeners();
  }

  @override
  void dispose() {
    _disposed = true;
    _firstNameController.dispose();
    _lastNameController.dispose();
    super.dispose();
  }
}
