import 'package:uuid/uuid.dart';

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

const _uuid = Uuid();

class ListServersUseCase {
  final ServerRepository serverRepository;
  ListServersUseCase({required this.serverRepository});

  Future<List<EmbyServer>> execute() => serverRepository.list();
}

class ReorderServersUseCase {
  final ServerRepository serverRepository;

  ReorderServersUseCase({required this.serverRepository});

  Future<void> execute(List<EmbyServer> orderedServers) {
    return serverRepository.replaceAll(orderedServers);
  }
}

class ProbeServerUseCase {
  final EmbyGateway embyGateway;
  ProbeServerUseCase({required this.embyGateway});

  Future<ProbePublicInfoRes> execute(EmbyServerProbeReq input) async {
    final baseUrl = input.baseUrl.trim();
    if (baseUrl.isEmpty) {
      throw DomainError(ErrorCode.invalidParams, '服务器地址不能为空');
    }
    return embyGateway.probePublicInfo(baseUrl);
  }
}

class SaveServerUseCase {
  final ServerRepository serverRepository;
  final DateTime Function() now;
  final String Function() idGenerator;

  SaveServerUseCase({
    required this.serverRepository,
    DateTime Function()? now,
    String Function()? idGenerator,
  }) : now = (now ?? DateTime.now),
       idGenerator = (idGenerator ?? _defaultIdGenerator);

  static String _defaultIdGenerator() => _uuid.v4();

  Future<EmbyServer> execute(EmbyServerSaveReq input) async {
    final name = input.name.trim();
    if (name.isEmpty) {
      throw DomainError(ErrorCode.invalidParams, '服务器名称不能为空');
    }

    final baseUrl = _normalizeBaseUrl(input.baseUrl);
    final nowIso = now().toUtc().toIso8601String();

    final duplicated = await serverRepository.findByBaseUrl(baseUrl);
    if (duplicated != null && duplicated.id != input.id) {
      throw DomainError(
        ErrorCode.storeConflict,
        '服务器地址已存在',
        details: {'baseUrl': baseUrl},
      );
    }

    final iconUrl = input.iconUrl.trim();

    if (input.id != null) {
      final current = await serverRepository.findById(input.id!);
      if (current == null) {
        throw DomainError(
          ErrorCode.storeNotFound,
          '服务器不存在',
          details: {'id': input.id},
        );
      }
      return serverRepository.update(
        current.copyWith(
          name: name,
          baseUrl: baseUrl,
          updatedAt: nowIso,
          iconUrl: iconUrl,
        ),
      );
    }

    return serverRepository.create(
      EmbyServer(
        id: idGenerator(),
        name: name,
        baseUrl: baseUrl,
        createdAt: nowIso,
        updatedAt: nowIso,
        iconUrl: iconUrl,
      ),
    );
  }


  String _normalizeBaseUrl(String raw) {
    final trimmed = raw.trim();
    if (trimmed.isEmpty) {
      throw DomainError(ErrorCode.invalidParams, '服务器地址不能为空');
    }

    Uri parsed;
    try {
      parsed = Uri.parse(trimmed);
    } catch (_) {
      throw DomainError(
        ErrorCode.invalidParams,
        '服务器地址格式不正确',
        details: {'baseUrl': raw},
      );
    }

    if (parsed.scheme != 'http' && parsed.scheme != 'https') {
      throw DomainError(
        ErrorCode.invalidParams,
        '仅支持 HTTP/HTTPS 协议',
        details: {'baseUrl': raw},
      );
    }

    final origin =
        '${parsed.scheme}://${parsed.host}'
        '${parsed.hasPort ? ':${parsed.port}' : ''}';
    final cleanPath = parsed.path.replaceAll(RegExp(r'/+$'), '');
    final normalizedPath = cleanPath.isEmpty ? '/' : cleanPath;

    if (RegExp(r'/emby$', caseSensitive: false).hasMatch(normalizedPath)) {
      return '$origin$normalizedPath';
    }
    if (normalizedPath == '/') {
      return '$origin/emby';
    }
    return '$origin$normalizedPath/emby';
  }
}

class TogglePauseServerUseCase {
  final ServerRepository serverRepository;

  TogglePauseServerUseCase({required this.serverRepository});

  Future<EmbyServer> execute(String id) async {
    final current = await serverRepository.findById(id);
    if (current == null) {
      throw DomainError(ErrorCode.storeNotFound, '服务器不存在', details: {'id': id});
    }
    return serverRepository.update(current.copyWith(paused: !current.paused));
  }
}

class DeleteServerUseCase {
  final ServerRepository serverRepository;
  final SessionRepository sessionRepository;

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

  Future<void> execute(String id) async {
    final exists = await serverRepository.findById(id);
    if (exists == null) {
      throw DomainError(ErrorCode.storeNotFound, '服务器不存在', details: {'id': id});
    }
    await serverRepository.deleteById(id);
    await sessionRepository.clear(id);
  }
}
