import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';

import { environment } from '../../../environments/environment';

export interface CreatePurchasePayload {
  cart_id: number;
  dni: string;
  telefono: string;
  nombre_apellido: string;
  email: string;
}

export interface PurchaseStatusResponse {
  status: string | null;
}

export interface PurchaseSummaryResponse extends PurchaseStatusResponse {
  id: number;
  created_at: string | null;
  total: string;
}

export interface PurchaseDetailAttributeResponse {
  name: string;
  value: string | null;
}

export interface PurchaseDetailItemResponse {
  id: number;
  quantity: number;
  unit_price: string;
  line_total: string;
  product: {
    id: number;
    nombre: string;
    slug: string;
    imagen: string | null;
  } | null;
  variant: {
    id: number;
    attributes: PurchaseDetailAttributeResponse[];
  } | null;
}

export interface PurchaseDetailResponse extends PurchaseStatusResponse {
  id: number;
  cart_id: number | null;
  tenant_codigo: string;
  user_id: number;
  created_at: string | null;
  payment_method: string | null;
  dni: string | null;
  telefono: string | null;
  nombre_apellido: string | null;
  email: string | null;
  items_source: 'purchase' | 'cart' | null;
  items: PurchaseDetailItemResponse[];
  subtotal: string;
  total: string;
}

@Injectable({
  providedIn: 'root'
})
export class CheckoutService {
  private readonly http = inject(HttpClient);

  async createPurchase(tenantCode: string, payload: CreatePurchasePayload): Promise<{ id: number }> {
    const response = await firstValueFrom(
      this.http.post<{ data?: { id: number }; id?: number }>(`${environment.url}tenants/${tenantCode}/compras`, payload)
    );

    const purchase = this.extractResponseData<{ id: number }>(response);

    if (!purchase?.id) {
      throw new Error('Error al crear la compra.');
    }

    return purchase;
  }

  async generatePaymentIntent(tenantCode: string, purchaseId: number, method: 'qr' | 'transfer' | 'telepagos'): Promise<any> {
    const response = await firstValueFrom(
      this.http.post<any>(`${environment.url}tenants/${tenantCode}/compras/${purchaseId}/payment-intent`, { method })
    );
    if (!response) {
      throw new Error('Error al generar la intención de pago.');
    }
    return response;
  }

  async completePurchase(tenantCode: string, purchaseId: number): Promise<PurchaseStatusResponse> {
    const response = await firstValueFrom(
      this.http.post<{ data?: PurchaseStatusResponse } | PurchaseStatusResponse>(`${environment.url}tenants/${tenantCode}/compras/${purchaseId}/complete`, {})
    );

    const purchase = this.extractResponseData<PurchaseStatusResponse>(response);

    if (!purchase) {
      throw new Error('Error al finalizar la compra.');
    }

    return {
      status: purchase.status ?? null
    };
  }

  async getPurchases(tenantCode: string, status?: string): Promise<{ data: PurchaseSummaryResponse[] }> {
    let url = `${environment.url}tenants/${tenantCode}/compras`;
    if (status) {
      url += `?status=${status}`;
    }
    const response = await firstValueFrom(
      this.http.get<{ data: PurchaseSummaryResponse[] }>(url)
    );
    if (!response) {
      throw new Error('Error al obtener las compras.');
    }
    return response;
  }

  async getPurchase(tenantCode: string, purchaseId: string | number): Promise<PurchaseDetailResponse> {
    const response = await firstValueFrom(
      this.http.get<{ data?: PurchaseDetailResponse } | PurchaseDetailResponse>(`${environment.url}tenants/${tenantCode}/compras/${purchaseId}`)
    );

    const purchase = this.extractResponseData<PurchaseDetailResponse>(response);

    if (!purchase) {
      throw new Error('Error al obtener la compra.');
    }

    return purchase;
  }

  private extractResponseData<T>(response: T | { data?: T } | null | undefined): T | null {
    if (!response) {
      return null;
    }

    if (typeof response === 'object' && 'data' in response && response.data) {
      return response.data;
    }

    return response as T;
  }
}
