<?php

declare(strict_types=1);



class AdminAlbumController
{
    public static function routes(): void
    {
        Router::get('/admin/albums', [self::class, 'index']);
        Router::get('/admin/albums/create', [self::class, 'create']);
        Router::post('/admin/albums/store', [self::class, 'store']);
        Router::get('/admin/albums/{id}/edit', [self::class, 'edit']);
        Router::post('/admin/albums/{id}/update', [self::class, 'update']);
        Router::post('/admin/albums/{id}/delete', [self::class, 'destroy']);
        Router::post('/admin/albums/bulk-delete', [self::class, 'bulkDelete']);
        Router::post('/admin/albums/{id}/translations', [self::class, 'saveTranslations']);
        EntityTranslateAdmin::routes('album', 'albums', self::class);
    }

    public static function aiTranslateInit(): void   { EntityTranslateAdmin::init('album'); }
    public static function aiTranslateStart(): void  { EntityTranslateAdmin::start('album'); }
    public static function aiTranslateStatus(): void { EntityTranslateAdmin::status('album'); }
    public static function aiTranslateCancel(): void { EntityTranslateAdmin::cancel('album'); }
    public static function aiTranslatePause(): void  { EntityTranslateAdmin::pause('album'); }
    public static function aiTranslateResume(): void { EntityTranslateAdmin::resume('album'); }
    public static function aiTranslateRetry(): void  { EntityTranslateAdmin::retry('album'); }
    public static function aiTranslateAuto(): void   { EntityTranslateAdmin::auto('album'); }

    public static function index(): void
    {
        Auth::requireAdmin();
        $search = $_GET['q'] ?? '';
        $status = $_GET['status'] ?? '';
        $categoryId = !empty($_GET['category']) ? (int) $_GET['category'] : 0;
        $performerId = !empty($_GET['performer']) ? (int) $_GET['performer'] : 0;
        $sort = $_GET['sort'] ?? 'newest';

        $typeRows = Database::fetchAll('SELECT video_type, COUNT(*) as cnt FROM albums GROUP BY video_type ORDER BY ' . Video::typeFieldOrder());
        $availableTypes = array_column($typeRows, 'video_type');
        $showTypeFilter = count($availableTypes) > 1;
        $typeFilter = '';
        if ($showTypeFilter) {
            $typeFilter = $_GET['type'] ?? '';
            if ($typeFilter !== '' && !in_array($typeFilter, Album::VALID_TYPES, true)) {
                $typeFilter = '';
            }
        }

        $filters = ['admin' => true];
        if ($search !== '') $filters['search'] = $search;
        if ($status !== '') $filters['status'] = $status;
        if ($categoryId > 0) $filters['category_id'] = $categoryId;
        if ($performerId > 0) $filters['performer_id'] = $performerId;
        if ($sort !== 'newest') $filters['sort'] = $sort;
        if ($typeFilter !== '') $filters['video_type'] = $typeFilter;

        $total = Album::count($filters);
        $pagination = Pagination::fromRequest($total, 100);
        $albums = Album::all($filters, $pagination->perPage, $pagination->offset);

         
        $albumTranslations = [];
        $albumIds = array_column($albums, 'id');
        if (!empty($albumIds)) {
            $ph = implode(',', array_fill(0, count($albumIds), '?'));
            foreach (Database::fetchAll("SELECT album_id, lang_code, title FROM album_translations WHERE album_id IN ({$ph}) ORDER BY album_id, lang_code", $albumIds) as $tr) {
                $albumTranslations[(int) $tr['album_id']][$tr['lang_code']] = $tr['title'];
            }
        }

        Router::render('admin/albums', [
            'pageTitle' => 'Albums',
            'headerExtra' => EntityTranslateAdmin::headerButtons('album'),
            'activeMenu' => 'albums',
            'contentTemplate' => '_albums',
            'headerAction' => ['url' => '/admin/albums/create', 'label' => 'New Album'],
            'albums' => $albums,
            'pagination' => $pagination,
            'search' => $search,
            'filterCategories' => Database::fetchAll('SELECT id, name FROM categories ORDER BY name ASC'),
            'filterPerformers' => Database::fetchAll('SELECT id, name FROM performers ORDER BY name ASC'),
            'currentStatus' => $status,
            'currentCategory' => $categoryId,
            'currentPerformer' => $performerId,
            'currentSort' => $sort,
            'showTypeFilter' => $showTypeFilter,
            'availableTypes' => $availableTypes,
            'currentType' => $typeFilter,
            'albumTranslations' => $albumTranslations,
        ]);
    }

    public static function create(): void
    {
        Auth::requireAdmin();
        Router::render('admin/album_form', [
            'pageTitle' => 'New Album',
            'activeMenu' => 'albums',
            'contentTemplate' => '_album_form',
            'album' => null,
            'albumImages' => [],
            'categories' => AlbumCategory::all(),
            'tags' => AlbumTag::all(),
            'performers' => AlbumPerformer::all(1000, 0),
            'channels' => AlbumChannel::all(1000, 0),
            'selectedCategories' => [],
            'selectedTags' => [],
            'selectedPerformers' => [],
            'selectedChannels' => [],
            'error' => null,
        ]);
    }

    public static function store(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) {
            $_SESSION['flash'] = ['type' => 'error', 'message' => 'Your session has expired. Please refresh and try again.'];
            Router::redirect('/admin/albums/create');
        }

        $title = trim($_POST['title'] ?? '');
        if ($title === '') {
            $_SESSION['flash'] = ['type' => 'error', 'message' => 'Title is required.'];
            Router::redirect('/admin/albums/create');
        }

        $hasUploads = !empty($_FILES['images']) && is_array($_FILES['images']['tmp_name'] ?? null)
            && count(array_filter($_FILES['images']['error'] ?? [], fn($e) => $e === UPLOAD_ERR_OK)) > 0;
        if ($hasUploads && MediaStorage::isAllFull()) {
            $_SESSION['flash'] = ['type' => 'error', 'message' => 'All storage servers are full. Add more storage before uploading.'];
            Router::redirect('/admin/albums/create');
            return;
        }

        $folder = AlbumAsset::createFolder();
        $sid = MediaStorage::activeDefaultId() ?: null;
        $images = self::processImages($folder, $sid, []);
        [$cover, $cw, $ch] = self::resolveCover($images, $_POST['cover_file'] ?? '');

        $data = [
            'title' => $title,
            'slug' => Slug::fromInput('albums', $_POST['slug'] ?? '', $title),
            'description' => trim($_POST['description'] ?? ''),
            'video_type' => in_array($_POST['video_type'] ?? '', Album::VALID_TYPES, true) ? $_POST['video_type'] : Album::DEFAULT_TYPE,
            'status' => in_array($_POST['status'] ?? '', ['draft', 'published', 'private'], true) ? $_POST['status'] : 'draft',
            'is_featured' => !empty($_POST['is_featured']) ? 1 : 0,
            'views' => max(0, (int) ($_POST['views'] ?? 0)),
            'likes' => max(0, (int) ($_POST['likes'] ?? 0)),
            'dislikes' => max(0, (int) ($_POST['dislikes'] ?? 0)),
            'user_id' => Auth::id(),
            'album_folder' => $folder,
            'storage_id' => $sid,
            'images' => json_encode($images),
            'image_count' => count($images),
            'cover_file' => $cover,
            'cover_width' => $cw,
            'cover_height' => $ch,
        ];
        if ($data['status'] === 'published') {
            $data['published_at'] = date('Y-m-d H:i:s');
        }

        $albumId = Album::create($data);

        Album::syncCategories($albumId, $_POST['categories'] ?? []);
        Album::syncTags($albumId, $_POST['tags'] ?? []);
        Album::syncPerformers($albumId, $_POST['performers'] ?? []);
        Album::syncChannels($albumId, $_POST['channels'] ?? []);

        HookSystem::doAction('album.created', $albumId);
        $_SESSION['flash'] = ['type' => 'success', 'message' => 'Album created successfully.'];
        SitemapController::markDirty();
        Router::redirect('/admin/albums');
    }

    public static function edit(): void
    {
        Auth::requireAdmin();
        $id = (int) Router::param('id');
        $album = Album::find($id);
        if (!$album) {
            $_SESSION['flash'] = ['type' => 'error', 'message' => 'Album not found.'];
            Router::redirect('/admin/albums');
        }

        $translations = Database::fetchAll('SELECT lang_code, title, description FROM album_translations WHERE album_id = ?', [$id]);
        $translationMap = [];
        foreach ($translations as $tr) {
            $translationMap[$tr['lang_code']] = $tr;
        }

        Router::render('admin/album_form', [
            'pageTitle' => 'Edit Album',
            'activeMenu' => 'albums',
            'contentTemplate' => '_album_form',
            'album' => $album,
            'albumImages' => AlbumAsset::imageUrls($album),
            'categories' => AlbumCategory::all(),
            'tags' => AlbumTag::all(),
            'performers' => AlbumPerformer::all(1000, 0),
            'channels' => AlbumChannel::all(1000, 0),
            'selectedCategories' => array_column($album['categories'], 'id'),
            'selectedTags' => array_column($album['tags'], 'id'),
            'selectedPerformers' => array_column($album['performers'], 'id'),
            'selectedChannels' => array_column($album['channels'] ?? [], 'id'),
            'albumTranslations' => $translationMap,
            'albumLanguages' => Translator::available(),
            'defaultLang' => Translator::getDefaultCode(),
            'error' => null,
        ]);
    }

    public static function update(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) {
            Router::redirect('/admin/albums');
        }
        $id = (int) Router::param('id');
        $album = Album::find($id);
        if (!$album) {
            Router::redirect('/admin/albums');
        }

        $folder = $album['album_folder'] ?? '';
        if ($folder === '') {
            $folder = AlbumAsset::createFolder();
        }
        $sid = isset($album['storage_id']) ? (int) $album['storage_id'] : (MediaStorage::activeDefaultId() ?: null);

         
        $keep = json_decode($_POST['existing_images'] ?? '[]', true);
        if (!is_array($keep)) $keep = [];
         
        $keptFiles = array_filter(array_map(fn($im) => is_array($im) ? ($im['f'] ?? '') : '', $keep));
        foreach (Album::images($album) as $im) {
            $f = $im['f'] ?? '';
            if ($f !== '' && !str_starts_with($f, 'http') && !in_array($f, $keptFiles, true)) {
                AlbumAsset::deleteImage($folder, $f, $sid);
            }
        }

        $images = self::processImages($folder, $sid, $keep);
        [$cover, $cw, $chH] = self::resolveCover($images, $_POST['cover_file'] ?? ($album['cover_file'] ?? ''));

        $data = [
            'title' => trim($_POST['title'] ?? ''),
            'slug' => Slug::fromInput('albums', $_POST['slug'] ?? '', $_POST['title'] ?? '', $id),
            'description' => trim($_POST['description'] ?? ''),
            'video_type' => in_array($_POST['video_type'] ?? '', Album::VALID_TYPES, true) ? $_POST['video_type'] : Album::DEFAULT_TYPE,
            'status' => in_array($_POST['status'] ?? '', ['draft', 'published', 'private'], true) ? $_POST['status'] : 'draft',
            'is_featured' => !empty($_POST['is_featured']) ? 1 : 0,
            'views' => max(0, (int) ($_POST['views'] ?? $album['views'])),
            'likes' => max(0, (int) ($_POST['likes'] ?? $album['likes'])),
            'dislikes' => max(0, (int) ($_POST['dislikes'] ?? $album['dislikes'])),
            'album_folder' => $folder,
            'storage_id' => $sid,
            'images' => json_encode($images),
            'image_count' => count($images),
            'cover_file' => $cover,
            'cover_width' => $cw,
            'cover_height' => $chH,
        ];
        if ($data['status'] === 'published' && empty($album['published_at'])) {
            $data['published_at'] = date('Y-m-d H:i:s');
        }

        Album::update($id, $data);
        Album::syncCategories($id, $_POST['categories'] ?? []);
        Album::syncTags($id, $_POST['tags'] ?? []);
        Album::syncPerformers($id, $_POST['performers'] ?? []);
        Album::syncChannels($id, $_POST['channels'] ?? []);

        $_SESSION['flash'] = ['type' => 'success', 'message' => 'Album updated successfully.'];
        SitemapController::markDirty();
        Router::redirect('/admin/albums');
    }

    public static function destroy(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) {
            Router::redirect('/admin/albums');
        }
        Album::delete((int) Router::param('id'));
        $_SESSION['flash'] = ['type' => 'success', 'message' => 'Album deleted successfully.'];
        SitemapController::markDirty();
        Router::redirect('/admin/albums');
    }

    public static function bulkDelete(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) {
            Router::json(['error' => 'Invalid CSRF token'], 403);
            return;
        }
        $input = json_decode(file_get_contents('php://input'), true) ?: [];
        $ids = array_filter(array_map('intval', $input['ids'] ?? []), fn($id) => $id > 0);

        // Batched, and honest: the count comes from what the database actually removed, and storage
        // is purged per batch instead of one request per image - a gallery can hold hundreds.
        $result = BulkDelete::run($ids, static function (array $batch): int {
            $r = Album::deleteMany($batch);
            foreach (Album::assetPaths($r['assets']) as $storageId => $paths) {
                MediaStorage::deleteRemoteKeys($paths, $storageId > 0 ? $storageId : null);
            }
            foreach ($r['assets'] as $album) {
                $folder = (string) ($album['album_folder'] ?? '');
                if ($folder !== '') AlbumAsset::purgeLocalFolder($folder);
            }
            return (int) $r['deleted'];
        }, 100);

        $_SESSION['flash'] = ['type' => 'success', 'message' => BulkDelete::message($result, 'album', 'albums')];
        SitemapController::markDirty();
        Router::json(BulkDelete::payload($result));
    }

    public static function saveTranslations(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) {
            Router::json(['error' => 'Invalid CSRF token'], 403);
        }
        $id = (int) Router::param('id');
        $input = json_decode(file_get_contents('php://input'), true) ?: [];
        $translations = $input['translations'] ?? [];

        foreach ($translations as $langCode => $fields) {
            $langCode = preg_replace('/[^a-z]/', '', strtolower($langCode));
            if ($langCode === '' || strlen($langCode) > 5) continue;

            $title = mb_substr(trim($fields['title'] ?? ''), 0, 500);
            $description = trim($fields['description'] ?? '');

            if ($title === '') {
                Database::query('DELETE FROM album_translations WHERE album_id = ? AND lang_code = ?', [$id, $langCode]);
            } else {
                $slug = Slug::uniqueEntityTranslation('album_translations', 'album_id', 'albums', $title, $langCode, $id);
                $existing = Database::fetchOne('SELECT id FROM album_translations WHERE album_id = ? AND lang_code = ?', [$id, $langCode]);
                if ($existing) {
                    Database::query('UPDATE album_translations SET title = ?, slug = ?, description = ? WHERE album_id = ? AND lang_code = ?', [$title, $slug, $description, $id, $langCode]);
                } else {
                    Database::query('INSERT INTO album_translations (album_id, lang_code, title, slug, description) VALUES (?, ?, ?, ?, ?)', [$id, $langCode, $title, $slug, $description]);
                }
            }
        }
        SitemapController::markDirty();
        Router::json(['success' => true]);
    }

    

    private static function processImages(string $folder, ?int $sid, array $keep): array
    {
        $list = [];
        foreach ($keep as $im) {
            $f = is_array($im) ? ($im['f'] ?? '') : (is_string($im) ? $im : '');
            if ($f === '') continue;
            $list[] = ['f' => $f, 'w' => $im['w'] ?? null, 'h' => $im['h'] ?? null];
        }

        if (!empty($_FILES['images']) && is_array($_FILES['images']['tmp_name'] ?? null)) {
            $n = count($_FILES['images']['tmp_name']);
            for ($i = 0; $i < $n; $i++) {
                if (($_FILES['images']['error'][$i] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) continue;
                $tmp = $_FILES['images']['tmp_name'][$i];
                $dim = @getimagesize($tmp) ?: [null, null];
                $fn = AlbumAsset::saveUploadedImage($folder, $tmp, $_FILES['images']['name'][$i] ?? 'image.jpg', $sid);
                if ($fn !== '') {
                    $list[] = ['f' => $fn, 'w' => $dim[0] ?? null, 'h' => $dim[1] ?? null];
                }
            }
        }

        $urls = trim($_POST['image_urls'] ?? '');
        if ($urls !== '') {
            foreach (preg_split('/\s+/', $urls) as $u) {
                $u = trim($u);
                if ($u !== '' && (str_starts_with($u, 'http://') || str_starts_with($u, 'https://'))) {
                    $list[] = ['f' => $u, 'w' => null, 'h' => null];
                }
            }
        }
        return $list;
    }

     
    private static function resolveCover(array $images, string $requested): array
    {
        if (empty($images)) return ['', null, null];
        $cover = $images[0];
        if ($requested !== '') {
            foreach ($images as $im) {
                if (($im['f'] ?? '') === $requested) {
                    $cover = $im;
                    break;
                }
            }
        }
        return [$cover['f'] ?? '', $cover['w'] ?? null, $cover['h'] ?? null];
    }
}
