<?php

declare(strict_types=1);

namespace FecaMailshots\Application;

use FecaMailshots\Repository\PdfAssetRepository;

final class PdfAssetService
{
    private PdfAssetRepository $repo;

    public function __construct(PdfAssetRepository $repo)
    {
        $this->repo = $repo;
    }

    /** @return list<array<string, mixed>> */
    public function list(): array
    {
        return $this->repo->all();
    }

    /** @return array<string, mixed> */
    public function save(?int $id, array $payload): array
    {
        $name = trim((string) ($payload['name'] ?? ''));
        $fileName = trim((string) ($payload['file_name'] ?? ''));
        $mimeType = trim((string) ($payload['mime_type'] ?? ''));
        if ($mimeType === '') {
            $mimeType = $this->inferMimeTypeFromFilename($fileName);
        }
        $justification = trim((string) ($payload['justification'] ?? 'in-place'));
        $width = (float) ($payload['width_mm'] ?? 0);
        $height = (float) ($payload['height_mm'] ?? 0);
        $base64 = (string) ($payload['file_bytes_base64'] ?? '');

        $errors = [];
        if ($name === '') {
            $errors[] = 'name is required.';
        }
        if ($fileName === '') {
            $errors[] = 'file_name is required.';
        }
        if ($mimeType === '') {
            $errors[] = 'mime_type is required (or inferable from file_name).';
        }
        if ($width <= 0 || $height <= 0) {
            $errors[] = 'width_mm and height_mm must be > 0.';
        }
        if (!in_array($justification, ['left', 'right', 'in-place'], true)) {
            $errors[] = 'justification must be one of: left, right, in-place.';
        }

        $fileBytes = base64_decode($base64, true);
        if ($base64 === '' || $fileBytes === false) {
            $errors[] = 'file_bytes_base64 is required and must be valid base64.';
        }

        if ($errors !== []) {
            return ['ok' => false, 'errors' => $errors];
        }

        $row = [
            'name' => $name,
            'file_name' => $fileName,
            'mime_type' => $mimeType,
            'file_bytes' => $fileBytes,
            'width_mm' => $width,
            'height_mm' => $height,
            'justification' => $justification,
        ];

        if ($id === null) {
            $id = $this->repo->create($row);
        } else {
            $this->repo->update($id, $row);
        }

        return ['ok' => true, 'id' => $id];
    }

    public function delete(int $id): void
    {
        $this->repo->delete($id);
    }

    private function inferMimeTypeFromFilename(string $fileName): string
    {
        $fileName = trim($fileName);
        if ($fileName === '') {
            return '';
        }
        $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        if ($ext === '') {
            return '';
        }
        $map = [
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
            'webp' => 'image/webp',
            'svg' => 'image/svg+xml',
            'bmp' => 'image/bmp',
            'tif' => 'image/tiff',
            'tiff' => 'image/tiff',
        ];
        return $map[$ext] ?? '';
    }
}
