<?php

namespace App\Services\Seo;

/**
 * Generates SEO metadata for job listings: Open Graph tags and Google
 * Jobs-compliant JSON-LD structured data (schema.org/JobPosting) — the
 * markup Google Search requires to surface a listing in Google for Jobs.
 * Views call these helpers directly rather than duplicating the schema
 * shape per template.
 */
class SeoService
{
    public function metaTagsFor(array $job): array
    {
        $title = $job['meta_title'] ?: ($job['title'] . ' at ' . ($job['company_name'] ?? ''));
        $description = $job['meta_description'] ?: mb_substr(strip_tags($job['description']), 0, 160);

        return [
            'title'       => $title,
            'description' => $description,
            'og' => [
                'og:title'       => $title,
                'og:description' => $description,
                'og:type'        => 'website',
                'og:url'         => base_url('jobs/' . $job['seo_slug']),
            ],
        ];
    }

    /**
     * @see https://developers.google.com/search/docs/appearance/structured-data/job-posting
     */
    public function jobPostingJsonLd(array $job, array $agency): string
    {
        $schema = [
            '@context'         => 'https://schema.org/',
            '@type'            => 'JobPosting',
            'title'            => $job['title'],
            'description'      => $job['description'],
            'datePosted'       => date('Y-m-d', strtotime($job['created_at'])),
            'validThrough'     => $job['expires_at'] ? date('c', strtotime($job['expires_at'])) : null,
            'employmentType'   => strtoupper(str_replace('_', '_', $job['employment_type'])),
            'hiringOrganization' => [
                '@type' => 'Organization',
                'name'  => $agency['company_name'],
                'sameAs' => $agency['website'] ?? null,
                'logo'  => $agency['logo_path'] ? base_url($agency['logo_path']) : null,
            ],
            'jobLocation' => [
                '@type'   => 'Place',
                'address' => ['@type' => 'PostalAddress', 'addressLocality' => $job['location']],
            ],
        ];

        if (! $job['is_remote']) {
            // jobLocationType only set for genuinely remote roles per
            // Google's guidance — omit entirely for onsite/hybrid.
        } else {
            $schema['jobLocationType'] = 'TELECOMMUTE';
        }

        if ($job['is_salary_visible'] && ($job['salary_min'] || $job['salary_max'])) {
            $schema['baseSalary'] = [
                '@type'    => 'MonetaryAmount',
                'currency' => $job['salary_currency'],
                'value'    => [
                    '@type'    => 'QuantitativeValue',
                    'minValue' => $job['salary_min'],
                    'maxValue' => $job['salary_max'],
                    'unitText' => 'MONTH',
                ],
            ];
        }

        return json_encode(array_filter($schema, fn ($v) => $v !== null), JSON_UNESCAPED_SLASHES);
    }
}
