<?php

declare(strict_types=1);

namespace App\Services;

use App\Repositories\ArticleRepository;
use App\Repositories\ClientRepository;
use App\Repositories\TarifClientRepository;

final class TarifClientService extends BaseService
{
    public function __construct(
        private readonly TarifClientRepository $tarifs = new TarifClientRepository(),
        private readonly ClientRepository $clients = new ClientRepository(),
        private readonly ArticleRepository $articles = new ArticleRepository(),
    ) {
    }

    public function clientTarifs(int $clientId): array
    {
        $this->ensureClientExists($clientId);
        return $this->tarifs->allForClient($clientId);
    }

    public function formDataForClient(int $clientId): array
    {
        $this->ensureClientExists($clientId);

        return [
            'tarifs' => $this->tarifs->allForClient($clientId),
            'articles' => $this->articles->allActive(),
        ];
    }

    public function saveForClient(array $data): int
    {
        $clientId = (int) ($data['client_id'] ?? 0);
        $articleId = (int) ($data['article_id'] ?? 0);
        $prixHt = $this->toFloat($data['prix_ht'] ?? 0);

        $this->ensureClientExists($clientId);

        if ($articleId <= 0) {
            throw new \RuntimeException('Veuillez sélectionner un article.');
        }
        if (!$this->articleExists($articleId)) {
            throw new \RuntimeException('Article introuvable.');
        }
        if ($prixHt <= 0) {
            throw new \RuntimeException('Le prix client doit être supérieur à zéro.');
        }

        $this->tarifs->save($clientId, $articleId, $prixHt);
        return $clientId;
    }

    public function deleteForClient(int $id, int $clientId): void
    {
        $this->ensureClientExists($clientId);
        if ($id <= 0) {
            throw new \RuntimeException('Tarif invalide.');
        }

        $this->tarifs->deactivate($id, $clientId);
    }


    public function getPrixClient(int $clientId, int $articleId, float $prixArticleHt = 0): float
    {
        if ($clientId <= 0 || $articleId <= 0) {
            return $prixArticleHt;
        }

        $prixClient = $this->tarifs->priceForClientAndArticle($clientId, $articleId);

        return $prixClient !== null ? $prixClient : $prixArticleHt;
    }

    public function documentTarifsMap(): array
    {
        return $this->tarifs->allActiveForDocuments();
    }

    private function ensureClientExists(int $clientId): void
    {
        if ($clientId <= 0 || !$this->clients->find($clientId)) {
            throw new \RuntimeException('Client introuvable.');
        }
    }

    private function articleExists(int $articleId): bool
    {
        foreach ($this->articles->allActive() as $article) {
            if ((int) ($article['id'] ?? 0) === $articleId) {
                return true;
            }
        }
        return false;
    }

    private function toFloat(mixed $value): float
    {
        if (is_string($value)) {
            $value = str_replace([' ', ','], ['', '.'], $value);
        }
        return (float) $value;
    }
}
