import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BaseTenantRepository, TenantContextService } from '@iconsulting/shared';
import { IPaymentRepository } from '../../../domain/repositories/payment.repository.interface';
import { PaymentEntity, PaymentStatus } from '../../../domain/entities/payment.entity';
import { PaymentORM } from '../../../infrastructure/database/postgres/entities/payment.orm';

@Injectable()
export class PaymentPostgresRepository
  extends BaseTenantRepository<PaymentEntity, PaymentORM>
  implements IPaymentRepository
{
  constructor(
    @InjectRepository(PaymentORM) repo: Repository<PaymentORM>,
    tenantContext: TenantContextService,
  ) {
    super(repo, tenantContext);
  }

  async save(payment: PaymentEntity): Promise<PaymentEntity> {
    const orm = this.toORM(payment);
    orm.tenantId = this.getTenantId();
    const saved = await this.repo.save(orm);
    return this.toEntity(saved);
  }

  async findById(id: string): Promise<PaymentEntity | null> {
    const orm = await this.findOneWithTenant({ id } as any);
    return orm ? this.toEntity(orm) : null;
  }

  async findPendingByOrderId(orderId: string): Promise<PaymentEntity | null> {
    const orm = await this.findOneWithTenant({ orderId, status: PaymentStatus.PENDING } as any);
    return orm ? this.toEntity(orm) : null;
  }

  async findByTransactionId(transactionId: string): Promise<PaymentEntity | null> {
    const orm = await this.findOneWithTenant({ transactionId } as any);
    return orm ? this.toEntity(orm) : null;
  }

  async update(payment: PaymentEntity): Promise<PaymentEntity> {
    const orm = this.toORM(payment);
    orm.tenantId = this.getTenantId();
    const saved = await this.repo.save(orm);
    return this.toEntity(saved);
  }

  private toORM(entity: PaymentEntity): PaymentORM {
    const orm = new PaymentORM();
    orm.id = entity.id;
    orm.tenantId = this.getTenantId();
    orm.orderId = entity.orderId;
    orm.method = entity.method;
    orm.amount = entity.amount;
    orm.currency = entity.currency;
    orm.status = entity.status;
    orm.transactionId = entity.transactionId;
    orm.qrCodeUrl = entity.qrCodeUrl;
    orm.paymentUrl = entity.paymentUrl;
    orm.expiresAt = entity.expiresAt;
    orm.paidAt = entity.paidAt;
    orm.failedReason = entity.failedReason;
    orm.callbackPayload = entity.callbackPayload;
    orm.createdAt = entity.createdAt;
    orm.updatedAt = entity.updatedAt;
    return orm;
  }

  private toEntity(orm: PaymentORM): PaymentEntity {
    return PaymentEntity.fromPersistence({
      id: orm.id,
      orderId: orm.orderId,
      method: orm.method,
      amount: Number(orm.amount),
      currency: orm.currency,
      status: orm.status,
      transactionId: orm.transactionId,
      qrCodeUrl: orm.qrCodeUrl,
      paymentUrl: orm.paymentUrl,
      expiresAt: orm.expiresAt,
      paidAt: orm.paidAt,
      failedReason: orm.failedReason,
      callbackPayload: orm.callbackPayload,
      createdAt: orm.createdAt,
      updatedAt: orm.updatedAt,
    });
  }
}
