import '../../contracts/contracts.dart';
import '../errors.dart';
import '../ports/emby_gateway.dart';
import '../ports/server_repository.dart';
import '../ports/session_repository.dart';

class AuthByNameUseCase {
  final ServerRepository serverRepository;
  final SessionRepository sessionRepository;
  final EmbyGateway embyGateway;
  final DateTime Function() now;

  AuthByNameUseCase({
    required this.serverRepository,
    required this.sessionRepository,
    required this.embyGateway,
    DateTime Function()? now,
  }) : now = now ?? DateTime.now;

  Future<void> execute(AuthByNameReq input) async {
    final username = input.username.trim();
    final password = input.password;
    if (username.isEmpty || password.isEmpty) {
      throw DomainError(ErrorCode.invalidParams, '用户名或密码不能为空');
    }

    final server = await serverRepository.findById(input.serverId);
    if (server == null) {
      throw DomainError(
        ErrorCode.storeNotFound,
        '服务器不存在',
        details: {'serverId': input.serverId},
      );
    }

    final auth = await embyGateway.authenticateByName(
      baseUrl: server.baseUrl,
      username: username,
      password: password,
    );

    final nowIso = now().toUtc().toIso8601String();
    await sessionRepository.set(
      SessionData(
        serverId: server.id,
        token: auth.accessToken,
        userId: auth.userId,
        userName: auth.userName,
        password: password,
        createdAt: nowIso,
      ),
    );
    await serverRepository.touchConnectedAt(server.id, nowIso);
  }
}

class LogoutUseCase {
  final SessionRepository sessionRepository;
  LogoutUseCase({required this.sessionRepository});

  Future<void> execute([String? serverId]) => sessionRepository.clear(serverId);
}

class ListSessionsUseCase {
  final SessionRepository sessionRepository;
  final ServerRepository serverRepository;

  ListSessionsUseCase({
    required this.sessionRepository,
    required this.serverRepository,
  });

  Future<SessionListRes> execute() async {
    final sessions = await sessionRepository.listAll();
    final activeServerId = await sessionRepository.getActiveServerId();
    final result = <AuthedSession>[];

    for (final session in sessions) {
      final server = await serverRepository.findById(session.serverId);
      if (server != null) {
        result.add(
          AuthedSession(
            serverId: session.serverId,
            serverName: server.name,
            serverUrl: server.baseUrl,
            token: session.token,
            userId: session.userId,
            userName: session.userName,
            password: session.password,
            isActive: session.serverId == activeServerId,
          ),
        );
      }
    }

    return SessionListRes(sessions: result, activeServerId: activeServerId);
  }
}

class SwitchSessionUseCase {
  final SessionRepository sessionRepository;

  SwitchSessionUseCase({required this.sessionRepository});

  Future<void> execute(String serverId) async {
    final session = await sessionRepository.getByServerId(serverId);
    if (session == null) {
      throw DomainError(
        ErrorCode.storeNotFound,
        '该服务器没有可用会话',
        details: {'serverId': serverId},
      );
    }
    await sessionRepository.setActive(serverId);
  }
}

class ChangePasswordUseCase {
  final SessionRepository sessionRepository;
  final ServerRepository serverRepository;
  final EmbyGateway embyGateway;

  ChangePasswordUseCase({
    required this.sessionRepository,
    required this.serverRepository,
    required this.embyGateway,
  });

  Future<void> execute({
    required String serverId,
    required String currentPassword,
    required String newPassword,
  }) async {
    if (currentPassword.isEmpty || newPassword.isEmpty) {
      throw DomainError(ErrorCode.invalidParams, '密码不能为空');
    }

    final session = await sessionRepository.getByServerId(serverId);
    if (session == null) {
      throw DomainError(ErrorCode.storeNotFound, '该服务器没有可用会话');
    }
    final server = await serverRepository.findById(serverId);
    if (server == null) {
      throw DomainError(ErrorCode.storeNotFound, '服务器不存在');
    }

    final ctx = AuthedRequestContext(
      baseUrl: server.baseUrl,
      token: session.token,
      userId: session.userId,
    );

    await embyGateway.changePassword(
      ctx: ctx,
      currentPassword: currentPassword,
      newPassword: newPassword,
    );

    await sessionRepository.setMany([session.copyWith(password: newPassword)]);
  }
}
