<?php

namespace App\Services\Tax;

use App\Models\Customer;

/**
 * The register, for tests.
 *
 * Answers UNAVAILABLE for anything it was not told about, which is deliberately
 * the awkward default: a test that forgets to arm a number finds out, instead of
 * quietly proving that an unchecked number earns a reverse charge.
 */
final class FakeVatIdVerifier implements VatIdVerifier
{
    /** @var array<string, VatIdCheck> */
    private array $answers = [];

    /** @var array<int, string> every number that was asked about, in order */
    public array $asked = [];

    public function registered(string $vatId, ?string $name = null): self
    {
        $this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::valid($name);

        return $this;
    }

    public function notRegistered(string $vatId): self
    {
        $this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::invalid();

        return $this;
    }

    /** The register is down — the case that must never clear a verification. */
    public function down(string $vatId): self
    {
        $this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::unavailable('test');

        return $this;
    }

    public function check(string $vatId): VatIdCheck
    {
        $normalised = Customer::normaliseVatId($vatId);

        // Refused before it is recorded as asked, exactly as the real verifier
        // refuses before it spends a request. Without this the fake would answer
        // where VIES would never have been consulted, and a test could prove the
        // opposite of what the product does.
        if (! VatIdShape::verifiable($normalised)) {
            return VatIdCheck::invalid();
        }

        $this->asked[] = $normalised;

        return $this->answers[$normalised] ?? VatIdCheck::unavailable('not armed in this test');
    }
}
