<?php

namespace app\foreignone\files;

use engine\Model;
use engine\SphinxUtil;

class BaconianaIssue
    extends Model
    implements FileInterface
{
    const DB_TABLE = 'baconiana_collection';

    public int $id;
    public int $parentId;
    public int $year;
    public string $issues;
    public string $path;
    public bool $jobc; // Journal of the Bacon Society
    public string $title; // Only for folders
    public int $size;
    public string $type;

    public function getTitleHtml(): ?string {
        return null;
    }

    public function getTitle(): string {
        if ($this->title !== '')
            return $this->title;

        return ($this->jobc ? lang('baconiana_old_name') : lang('baconiana')).' №'.$this->issues;
    }

    public function isTargetBlank(): bool {
        return $this->type == 'file';
    }

    public function getId(): string {
        return $this->id;
    }

    public function getUrl(): string {
        if ($this->type == 'folder') {
            return '/files/'.ArchiveType::Baconiana->value.'/'.$this->id.'/';
        }
        global $config;
        return 'https://'.$config['files_domain'].'/'.$this->path;
    }

    public function getMeta(?string $hl_matched = null): array {
        $items = [];
        if ($this->type == 'folder')
            return $items;

        if ($this->year >= 2007) {
            $online_ed = 'Online Edition';
            if ($this->year >= 2024)
                $online_ed .= ', Vol. 2';
            $items = array_merge($items, [$online_ed]);
        }

        $items = array_merge($items, [
            sizeString($this->size),
            'PDF'
        ]);

        return [
            'inline' => false,
            'items' => $items
        ];
    }

    public function getSubtitle(): ?string {
        return $this->year > 0 ? '('.$this->year.')' : null;
    }

    public function getSize(): ?int {
        return $this->type == 'file' ? $this->size : null;
    }

    public function getIcon(): string {
        return $this->type;
    }

    public function getFullText(): ?string {
        $db = getDB();
        $q = $db->query("SELECT text FROM baconiana_texts WHERE bcn_id=?", $this->id);
        if (!$db->numRows($q))
            return null;
        return $db->result($q);
    }


    /**
     * Static methods
     */

    public static function add(string $path, int $size, string $issue, int $year, string $text): ?int {
        $db = getDB();
        if (!$db->insert(static::DB_TABLE, [
            'parent_id' => 0,
            'path' => $path,
            'issues' => $issue,
            'year' => $year,
            'size' => $size,
            'type' => 'file',
            'jobc' => 0,
            'title' => '',
        ])) {
            logError(__METHOD__.': failed to create new item');
            return null;
        }

        $id = $db->insertId();

        list($table, $id_field) = ArchiveType::Baconiana->getMySQLData();
        if (!$db->insert($table, [
            $id_field => $id,
            'text' => $text
        ])) {
            logError(__METHOD__.': failed to add item\'s text to database');
            $db->query("DELETE FROM ".static::DB_TABLE." WHERE id=?", $id);
            return null;
        }

        self::addToSphinx(self::get($id), $text);
        return $id;
    }

    public static function addToSphinx(BaconianaIssue $item, string $text): void {
        SphinxUtil::execute("INSERT INTO ".ArchiveType::Baconiana->getSphinxIndex()." (id, title, year, text) VALUES (?, ?, ?, ?)",
            $item->id, "$item->year ($item->issues)", $item->year, $text);
    }

    /**
     * @param int|null $parent_id
     * @return BaconianaIssue[]
     */
    public static function getList(?int $parent_id = 0): array {
        $db = getDB();
        $sql = "SELECT * FROM baconiana_collection";
        if ($parent_id !== null)
            $sql .= " WHERE parent_id='".$db->escape($parent_id)."'";
        $sql .= " ORDER BY type, year, id";
        $q = $db->query($sql);
        return array_map(static::create_instance(...), $db->fetchAll($q));
    }

    /**
     * @param int[] $ids
     * @return BaconianaIssue[]
     */
    public static function getIssuesById(array $ids): array {
        $db = getDB();
        $q = $db->query("SELECT * FROM baconiana_collection WHERE id IN (".implode(',', $ids).")");
        return array_map(static::create_instance(...), $db->fetchAll($q));
    }

    public static function get(int $id): ?BaconianaIssue {
        $db = getDB();
        $q = $db->query("SELECT * FROM baconiana_collection WHERE id=?", $id);
        return $db->numRows($q) ? new static($db->fetch($q)) : null;
    }

    /**
     * @param int $folder_id
     * @param bool $with_parents
     * @return BaconianaIssue|BaconianaIssue[]|null
     */
    public static function getFolder(int $folder_id, bool $with_parents = false): static|array|null {
        $db = getDB();
        $q = $db->query("SELECT * FROM baconiana_collection WHERE id=?", $folder_id);
        if (!$db->numRows($q))
            return null;
        $item = new BaconianaIssue($db->fetch($q));
        if ($item->type != 'folder')
            return null;
        if ($with_parents) {
            $items = [$item];
            if ($item->parentId) {
                $parents = static::getFolder($item->parentId, with_parents: true);
                if ($parents !== null)
                    $items = array_merge($items, $parents);
            }
            return $items;
        }
        return $item;
    }
}
