<?php
declare(strict_types=1);

namespace App\Modules\Settings;

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

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

    /**
     * @return array<int, array{allegro_status_code:string,allegro_status_name:string,orderpro_status_code:string}>
     */
    public function listAll(): array
    {
        $statement = $this->pdo->query(
            'SELECT allegro_status_code, allegro_status_name, orderpro_status_code
            FROM allegro_order_status_pull_mappings
            ORDER BY allegro_status_code ASC'
        );
        $rows = $statement->fetchAll(PDO::FETCH_ASSOC);

        if (!is_array($rows)) {
            return [];
        }

        $result = [];
        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }

            $allegroCode = strtolower(trim((string) ($row['allegro_status_code'] ?? '')));
            if ($allegroCode === '') {
                continue;
            }

            $result[] = [
                'allegro_status_code' => $allegroCode,
                'allegro_status_name' => trim((string) ($row['allegro_status_name'] ?? '')),
                'orderpro_status_code' => strtolower(trim((string) ($row['orderpro_status_code'] ?? ''))),
            ];
        }

        return $result;
    }

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

        $statement = $this->pdo->prepare(
            'SELECT orderpro_status_code
            FROM allegro_order_status_pull_mappings
            WHERE allegro_status_code = :allegro_status_code
              AND orderpro_status_code IS NOT NULL
              AND orderpro_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;
    }

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

        $existing = $this->pdo->prepare(
            'SELECT id FROM allegro_order_status_pull_mappings
            WHERE allegro_status_code = :allegro_status_code
            LIMIT 1'
        );
        $existing->execute(['allegro_status_code' => $code]);

        if ($existing->fetchColumn() !== false) {
            if ($allegroStatusName !== null && trim($allegroStatusName) !== '') {
                $update = $this->pdo->prepare(
                    'UPDATE allegro_order_status_pull_mappings
                    SET allegro_status_name = :allegro_status_name,
                        updated_at = NOW()
                    WHERE allegro_status_code = :allegro_status_code
                      AND (allegro_status_name IS NULL OR allegro_status_name = "")'
                );
                $update->execute([
                    'allegro_status_name' => trim($allegroStatusName),
                    'allegro_status_code' => $code,
                ]);
            }
            return;
        }

        $insert = $this->pdo->prepare(
            'INSERT INTO allegro_order_status_pull_mappings (
                allegro_status_code, allegro_status_name, orderpro_status_code, created_at, updated_at
            ) VALUES (
                :allegro_status_code, :allegro_status_name, NULL, NOW(), NOW()
            )'
        );
        $insert->execute([
            'allegro_status_code' => $code,
            'allegro_status_name' => StringHelper::nullableString((string) $allegroStatusName),
        ]);
    }

    /**
     * @param array<int, array{allegro_status_code:string,allegro_status_name:string,orderpro_status_code:string}> $mappings
     */
    public function replaceAll(array $mappings): void
    {
        $this->pdo->exec('DELETE FROM allegro_order_status_pull_mappings');

        if ($mappings === []) {
            return;
        }

        $insertStatement = $this->pdo->prepare(
            'INSERT INTO allegro_order_status_pull_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()
            )'
        );

        foreach ($mappings as $mapping) {
            $allegroCode = strtolower(trim((string) ($mapping['allegro_status_code'] ?? '')));
            if ($allegroCode === '') {
                continue;
            }

            $orderpro = strtolower(trim((string) ($mapping['orderpro_status_code'] ?? '')));
            $allegroName = trim((string) ($mapping['allegro_status_name'] ?? ''));

            $insertStatement->execute([
                'allegro_status_code' => $allegroCode,
                'allegro_status_name' => $allegroName !== '' ? $allegroName : null,
                'orderpro_status_code' => $orderpro !== '' ? $orderpro : null,
            ]);
        }
    }
}
