<?php

declare(strict_types=1);

namespace App\Models;

use App\Core\BaseModel;

final class TagModel extends BaseModel
{
    protected string $table = 'tags';
    protected array $fillable = ['name', 'slug', 'color_hex'];
    protected bool $timestamps = false;
    protected bool $softDeletes = false;
    protected bool $auditStamps = false;

    public function all(array $where = [], string $orderBy = 'name ASC', ?int $limit = null): array
    {
        return parent::all($where, $orderBy, $limit);
    }

    public function findOrCreateByName(string $name): int
    {
        $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '-', $name), '-'));

        $stmt = $this->db->prepare('SELECT id FROM tags WHERE slug = :slug');
        $stmt->execute(['slug' => $slug]);
        $id = $stmt->fetchColumn();

        if ($id !== false) {
            return (int) $id;
        }

        return $this->insert(['name' => $name, 'slug' => $slug]);
    }

    public function attach(int $tagId, string $entityType, int $entityId): bool
    {
        $stmt = $this->db->prepare(
            'INSERT IGNORE INTO taggables (tag_id, entity_type, entity_id) VALUES (:tag, :type, :id)'
        );

        return $stmt->execute(['tag' => $tagId, 'type' => $entityType, 'id' => $entityId]);
    }

    public function detach(int $tagId, string $entityType, int $entityId): bool
    {
        $stmt = $this->db->prepare(
            'DELETE FROM taggables WHERE tag_id = :tag AND entity_type = :type AND entity_id = :id'
        );

        return $stmt->execute(['tag' => $tagId, 'type' => $entityType, 'id' => $entityId]);
    }

    public function forEntity(string $entityType, int $entityId): array
    {
        $stmt = $this->db->prepare(
            'SELECT t.* FROM tags t
             JOIN taggables tg ON tg.tag_id = t.id
             WHERE tg.entity_type = :type AND tg.entity_id = :id
             ORDER BY t.name'
        );
        $stmt->execute(['type' => $entityType, 'id' => $entityId]);

        return $stmt->fetchAll();
    }

    /** Every entity id of a given type carrying a given tag — used to filter e.g. "leads tagged 'VIP'". */
    public function entityIdsWithTag(int $tagId, string $entityType): array
    {
        $stmt = $this->db->prepare('SELECT entity_id FROM taggables WHERE tag_id = :tag AND entity_type = :type');
        $stmt->execute(['tag' => $tagId, 'type' => $entityType]);

        return $stmt->fetchAll(\PDO::FETCH_COLUMN);
    }
}
