<?php

declare(strict_types=1);

trait AnimalPhotoActions
{
    public static function uploadPhoto(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
            http_response_code(405);
            echo h(t('error.method_not_allowed'));
            return;
        }

        $id = (int) ($_POST['animal_id'] ?? 0);
        if ($id <= 0) {
            http_response_code(400);
            echo h(t('error.bad_request'));
            return;
        }

        if (!isset($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) {
            http_response_code(400);
            echo h(t('error.upload_failed'));
            return;
        }

        $db = DB::pdo();

        $tmp = $_FILES['photo']['tmp_name'];
        $orig = (string) ($_FILES['photo']['name'] ?? 'photo');
        $size = (int) ($_FILES['photo']['size'] ?? 0);
        $mime = (string) ($_FILES['photo']['type'] ?? '');

        $base = preg_replace('/[^a-zA-Z0-9._-]+/', '_', pathinfo($orig, PATHINFO_FILENAME));
        $base = $base ?: 'photo';
        $dir = __DIR__ . '/../../public/media/animals/' . $id;
        try {
            $stored = ImageService::storeUploaded($tmp, $dir, $base, 'photo');
            $filename = $stored['filename'];
            $mime = $stored['mime'];
            $size = $stored['size'];
        } catch (Throwable $e) {
            http_response_code(400);
            echo h($e->getMessage());
            return;
        }

        // si aucune photo primaire, celle-ci devient primaire
        $stmt = $db->prepare('SELECT COUNT(*) FROM animal_photos WHERE animal_id=:id AND is_primary=1');
        $stmt->execute([':id' => $id]);
        $hasPrimary = (int) $stmt->fetchColumn() > 0;

        $stmt = $db->prepare('
        INSERT INTO animal_photos(animal_id, filename, original_name, mime, size_bytes, is_primary)
        VALUES(:aid,:fn,:orig,:mime,:sz,:prim)
        ');
        $stmt->execute([
            ':aid' => $id,
            ':fn' => $filename,
            ':orig' => $orig,
            ':mime' => $mime,
            ':sz' => $size,
            ':prim' => $hasPrimary ? 0 : 1,
        ]);

        header('Location: /animal?id=' . $id);
        exit();
    }

    public static function uploadPhotos(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
            http_response_code(405);
            return;
        }

        $animalId = (int) ($_POST['animal_id'] ?? 0);
        if ($animalId <= 0) {
            http_response_code(400);
            echo h(t('error.bad_request'));
            return;
        }

        if (empty($_FILES['photos'])) {
            http_response_code(400);
            echo h(t('error.no_files'));
            return;
        }

        $isPublic = (int) ($_POST['is_public'] ?? 1 ? 1 : 0);
        $redirectHash = trim((string) ($_POST['redirect_hash'] ?? ''));

        $db = DB::pdo();
        self::ensureAnimalMediaDir($animalId);

        $files = $_FILES['photos'];
        $count = is_array($files['name']) ? count($files['name']) : 1;

        // Y a-t-il déjà une photo principale ?
        $hasPrimary = (bool) $db
            ->query(
                '
        SELECT 1 FROM animal_photos
        WHERE animal_id=' .
                    (int) $animalId .
                    '
        AND is_primary=1
        LIMIT 1
        ',
            )
            ->fetchColumn();

        for ($i = 0; $i < $count; $i++) {
            $name = is_array($files['name']) ? $files['name'][$i] : $files['name'];
            $tmp = is_array($files['tmp_name']) ? $files['tmp_name'][$i] : $files['tmp_name'];
            $err = is_array($files['error']) ? $files['error'][$i] : $files['error'];

            if ($err !== UPLOAD_ERR_OK) {
                continue;
            }
            if (!is_uploaded_file($tmp)) {
                continue;
            }
            if (!self::isAllowedImage($tmp)) {
                continue;
            }

            $base = self::safeFilename(pathinfo($name, PATHINFO_FILENAME));
            $targetDir = $isPublic === 1 ? self::animalMediaDir($animalId) : PrivateMediaService::animalDir($animalId);
            if ($isPublic === 0) {
                PrivateMediaService::ensure($targetDir);
            }
            try {
                $stored = ImageService::storeUploaded($tmp, $targetDir, $base, 'photo');
                $final = $stored['filename'];
                if ($isPublic === 0) {
                    @chmod($stored['path'], 0600);
                }
            } catch (Throwable) {
                continue;
            }

            // RÈGLE : jamais une privée en principale
            $isPrimary = !$hasPrimary && $isPublic === 1 ? 1 : 0;
            if ($isPrimary === 1) {
                $hasPrimary = true;
            }

            $st = $db->prepare('
            INSERT INTO animal_photos(animal_id, filename, is_primary, is_public)
            VALUES(:aid,:fn,:p,:pub)
            ');
            $st->execute([
                ':aid' => $animalId,
                ':fn' => $final,
                ':p' => $isPrimary,
                ':pub' => $isPublic,
            ]);
        }

        $db->prepare(
            "
        UPDATE animals
        SET updated_at=datetime('now')
        WHERE id=:id
        ",
        )->execute([':id' => $animalId]);

        // Retour direct sur onglet photos
        $hash = $redirectHash !== '' && $redirectHash[0] === '#' ? $redirectHash : '';
        header('Location: /animal?id=' . $animalId . $hash);
        exit();
    }

    public static function setPrimaryPhoto(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
            http_response_code(405);
            return;
        }

        $animalId = (int) ($_POST['animal_id'] ?? 0);
        $photoId = (int) ($_POST['photo_id'] ?? 0);
        if ($animalId <= 0 || $photoId <= 0) {
            http_response_code(400);
            return;
        }

        $db = DB::pdo();
        $stmt = $db->prepare('SELECT filename,is_public FROM animal_photos WHERE id=:pid AND animal_id=:aid');
        $stmt->execute([':pid' => $photoId, ':aid' => $animalId]);
        $photo = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$photo) {
            http_response_code(404);
            echo h(t('error.photo_not_found'));
            return;
        }
        $moved = false;
        try {
            if ((int) $photo['is_public'] !== 1) {
                PrivateMediaService::moveVisibility($animalId, (string) $photo['filename'], true);
                $moved = true;
            }
            $db->beginTransaction();
            $db->prepare('UPDATE animal_photos SET is_primary=0 WHERE animal_id=:aid')->execute([':aid' => $animalId]);
            $db->prepare('UPDATE animal_photos SET is_primary=1,is_public=1 WHERE id=:pid AND animal_id=:aid')->execute(
                [':pid' => $photoId, ':aid' => $animalId],
            );
            $db->commit();
        } catch (Throwable $e) {
            if ($db->inTransaction()) {
                $db->rollBack();
            }
            if ($moved) {
                try {
                    PrivateMediaService::moveVisibility($animalId, (string) $photo['filename'], false);
                } catch (Throwable) {
                }
            }
            throw $e;
        }

        // Historique si tu veux
        if (method_exists(__CLASS__, 'logHistory')) {
            self::logHistory($animalId, 'photo', 'Photo principale modifiée');
        }

        header('Location: /animal?id=' . $animalId);
        exit();
    }

    public static function deletePhoto(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
            http_response_code(405);
            return;
        }

        $animalId = (int) ($_POST['animal_id'] ?? 0);
        $photoId = (int) ($_POST['photo_id'] ?? 0);
        if ($animalId <= 0 || $photoId <= 0) {
            http_response_code(400);
            return;
        }

        $db = DB::pdo();

        $st = $db->prepare(
            'SELECT filename, is_primary, is_public FROM animal_photos WHERE id=:pid AND animal_id=:aid',
        );
        $st->execute([':pid' => $photoId, ':aid' => $animalId]);
        $row = $st->fetch(PDO::FETCH_ASSOC);
        if (!$row) {
            header('Location: /animal?id=' . $animalId);
            exit();
        }

        $filename = (string) $row['filename'];
        $wasPrimary = (int) $row['is_primary'] === 1;

        $db->prepare('DELETE FROM animal_photos WHERE id=:pid AND animal_id=:aid')->execute([
            ':pid' => $photoId,
            ':aid' => $animalId,
        ]);

        $path =
            ((int) ($row['is_public'] ?? 1) === 1
                ? self::animalMediaDir($animalId)
                : PrivateMediaService::animalDir($animalId)) .
            '/' .
            $filename;
        if (is_file($path)) {
            @unlink($path);
        }

        // Si on a supprimé la principale, on met la plus récente restante en principale
        if ($wasPrimary) {
            $pid = $db
                ->query('SELECT id FROM animal_photos WHERE animal_id=' . (int) $animalId . ' ORDER BY id DESC LIMIT 1')
                ->fetchColumn();
            if ($pid) {
                $db->prepare('UPDATE animal_photos SET is_primary=1 WHERE id=:pid')->execute([':pid' => (int) $pid]);
            }
        }

        $db->prepare("UPDATE animals SET updated_at=datetime('now') WHERE id=:id")->execute([':id' => $animalId]);

        if (method_exists(__CLASS__, 'logHistory')) {
            self::logHistory($animalId, 'photo', 'Photo supprimée');
        }

        header('Location: /animal?id=' . $animalId);
        exit();
    }
}
