import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:formz/formz.dart';
import 'package:equatable/equatable.dart';
import '../../../../core/api/api_exception.dart';
import '../../../../core/form_inputs/form_inputs.dart';
import '../../data/auth_repository.dart';
import '../../data/models/signup_request.dart';
import '../../data/models/auth_response.dart';

class RegisterState extends Equatable {
  final Username username;
  final Email email;
  final Password password;
  final VerificationCode verificationCode;
  final String inviteCode;
  final FormzSubmissionStatus status;
  final String? errorMessage;
  final String? pendingEmail;
  final bool codeSent;
  final bool isSending;

  const RegisterState({
    this.username = const Username.pure(),
    this.email = const Email.pure(),
    this.password = const Password.pure(),
    this.verificationCode = const VerificationCode.pure(),
    this.inviteCode = '',
    this.status = FormzSubmissionStatus.initial,
    this.errorMessage,
    this.pendingEmail,
    this.codeSent = false,
    this.isSending = false,
  });

  bool get isStep1Valid =>
      username.isValid && email.isValid && password.isValid;
  bool get isStep2Valid => verificationCode.isValid;

  RegisterState copyWith({
    Username? username,
    Email? email,
    Password? password,
    VerificationCode? verificationCode,
    String? inviteCode,
    FormzSubmissionStatus? status,
    String? errorMessage,
    String? pendingEmail,
    bool? codeSent,
    bool? isSending,
  }) {
    return RegisterState(
      username: username ?? this.username,
      email: email ?? this.email,
      password: password ?? this.password,
      verificationCode: verificationCode ?? this.verificationCode,
      inviteCode: inviteCode ?? this.inviteCode,
      status: status ?? this.status,
      errorMessage: errorMessage,
      pendingEmail: pendingEmail ?? this.pendingEmail,
      codeSent: codeSent ?? this.codeSent,
      isSending: isSending ?? this.isSending,
    );
  }

  @override
  List<Object?> get props => [
    username,
    email,
    password,
    verificationCode,
    inviteCode,
    status,
    errorMessage,
    pendingEmail,
    codeSent,
    isSending,
  ];
}

class RegisterCubit extends Cubit<RegisterState> {
  final AuthRepository _repository;

  RegisterCubit(this._repository) : super(const RegisterState());

  void usernameChanged(String value) {
    emit(state.copyWith(username: Username.dirty(value)));
  }

  void emailChanged(String value) {
    emit(state.copyWith(email: Email.dirty(value)));
  }

  void passwordChanged(String value) {
    emit(state.copyWith(password: Password.dirty(value)));
  }

  void verificationCodeChanged(String value) {
    emit(state.copyWith(verificationCode: VerificationCode.dirty(value)));
  }

  void inviteCodeChanged(String value) {
    emit(state.copyWith(inviteCode: value));
  }

  Future<bool> submitStep1() async {
    if (!state.isStep1Valid) return false;

    emit(state.copyWith(status: FormzSubmissionStatus.inProgress));

    try {
      final response = await _repository.createVerification(
        SignupStartRequest(
          username: state.username.value,
          email: state.email.value,
          password: state.password.value,
          inviteCode: state.inviteCode.isNotEmpty ? state.inviteCode : null,
        ),
      );
      emit(
        state.copyWith(
          status: FormzSubmissionStatus.success,
          pendingEmail: response.email,
          codeSent: true,
        ),
      );
      return true;
    } catch (e) {
      final message = e is ApiException ? e.message : e.toString();
      emit(
        state.copyWith(
          status: FormzSubmissionStatus.failure,
          errorMessage: message,
        ),
      );
      return false;
    }
  }

  Future<AuthResponse?> submitStep2() async {
    if (!state.isStep2Valid || state.pendingEmail == null) return null;

    emit(state.copyWith(status: FormzSubmissionStatus.inProgress));

    try {
      final response = await _repository.verifyVerification(
        SignupVerifyRequest(
          email: state.pendingEmail!,
          token: state.verificationCode.value,
        ),
      );
      emit(state.copyWith(status: FormzSubmissionStatus.success));
      return response;
    } catch (e) {
      final message = e is ApiException ? e.message : e.toString();
      emit(
        state.copyWith(
          status: FormzSubmissionStatus.failure,
          errorMessage: message,
        ),
      );
      return null;
    }
  }

  Future<bool> resendCode() async {
    if (state.pendingEmail == null) {
      emit(
        state.copyWith(
          status: FormzSubmissionStatus.failure,
          errorMessage: '验证码发送失败，请返回上一步重试',
        ),
      );
      return false;
    }

    emit(state.copyWith(status: FormzSubmissionStatus.inProgress));

    try {
      await _repository.resendVerification(
        SignupResendRequest(email: state.pendingEmail!),
      );
      emit(
        state.copyWith(status: FormzSubmissionStatus.success, codeSent: true),
      );
      return true;
    } catch (e) {
      final message = e is ApiException ? e.message : '验证码发送失败，请重试';
      emit(
        state.copyWith(
          status: FormzSubmissionStatus.failure,
          errorMessage: message,
        ),
      );
      return false;
    }
  }

  Future<void> sendCodeSilently() async {
    if (!state.isStep1Valid || state.isSending) return;

    emit(
      state.copyWith(
        isSending: true,
        status: FormzSubmissionStatus.inProgress,
        errorMessage: null,
      ),
    );

    try {
      final response = await _repository.createVerification(
        SignupStartRequest(
          username: state.username.value,
          email: state.email.value,
          password: state.password.value,
          inviteCode: state.inviteCode.isNotEmpty ? state.inviteCode : null,
        ),
      );
      emit(
        state.copyWith(
          isSending: false,
          status: FormzSubmissionStatus.success,
          pendingEmail: response.email,
          codeSent: true,
          errorMessage: null,
        ),
      );
    } catch (e) {
      final message = e is ApiException ? e.message : '验证码发送失败，请重试';
      emit(
        state.copyWith(
          isSending: false,
          status: FormzSubmissionStatus.failure,
          errorMessage: message,
        ),
      );
    }
  }
}
