<?php
declare(strict_types=1);

namespace App\Modules\Settings;

use App\Core\Support\StringHelper;
use PDO;

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

    /**
     * @return array<int, array<string, mixed>>
     */
    public function listMappings(): array
    {
        $statement = $this->pdo->query(
            'SELECT id, allegro_status_code, allegro_status_name, orderpro_status_code, created_at, updated_at
            FROM allegro_order_status_mappings
            ORDER BY allegro_status_code ASC'
        );
        $rows = $statement->fetchAll(PDO::FETCH_ASSOC);
        if (!is_array($rows)) {
            return [];
        }

        return array_map(static function (array $row): array {
            return [
                'id' => (int) ($row['id'] ?? 0),
                'allegro_status_code' => strtolower(trim((string) ($row['allegro_status_code'] ?? ''))),
                'allegro_status_name' => trim((string) ($row['allegro_status_name'] ?? '')),
                'orderpro_status_code' => strtolower(trim((string) ($row['orderpro_status_code'] ?? ''))),
                'created_at' => (string) ($row['created_at'] ?? ''),
                'updated_at' => (string) ($row['updated_at'] ?? ''),
            ];
        }, $rows);
    }

    public function upsertMapping(string $allegroStatusCode, ?string $allegroStatusName, ?string $orderproStatusCode): void
    {
        $code = strtolower(trim($allegroStatusCode));
        $orderproCode = $orderproStatusCode !== null ? strtolower(trim($orderproStatusCode)) : null;
        if ($code === '') {
            return;
        }

        $statement = $this->pdo->prepare(
            'INSERT INTO allegro_order_status_mappings (
                allegro_status_code, allegro_status_name, orderpro_status_code, created_at, updated_at
            ) VALUES (
                :allegro_status_code, :allegro_status_name, :orderpro_status_code, NOW(), NOW()
            )
            ON DUPLICATE KEY UPDATE
                allegro_status_name = VALUES(allegro_status_name),
                orderpro_status_code = VALUES(orderpro_status_code),
                updated_at = VALUES(updated_at)'
        );
        $statement->execute([
            'allegro_status_code' => $code,
            'allegro_status_name' => StringHelper::nullableString((string) $allegroStatusName),
            'orderpro_status_code' => $orderproCode !== null && $orderproCode !== '' ? $orderproCode : null,
        ]);
    }

    public function upsertDiscoveredStatus(string $allegroStatusCode, ?string $allegroStatusName): void
    {
        $code = strtolower(trim($allegroStatusCode));
        if ($code === '') {
            return;
        }

        $statement = $this->pdo->prepare(
            'INSERT INTO allegro_order_status_mappings (
                allegro_status_code, allegro_status_name, orderpro_status_code, created_at, updated_at
            ) VALUES (
                :allegro_status_code, :allegro_status_name, NULL, NOW(), NOW()
            )
            ON DUPLICATE KEY UPDATE
                allegro_status_name = CASE
                    WHEN VALUES(allegro_status_name) IS NULL OR VALUES(allegro_status_name) = "" THEN allegro_status_name
                    ELSE VALUES(allegro_status_name)
                END,
                updated_at = VALUES(updated_at)'
        );
        $statement->execute([
            'allegro_status_code' => $code,
            'allegro_status_name' => StringHelper::nullableString((string) $allegroStatusName),
        ]);
    }

    public function deleteMappingById(int $id): void
    {
        if ($id <= 0) {
            return;
        }

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

    public function findMappedOrderproStatusCode(string $allegroStatusCode): ?string
    {
        $code = strtolower(trim($allegroStatusCode));
        if ($code === '') {
            return null;
        }

        $statement = $this->pdo->prepare(
            'SELECT orderpro_status_code
            FROM allegro_order_status_mappings
            WHERE allegro_status_code = :allegro_status_code
            LIMIT 1'
        );
        $statement->execute(['allegro_status_code' => $code]);
        $value = $statement->fetchColumn();
        if (!is_string($value)) {
            return null;
        }

        $mapped = strtolower(trim($value));
        return $mapped !== '' ? $mapped : null;
    }

    /**
     * @return array<string, string> orderpro_status_code => allegro_status_code
     */
    public function buildOrderproToAllegroMap(): array
    {
        $statement = $this->pdo->query(
            'SELECT allegro_status_code, orderpro_status_code
            FROM allegro_order_status_mappings
            WHERE orderpro_status_code IS NOT NULL
              AND orderpro_status_code <> ""
            ORDER BY id ASC'
        );
        $rows = $statement->fetchAll(PDO::FETCH_ASSOC);
        if (!is_array($rows)) {
            return [];
        }

        $map = [];
        foreach ($rows as $row) {
            $orderproCode = strtolower(trim((string) ($row['orderpro_status_code'] ?? '')));
            $allegroCode = strtolower(trim((string) ($row['allegro_status_code'] ?? '')));
            if ($orderproCode === '' || $allegroCode === '') {
                continue;
            }

            if (!isset($map[$orderproCode])) {
                $map[$orderproCode] = $allegroCode;
            }
        }

        return $map;
    }

}
