import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { environment } from '@environments/environment';
import { Observable, map, catchError, throwError } from 'rxjs';

import {
  Transaction,
  TransactionQuery,
  PaginatedTransactions,
  TransactionStats,
  RefundRequest
} from '../models/transaction';

@Injectable({ providedIn: 'root' })
export class TransactionsService {
  private http = inject(HttpClient);
  private apiUrl = `${environment.localServiceTestApiUrl}/transactions`;

  // === CRUD OPERATIONS ===
  getTransactions(query: TransactionQuery): Observable<PaginatedTransactions> {
    let params = new HttpParams();
    
    // Ajouter tous les paramètres de query
    Object.keys(query).forEach(key => {
      const value = query[key as keyof TransactionQuery];
      if (value !== undefined && value !== null) {
        if (value instanceof Date) {
          params = params.set(key, value.toISOString());
        } else {
          params = params.set(key, value.toString());
        }
      }
    });

    return this.http.get<PaginatedTransactions>(`${this.apiUrl}`, { params }).pipe(
      catchError(error => {
        console.error('Error loading transactions:', error);
        return throwError(() => error);
      })
    );
  }

  getTransactionById(id: string): Observable<Transaction> {
    return this.http.get<Transaction>(`${this.apiUrl}/${id}`).pipe(
      catchError(error => {
        console.error('Error loading transaction:', error);
        return throwError(() => error);
      })
    );
  }

  // === ACTIONS ===
  refundTransaction(refundRequest: RefundRequest): Observable<{ message: string; transaction: Transaction }> {
    return this.http.post<{ message: string; transaction: Transaction }>(
      `${this.apiUrl}/${refundRequest.transactionId}/refund`,
      refundRequest
    );
  }

  cancelTransaction(transactionId: string): Observable<{ message: string }> {
    return this.http.post<{ message: string }>(
      `${this.apiUrl}/${transactionId}/cancel`,
      {}
    );
  }

  retryTransaction(transactionId: string): Observable<{ message: string; transaction: Transaction }> {
    return this.http.post<{ message: string; transaction: Transaction }>(
      `${this.apiUrl}/${transactionId}/retry`,
      {}
    );
  }

  // === STATISTIQUES ===
  getTransactionStats(query?: Partial<TransactionQuery>): Observable<TransactionStats> {
    let params = new HttpParams();
    
    if (query) {
      Object.keys(query).forEach(key => {
        const value = query[key as keyof TransactionQuery];
        if (value !== undefined && value !== null) {
          if (value instanceof Date) {
            params = params.set(key, value.toISOString());
          } else {
            params = params.set(key, value.toString());
          }
        }
      });
    }

    return this.http.get<TransactionStats>(`${this.apiUrl}/stats`, { params });
  }

  // === EXPORT ===
  exportTransactions(exportRequest: any): Observable<{ url: string; filename: string }> {
    return this.http.post<{ url: string; filename: string }>(
      `${this.apiUrl}/export`,
      exportRequest
    );
  }

  // === MOCK DATA POUR LE DÉVELOPPEMENT ===
  getMockTransactions(): Transaction[] {
    return [
      {
        id: 'tx_001',
        msisdn: '+33612345678',
        operator: 'Orange',
        operatorId: 'orange_fr',
        country: 'FR',
        amount: 4.99,
        currency: 'EUR',
        status: 'SUCCESS',
        productId: 'prod_premium',
        productName: 'Contenu Premium',
        productCategory: 'ENTERTAINMENT',
        transactionDate: new Date('2024-01-15T14:30:00'),
        createdAt: new Date('2024-01-15T14:30:00'),
        updatedAt: new Date('2024-01-15T14:30:00'),
        externalId: 'ext_123456',
        merchantName: 'MediaCorp'
      },
      {
        id: 'tx_002',
        msisdn: '+33798765432',
        operator: 'Free',
        operatorId: 'free_fr',
        country: 'FR',
        amount: 2.99,
        currency: 'EUR',
        status: 'PENDING',
        productId: 'prod_basic',
        productName: 'Abonnement Basique',
        productCategory: 'SUBSCRIPTION',
        transactionDate: new Date('2024-01-15T14:25:00'),
        createdAt: new Date('2024-01-15T14:25:00'),
        updatedAt: new Date('2024-01-15T14:25:00'),
        externalId: 'ext_123457'
      },
      {
        id: 'tx_003',
        msisdn: '+33687654321',
        operator: 'SFR',
        operatorId: 'sfr_fr',
        country: 'FR',
        amount: 9.99,
        currency: 'EUR',
        status: 'FAILED',
        productId: 'prod_pro',
        productName: 'Pack Professionnel',
        productCategory: 'BUSINESS',
        transactionDate: new Date('2024-01-15T14:20:00'),
        createdAt: new Date('2024-01-15T14:20:00'),
        updatedAt: new Date('2024-01-15T14:20:00'),
        errorCode: 'INSUFFICIENT_FUNDS',
        errorMessage: 'Solde insuffisant'
      },
      {
        id: 'tx_004',
        msisdn: '+33611223344',
        operator: 'Bouygues',
        operatorId: 'bouygues_fr',
        country: 'FR',
        amount: 1.99,
        currency: 'EUR',
        status: 'REFUNDED',
        productId: 'prod_mini',
        productName: 'Pack Découverte',
        productCategory: 'GAMING',
        transactionDate: new Date('2024-01-15T14:15:00'),
        createdAt: new Date('2024-01-15T14:15:00'),
        updatedAt: new Date('2024-01-15T16:30:00'),
        merchantName: 'GameStudio'
      }
    ];
  }
}