<?php
namespace Domain\Scontainers;

class ScontainersRepository
{
    private const MAX_PER_PAGE = 100;

    private $db;

    public function __construct($db)
    {
        $this->db = $db;
    }

    /**
     * @return array{items: array<int, array<string, mixed>>, total: int}
     */
    public function listForAdmin(
        array $filters,
        string $sortColumn = 'id',
        string $sortDir = 'DESC',
        int $page = 1,
        int $perPage = 15
    ): array {
        $allowedSortColumns = [
            'id' => 'q1.id',
            'title' => 'q1.title',
            'status' => 'q1.status',
        ];

        $sortSql = $allowedSortColumns[$sortColumn] ?? 'q1.id';
        $sortDir = strtoupper(trim($sortDir)) === 'ASC' ? 'ASC' : 'DESC';
        $page = max(1, $page);
        $perPage = min(self::MAX_PER_PAGE, max(1, $perPage));
        $offset = ($page - 1) * $perPage;

        $where = ['1 = 1'];
        $params = [];

        $title = trim((string)($filters['title'] ?? ''));
        if ($title !== '') {
            if (strlen($title) > 255) {
                $title = substr($title, 0, 255);
            }
            $where[] = 'q1.title LIKE :title';
            $params[':title'] = '%' . $title . '%';
        }

        $status = trim((string)($filters['status'] ?? ''));
        if ($status === '0' || $status === '1') {
            $where[] = 'q1.status = :status';
            $params[':status'] = (int)$status;
        }

        $whereSql = implode(' AND ', $where);
        $baseSelect = $this->baseListSelect();

        $sqlCount = "
            SELECT COUNT(0)
            FROM ({$baseSelect}) AS q1
            WHERE {$whereSql}
        ";

        $stmtCount = $this->db->query($sqlCount, $params);
        $countRows = $stmtCount ? $stmtCount->fetchAll() : [];
        $total = isset($countRows[0][0]) ? (int)$countRows[0][0] : 0;

        $sql = "
            SELECT q1.*
            FROM ({$baseSelect}) AS q1
            WHERE {$whereSql}
            ORDER BY {$sortSql} {$sortDir}, q1.id DESC
            LIMIT {$perPage} OFFSET {$offset}
        ";

        $stmt = $this->db->query($sql, $params);
        $items = $stmt ? $stmt->fetchAll() : [];

        return [
            'items' => is_array($items) ? $items : [],
            'total' => $total,
        ];
    }

    public function find(int $containerId): array
    {
        if ($containerId <= 0) {
            return $this->defaultContainer();
        }

        $container = $this->db->get('pp_scontainers', '*', ['id' => $containerId]);
        if (!is_array($container)) {
            return $this->defaultContainer();
        }

        $container['languages'] = $this->translationsMap($containerId);
        return $container;
    }

    public function detailsForLanguage(int $containerId, string $langId): ?array
    {
        if ($containerId <= 0 || trim($langId) === '') {
            return null;
        }

        $container = $this->db->get('pp_scontainers', '*', ['id' => $containerId]);
        if (!is_array($container)) {
            return null;
        }

        $translation = $this->db->get('pp_scontainers_langs', '*', [
            'AND' => [
                'container_id' => $containerId,
                'lang_id' => $langId,
            ],
        ]);

        $container['languages'] = is_array($translation) ? $translation : [
            'lang_id' => $langId,
            'title' => '',
            'text' => '',
        ];

        return $container;
    }

    public function save(array $data): ?int
    {
        $containerId = (int)($data['id'] ?? 0);
        $status = $this->toSwitchValue($data['status'] ?? 0);
        $showTitle = $this->toSwitchValue($data['show_title'] ?? 0);
        $translations = $this->extractTranslations($data);

        if ($containerId <= 0) {
            $this->db->insert('pp_scontainers', [
                'status' => $status,
                'show_title' => $showTitle,
            ]);
            $containerId = (int)$this->db->id();
            if ($containerId <= 0) {
                return null;
            }
        } else {
            $this->db->update('pp_scontainers', [
                'status' => $status,
                'show_title' => $showTitle,
            ], [
                'id' => $containerId,
            ]);
        }

        foreach ($translations as $langId => $row) {
            $translationId = $this->db->get('pp_scontainers_langs', 'id', [
                'AND' => [
                    'container_id' => $containerId,
                    'lang_id' => $langId,
                ],
            ]);

            if ($translationId) {
                $this->db->update('pp_scontainers_langs', [
                    'title' => (string)($row['title'] ?? ''),
                    'text' => (string)($row['text'] ?? ''),
                ], [
                    'id' => (int)$translationId,
                ]);
            } else {
                $this->db->insert('pp_scontainers_langs', [
                    'container_id' => $containerId,
                    'lang_id' => $langId,
                    'title' => (string)($row['title'] ?? ''),
                    'text' => (string)($row['text'] ?? ''),
                ]);
            }
        }

        \Shared\Helpers\Helpers::delete_dir('../temp/');
        $this->clearFrontCache($containerId);

        return $containerId;
    }

    public function delete(int $containerId): bool
    {
        if ($containerId <= 0) {
            return false;
        }

        $result = (bool)$this->db->delete('pp_scontainers', ['id' => $containerId]);
        if ($result) {
            $this->clearFrontCache($containerId);
        }

        return $result;
    }

    private function baseListSelect(): string
    {
        return "
            SELECT
                ps.id,
                ps.status,
                (
                    SELECT psl.title
                    FROM pp_scontainers_langs AS psl
                    JOIN pp_langs AS pl ON psl.lang_id = pl.id
                    WHERE psl.container_id = ps.id
                        AND psl.title <> ''
                    ORDER BY pl.o ASC
                    LIMIT 1
                ) AS title
            FROM pp_scontainers AS ps
        ";
    }

    private function clearFrontCache(int $containerId): void
    {
        if ($containerId <= 0 || !class_exists('\Shared\Cache\CacheHandler')) {
            return;
        }

        $cacheHandler = new \Shared\Cache\CacheHandler();
        $cacheKey = '\front\factory\Scontainers::scontainer_details:' . $containerId;
        $cacheHandler->delete($cacheKey);
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function translationsMap(int $containerId): array
    {
        $rows = $this->db->select('pp_scontainers_langs', '*', ['container_id' => $containerId]);
        if (!is_array($rows)) {
            return [];
        }

        $result = [];
        foreach ($rows as $row) {
            $langId = (string)($row['lang_id'] ?? '');
            if ($langId !== '') {
                $result[$langId] = $row;
            }
        }

        return $result;
    }

    /**
     * @return array<string, array<string, string>>
     */
    private function extractTranslations(array $data): array
    {
        $translations = [];

        if (isset($data['translations']) && is_array($data['translations'])) {
            foreach ($data['translations'] as $langId => $row) {
                if (!is_array($row)) {
                    continue;
                }

                $safeLangId = trim((string)$langId);
                if ($safeLangId === '') {
                    continue;
                }

                $translations[$safeLangId] = [
                    'title' => (string)($row['title'] ?? ''),
                    'text' => (string)($row['text'] ?? ''),
                ];
            }
        }

        $legacyTitles = isset($data['title']) && is_array($data['title']) ? $data['title'] : [];
        $legacyTexts = isset($data['text']) && is_array($data['text']) ? $data['text'] : [];

        foreach ($legacyTitles as $langId => $title) {
            $safeLangId = trim((string)$langId);
            if ($safeLangId === '') {
                continue;
            }

            if (!isset($translations[$safeLangId])) {
                $translations[$safeLangId] = [
                    'title' => '',
                    'text' => '',
                ];
            }

            $translations[$safeLangId]['title'] = (string)$title;
            $translations[$safeLangId]['text'] = (string)($legacyTexts[$safeLangId] ?? '');
        }

        return $translations;
    }

    private function toSwitchValue($value): int
    {
        return ($value === 'on' || $value === 1 || $value === '1' || $value === true) ? 1 : 0;
    }

    private function defaultContainer(): array
    {
        return [
            'id' => 0,
            'status' => 1,
            'show_title' => 0,
            'languages' => [],
        ];
    }
}

