import 'package:dio/dio.dart';
import 'package:superport_v2/core/common/models/paginated_result.dart';
import 'package:superport_v2/core/network/api_client.dart';
import 'package:superport_v2/core/network/api_routes.dart';

import '../../domain/entities/stock_transaction.dart';
import '../../domain/entities/stock_transaction_input.dart';
import '../../domain/repositories/stock_transaction_repository.dart';
import '../dtos/stock_transaction_dto.dart';

/// 재고 트랜잭션 API를 호출하는 원격 저장소 구현체.
class StockTransactionRepositoryRemote implements StockTransactionRepository {
  StockTransactionRepositoryRemote({required ApiClient apiClient})
    : _api = apiClient;

  final ApiClient _api;

  static const _basePath = '${ApiRoutes.apiV1}/stock-transactions';

  @override
  Future<PaginatedResult<StockTransaction>> list({
    StockTransactionListFilter? filter,
  }) async {
    final effectiveFilter = filter ?? StockTransactionListFilter();
    final response = await _api.get<Map<String, dynamic>>(
      _basePath,
      query: effectiveFilter.toQuery(),
      options: Options(responseType: ResponseType.json),
    );
    return StockTransactionDto.parsePaginated(response.data ?? const {});
  }

  @override
  Future<StockTransaction> fetchDetail(
    int id, {
    List<String> include = const ['lines', 'customers', 'approval'],
  }) async {
    final response = await _api.get<Map<String, dynamic>>(
      '$_basePath/$id',
      query: {if (include.isNotEmpty) 'include': include.join(',')},
      options: Options(responseType: ResponseType.json),
    );
    return _parseSingle(response.data);
  }

  @override
  Future<StockTransaction> create(StockTransactionCreateInput input) async {
    final response = await _api.post<Map<String, dynamic>>(
      _basePath,
      data: input.toPayload(),
      options: Options(responseType: ResponseType.json),
    );
    return _parseSingle(response.data);
  }

  @override
  Future<StockTransaction> update(
    int id,
    StockTransactionUpdateInput input,
  ) async {
    final payload = {'id': id, ...input.toPayload()};
    final response = await _api.patch<Map<String, dynamic>>(
      '$_basePath/$id',
      data: payload,
      options: Options(responseType: ResponseType.json),
    );
    return _parseSingle(response.data);
  }

  @override
  Future<void> delete(int id) async {
    await _api.delete<void>('$_basePath/$id');
  }

  @override
  Future<StockTransaction> restore(int id) async {
    final response = await _api.post<Map<String, dynamic>>(
      '$_basePath/$id/restore',
      options: Options(responseType: ResponseType.json),
    );
    return _parseSingle(response.data);
  }

  @override
  Future<StockTransaction> submit(int id, {String? note}) async {
    return _postTransition(id: id, action: 'submit', note: note);
  }

  @override
  Future<StockTransaction> complete(int id, {String? note}) async {
    return _postTransition(id: id, action: 'complete', note: note);
  }

  @override
  Future<StockTransaction> approve(int id, {String? note}) async {
    return _postTransition(id: id, action: 'approve', note: note);
  }

  @override
  Future<StockTransaction> reject(int id, {String? note}) async {
    return _postTransition(id: id, action: 'reject', note: note);
  }

  @override
  Future<StockTransaction> cancel(int id, {String? note}) async {
    return _postTransition(id: id, action: 'cancel', note: note);
  }

  Future<StockTransaction> _postTransition({
    required int id,
    required String action,
    String? note,
  }) async {
    final payload = <String, dynamic>{'id': id};
    final trimmedNote = note?.trim();
    if (trimmedNote != null && trimmedNote.isNotEmpty) {
      payload['note'] = trimmedNote;
    }
    final response = await _api.post<Map<String, dynamic>>(
      '$_basePath/$id/$action',
      data: payload,
      options: Options(responseType: ResponseType.json),
    );
    return _parseSingle(response.data);
  }

  StockTransaction _parseSingle(Map<String, dynamic>? body) {
    final data = _extractData(body);
    return StockTransactionDto.fromJson(data).toEntity();
  }

  Map<String, dynamic> _extractData(Map<String, dynamic>? body) {
    if (body == null) {
      return <String, dynamic>{};
    }
    if (body['data'] is Map<String, dynamic>) {
      return body['data'] as Map<String, dynamic>;
    }
    if (body.containsKey('transaction')) {
      final transaction = body['transaction'];
      if (transaction is Map<String, dynamic>) {
        return transaction;
      }
    }
    return body;
  }
}
