<?php

declare(strict_types=1);

namespace App\Models;

use App\Core\Database;

/**
 * Accès aux images de galerie pour le back-office.
 */
final class ImageRepository
{
    /** @return list<array<string,mixed>> */
    public static function listFor(int $galleryId): array
    {
        $pdo  = Database::connection();
        $stmt = $pdo->prepare('SELECT * FROM gallery_images WHERE gallery_id = :gid ORDER BY sort_order ASC, id ASC');
        $stmt->execute(['gid' => $galleryId]);
        return $stmt->fetchAll();
    }

    /**
     * Une image publiée au hasard, dont la galerie est elle-même publiée
     * (illustration de la page de contact). @return array<string,mixed>|null
     */
    public static function randomPublished(): ?array
    {
        $pdo  = Database::connection();
        $stmt = $pdo->query(
            "SELECT gi.gallery_id, gi.filename, gi.alt, gi.name
             FROM gallery_images gi
             JOIN galleries g ON g.id = gi.gallery_id
             WHERE gi.status = 'published' AND g.status = 'published'
             ORDER BY RAND() LIMIT 1"
        );
        $row = $stmt === false ? false : $stmt->fetch();
        return $row === false ? null : $row;
    }

    /** @return array<string,mixed>|null */
    public static function find(int $id): ?array
    {
        $pdo  = Database::connection();
        $stmt = $pdo->prepare('SELECT * FROM gallery_images WHERE id = :id');
        $stmt->execute(['id' => $id]);
        $row = $stmt->fetch();
        return $row === false ? null : $row;
    }

    public static function nextSortOrder(int $galleryId): int
    {
        $pdo  = Database::connection();
        $stmt = $pdo->prepare('SELECT COALESCE(MAX(sort_order), 0) FROM gallery_images WHERE gallery_id = :gid');
        $stmt->execute(['gid' => $galleryId]);
        return (int) $stmt->fetchColumn() + 1;
    }

    /** Garantit l'unicité du nom de fichier (base.jpg) dans la galerie. */
    public static function uniqueBase(int $galleryId, string $base): string
    {
        $pdo  = Database::connection();
        $candidate = $base !== '' ? $base : 'image';
        $n = 1;
        while (true) {
            $stmt = $pdo->prepare('SELECT id FROM gallery_images WHERE gallery_id = :gid AND filename = :file LIMIT 1');
            $stmt->execute(['gid' => $galleryId, 'file' => $candidate . '.jpg']);
            if ($stmt->fetchColumn() === false) {
                return $candidate;
            }
            $n++;
            $candidate = $base . '-' . $n;
        }
    }

    /** @param array<string,mixed> $data */
    public static function create(int $galleryId, array $data): int
    {
        $pdo  = Database::connection();
        $stmt = $pdo->prepare(
            "INSERT INTO gallery_images (gallery_id, name, alt, filename, original_name, width, height, sort_order, status)
             VALUES (:gid, :name, :alt, :file, :orig, :w, :h, :sort, :status)"
        );
        $stmt->execute([
            'gid'    => $galleryId,
            'name'   => $data['name'],
            'alt'    => $data['alt'],
            'file'   => $data['filename'],
            'orig'   => $data['original_name'],
            'w'      => $data['width'],
            'h'      => $data['height'],
            'sort'   => $data['sort_order'],
            'status' => $data['status'],
        ]);
        return (int) $pdo->lastInsertId();
    }

    /** @param array<string,mixed> $data */
    public static function update(int $id, array $data): void
    {
        $pdo  = Database::connection();
        $stmt = $pdo->prepare('UPDATE gallery_images SET name = :name, alt = :alt, status = :status WHERE id = :id');
        $stmt->execute([
            'name'   => $data['name'],
            'alt'    => $data['alt'],
            'status' => $data['status'],
            'id'     => $id,
        ]);
    }

    /** Met à jour le nom de fichier, les dimensions et le nom d'origine après remplacement. */
    public static function updateFile(int $id, string $filename, int $width, int $height, string $originalName): void
    {
        $pdo  = Database::connection();
        $stmt = $pdo->prepare('UPDATE gallery_images SET filename = :file, width = :w, height = :h, original_name = :orig WHERE id = :id');
        $stmt->execute(['file' => $filename, 'w' => $width, 'h' => $height, 'orig' => $originalName, 'id' => $id]);
    }

    /** Bascule du statut publié/masqué (AJAX). */
    public static function setStatus(int $id, string $status): void
    {
        $pdo = Database::connection();
        $pdo->prepare('UPDATE gallery_images SET status = :s WHERE id = :id')->execute(['s' => $status, 'id' => $id]);
    }

    public static function delete(int $id): void
    {
        $pdo = Database::connection();
        $pdo->prepare('DELETE FROM gallery_images WHERE id = :id')->execute(['id' => $id]);
    }

    /** Déplace une image d'un cran dans sa galerie (échange de sort_order). */
    public static function move(int $id, string $direction): void
    {
        $image = self::find($id);
        if ($image === null) {
            return;
        }
        $pdo = Database::connection();
        $cmp = $direction === 'up' ? '<' : '>';
        $ord = $direction === 'up' ? 'DESC' : 'ASC';

        $stmt = $pdo->prepare(
            "SELECT id, sort_order FROM gallery_images
             WHERE gallery_id = :gid AND sort_order {$cmp} :order
             ORDER BY sort_order {$ord} LIMIT 1"
        );
        $stmt->execute(['gid' => $image['gallery_id'], 'order' => $image['sort_order']]);
        $neighbour = $stmt->fetch();
        if ($neighbour === false) {
            return;
        }

        $upd = $pdo->prepare('UPDATE gallery_images SET sort_order = :order WHERE id = :id');
        $upd->execute(['order' => $neighbour['sort_order'], 'id' => $id]);
        $upd->execute(['order' => $image['sort_order'], 'id' => $neighbour['id']]);
    }

    /**
     * Réordonne les images d'une galerie selon la liste d'ids (position 1..n).
     * @param list<int> $ids
     */
    public static function reorder(int $galleryId, array $ids): void
    {
        $pdo  = Database::connection();
        $stmt = $pdo->prepare('UPDATE gallery_images SET sort_order = :order WHERE id = :id AND gallery_id = :gid');
        $position = 1;
        foreach ($ids as $id) {
            $stmt->execute(['order' => $position, 'id' => (int) $id, 'gid' => $galleryId]);
            $position++;
        }
    }
}
