<?php

declare(strict_types=1);

class Performer
{
    public static function find(int $id): ?array
    {
        return Database::fetchOne('SELECT * FROM performers WHERE id = ?', [$id]);
    }

    public static function findBySlug(string $slug): ?array
    {
        $vt = Video::activeType();
        $locale = Translator::locale();
        $defaultLang = Translator::getDefaultCode();

         
        if ($locale !== $defaultLang) {
            $q = 'SELECT pt.performer_id FROM performer_translations pt
                  JOIN performers p ON pt.performer_id = p.id
                  WHERE pt.slug = ? AND pt.lang_code = ?';
            $p = [$slug, $locale];
            if ($vt !== '') { $q .= ' AND p.video_type = ?'; $p[] = $vt; }
            $trans = Database::fetchOne($q, $p);
            if ($trans) {
                $perf = self::find((int) $trans['performer_id']);
                return $perf ? self::localize($perf) : null;
            }
        }

         
        $q = 'SELECT * FROM performers WHERE slug = ?';
        $p = [$slug];
        if ($vt !== '') { $q .= ' AND video_type = ?'; $p[] = $vt; }
        $perf = Database::fetchOne($q, $p);

         
        if (!$perf && $vt !== '') {
            $perf = Database::fetchOne('SELECT * FROM performers WHERE slug = ?', [$slug]);
        }

        return $perf ? self::localize($perf) : null;
    }

    public static function all(string $search = '', int $limit = 24, int $offset = 0, string $sort = 'alphabetical', string $videoType = '', bool $onlyPopulated = false): array
    {
        $override = HookSystem::applyFilter('performer.listing', null, $search, $limit, $offset, $sort, $videoType, $onlyPopulated);
        if ($override !== null && $override !== []) {
            VideoAsset::assignUniqueThumbFolders($override, 'video_performers', 'performer_id', 'photo');
            return self::localizeResults($override);
        }

        $orderBy = match ($sort) {
            'popularity' => 'p.total_views DESC, p.name ASC',
            default => 'p.name ASC',
        };

        $conditions = [];
        $params = [];
        if ($search !== '') {
            if (mb_strlen($search) >= 3) {
                $conditions[] = 'MATCH(p.name) AGAINST(? IN BOOLEAN MODE)';
                $params[] = $search;
            } else {
                $conditions[] = 'p.name LIKE ?';
                $params[] = $search . '%';
            }
        }
        if ($videoType !== '') {
            $conditions[] = 'p.video_type = ?';
            $params[] = $videoType;
        }
         
        if ($onlyPopulated) { $conditions[] = 'p.video_count > 0'; }
        $where = !empty($conditions) ? ' WHERE ' . implode(' AND ', $conditions) : '';

        $params[] = $limit;
        $params[] = $offset;

        $results = Database::fetchAll(
            "SELECT p.* FROM performers p{$where} ORDER BY {$orderBy} LIMIT ? OFFSET ?",
            $params
        );
        VideoAsset::assignUniqueThumbFolders($results, 'video_performers', 'performer_id', 'photo');
        return self::localizeResults($results);
    }

    public static function count(string $search = '', string $videoType = '', bool $onlyPopulated = false): int
    {
        $where = [];
        $params = [];
        if ($search !== '') {
            if (mb_strlen($search) >= 3) {
                $where[] = 'MATCH(name) AGAINST(? IN BOOLEAN MODE)';
                $params[] = $search;
            } else {
                $where[] = 'name LIKE ?';
                $params[] = $search . '%';
            }
        }
        if ($videoType !== '') {
            $where[] = 'video_type = ?';
            $params[] = $videoType;
        }
        if ($onlyPopulated) { $where[] = 'video_count > 0'; }
        if (!empty($where)) {
            return Database::count('performers', implode(' AND ', $where), $params);
        }
        return Database::count('performers');
    }

    public static function create(array $data): int
    {
        return Database::insert('performers', $data);
    }

    public static function update(int $id, array $data): void
    {
        Database::update('performers', $data, 'id = ?', [$id]);
    }

    public static function delete(int $id): void
    {
        Database::delete('performers', 'id = ?', [$id]);
    }

    

    public static function updateCounts(int $id): void
    {
        $row = Database::fetchOne(
            "SELECT COUNT(*) as cnt, COALESCE(SUM(v.views), 0) as tv
             FROM video_performers vp
             JOIN videos v ON vp.video_id = v.id
             WHERE vp.performer_id = ? AND v.status = 'published'",
            [$id]
        );
        Database::update('performers', [
            'video_count' => (int) ($row['cnt'] ?? 0),
            'total_views' => (int) ($row['tv'] ?? 0),
        ], 'id = ?', [$id]);
    }

    

    public static function recalcAllCounts(): void
    {
        Database::query(
            "UPDATE performers p LEFT JOIN (
                SELECT vp.performer_id, COUNT(*) as cnt, COALESCE(SUM(v.views), 0) as tv
                FROM video_performers vp
                JOIN videos v ON vp.video_id = v.id AND v.status = 'published'
                GROUP BY vp.performer_id
            ) agg ON p.id = agg.performer_id
            SET p.video_count = COALESCE(agg.cnt, 0),
                p.total_views = COALESCE(agg.tv, 0)"
        );
    }

    

    public static function translations(int $performerId): array
    {
        $rows = Database::fetchAll(
            'SELECT lang_code, name, slug, bio FROM performer_translations WHERE performer_id = ? ORDER BY lang_code',
            [$performerId]
        );
        $result = [];
        foreach ($rows as $row) {
            $result[$row['lang_code']] = $row;
        }
        return $result;
    }

    

    public static function localize(?array $performer): ?array
    {
        if ($performer === null || Translator::locale() === Translator::getDefaultCode()) {
            return $performer;
        }

        $row = Database::fetchOne(
            'SELECT name, slug, bio FROM performer_translations WHERE performer_id = ? AND lang_code = ?',
            [(int) $performer['id'], Translator::locale()]
        );

        if ($row) {
            if ($row['name'] !== null && $row['name'] !== '') {
                $performer['name'] = $row['name'];
            }
            if ($row['slug'] !== null && $row['slug'] !== '') {
                $performer['slug'] = $row['slug'];
            }
            if ($row['bio'] !== null && $row['bio'] !== '') {
                $performer['bio'] = $row['bio'];
            }
        }

        return $performer;
    }

    

    public static function localizeResults(array $performers): array
    {
        if (empty($performers) || Translator::locale() === Translator::getDefaultCode()) {
            return $performers;
        }

        $ids = array_column($performers, 'id');
        if (empty($ids)) {
            return $performers;
        }

        $placeholders = implode(',', array_fill(0, count($ids), '?'));
        $params = array_merge([Translator::locale()], $ids);

        $rows = Database::fetchAll(
            "SELECT performer_id, name, slug, bio FROM performer_translations WHERE lang_code = ? AND performer_id IN ({$placeholders})",
            $params
        );

        $map = [];
        foreach ($rows as $row) {
            $map[(int) $row['performer_id']] = $row;
        }

        foreach ($performers as &$perf) {
            $pid = (int) $perf['id'];
            if (isset($map[$pid])) {
                $tr = $map[$pid];
                if ($tr['name'] !== null && $tr['name'] !== '') {
                    $perf['name'] = $tr['name'];
                }
                if ($tr['slug'] !== null && $tr['slug'] !== '') {
                    $perf['slug'] = $tr['slug'];
                }
                if ($tr['bio'] !== null && $tr['bio'] !== '') {
                    $perf['bio'] = $tr['bio'];
                }
            }
        }
        unset($perf);

        return $performers;
    }
}
