<?php

namespace App\PaymentMethod\Repository;

use App\Auth\Entity\User;
use App\PaymentMethod\Entity\Pos;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class PosRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Pos::class);
    }

    public function findByUuid(string $uuid): ?Pos
    {
        return $this->findOneBy(['uuid' => $uuid]);
    }

    /** @return Pos[] */
    public function findByEntity(string $entityType, int $entityId): array
    {
        return $this->createQueryBuilder('p')
            ->where('p.entityType = :type')->setParameter('type', $entityType)
            ->andWhere('p.entityId = :id')->setParameter('id', $entityId)
            ->orderBy('p.createdAt', 'DESC')
            ->getQuery()
            ->getResult();
    }

    /**
     * قرینهٔ {@see BankAccountRepository::findUnassignedByUser()} — و به همان دلیل
     * DBAL است: ردیف بی‌محیط از DQL برنمی‌گردد چون فیلتر شرط تساوی می‌گذارد.
     *
     * شکل خروجی باید با {@see Pos::toArray()} یکی بماند.
     *
     * @return array<int, array<string, mixed>>
     */
    public function findUnassignedByUser(User $user): array
    {
        $rows = $this->getEntityManager()->getConnection()->fetchAllAssociative(
            'SELECT uuid, bank_name, serial_number, terminal_number, account_number, is_active, created_at
             FROM pos_devices
             WHERE user_id = ? AND (entity_type IS NULL OR entity_id IS NULL)
             ORDER BY created_at DESC',
            [$user->getId()],
        );

        return array_map(static fn (array $r) => [
            'uuid'            => $r['uuid'],
            'bank_name'       => $r['bank_name'],
            'serial_number'   => $r['serial_number'],
            'terminal_number' => $r['terminal_number'],
            'account_number'  => $r['account_number'],
            'is_active'       => (bool) $r['is_active'],
            'created_at'      => (int) $r['created_at'],
            'entity_type'     => null,
        ], $rows);
    }

    /** @see BankAccountRepository::assignEntity() */
    public function assignEntity(string $uuid, User $user, string $entityType, int $entityId): bool
    {
        return $this->getEntityManager()->getConnection()->executeStatement(
            'UPDATE pos_devices SET entity_type = ?, entity_id = ?, updated_at = ?
             WHERE uuid = ? AND user_id = ? AND (entity_type IS NULL OR entity_id IS NULL)',
            [$entityType, $entityId, time(), $uuid, $user->getId()],
        ) > 0;
    }

    /** @see BankAccountRepository::reloadByUuid() */
    public function reloadByUuid(string $uuid): ?Pos
    {
        $pos = $this->findByUuid($uuid);
        if ($pos !== null) {
            $this->getEntityManager()->refresh($pos);
        }

        return $pos;
    }

    public function save(Pos $entity, bool $flush = true): void
    {
        $this->getEntityManager()->persist($entity);
        if ($flush) $this->getEntityManager()->flush();
    }
}
