<?php
declare(strict_types=1);

namespace App\Modules\Shipments;

use PDO;

final class DeliveryStatusMappingRepository
{
    public function __construct(private readonly PDO $pdo)
    {
    }

    /**
     * @return array<int, array{provider: string, raw_status: string, normalized_status: string, description: string}>
     */
    public function listByProvider(string $provider): array
    {
        $provider = strtolower(trim($provider));
        if ($provider === '') {
            return [];
        }

        $statement = $this->pdo->prepare(
            'SELECT provider, raw_status, normalized_status, description
            FROM delivery_status_mappings
            WHERE provider = :provider
            ORDER BY raw_status ASC'
        );
        $statement->execute(['provider' => $provider]);
        $rows = $statement->fetchAll(PDO::FETCH_ASSOC);
        if (!is_array($rows)) {
            return [];
        }

        return array_map(static function (array $row): array {
            return [
                'provider' => (string) ($row['provider'] ?? ''),
                'raw_status' => (string) ($row['raw_status'] ?? ''),
                'normalized_status' => (string) ($row['normalized_status'] ?? ''),
                'description' => (string) ($row['description'] ?? ''),
            ];
        }, $rows);
    }

    public function upsertMapping(string $provider, string $rawStatus, string $normalizedStatus, string $description): void
    {
        $provider = strtolower(trim($provider));
        $rawStatus = trim($rawStatus);
        if ($provider === '' || $rawStatus === '') {
            return;
        }

        $statement = $this->pdo->prepare(
            'INSERT INTO delivery_status_mappings (provider, raw_status, normalized_status, description, created_at, updated_at)
            VALUES (:provider, :raw_status, :normalized_status, :description, NOW(), NOW())
            ON DUPLICATE KEY UPDATE
                normalized_status = VALUES(normalized_status),
                description = VALUES(description),
                updated_at = NOW()'
        );
        $statement->execute([
            'provider' => $provider,
            'raw_status' => $rawStatus,
            'normalized_status' => $normalizedStatus,
            'description' => $description,
        ]);
    }

    public function deleteMapping(string $provider, string $rawStatus): void
    {
        $provider = strtolower(trim($provider));
        $rawStatus = trim($rawStatus);
        if ($provider === '' || $rawStatus === '') {
            return;
        }

        $statement = $this->pdo->prepare(
            'DELETE FROM delivery_status_mappings WHERE provider = :provider AND raw_status = :raw_status'
        );
        $statement->execute([
            'provider' => $provider,
            'raw_status' => $rawStatus,
        ]);
    }

    public function deleteAllByProvider(string $provider): void
    {
        $provider = strtolower(trim($provider));
        if ($provider === '') {
            return;
        }

        $statement = $this->pdo->prepare(
            'DELETE FROM delivery_status_mappings WHERE provider = :provider'
        );
        $statement->execute(['provider' => $provider]);
    }

    /**
     * @return array<string, array{normalized_status: string, description: string}>
     */
    public function getAllOverrides(): array
    {
        $statement = $this->pdo->query(
            'SELECT provider, raw_status, normalized_status, description FROM delivery_status_mappings'
        );
        $rows = $statement->fetchAll(PDO::FETCH_ASSOC);
        if (!is_array($rows)) {
            return [];
        }

        $result = [];
        foreach ($rows as $row) {
            $key = ((string) ($row['provider'] ?? '')) . ':' . ((string) ($row['raw_status'] ?? ''));
            $result[$key] = [
                'normalized_status' => (string) ($row['normalized_status'] ?? ''),
                'description' => (string) ($row['description'] ?? ''),
            ];
        }

        return $result;
    }
}
