<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Page extends Model
{
    const BUILTIN_TYPES = ['terms', 'privacy', 'refund', 'contact'];

    protected $fillable = [
        'title', 'slug', 'content', 'sections', 'meta_title',
        'meta_description', 'meta_image', 'is_published', 'type',
    ];

    protected function casts(): array
    {
        return [
            'content' => 'array',
            'sections' => 'array',
            'is_published' => 'boolean',
        ];
    }

    protected static function booted(): void
    {
        static::creating(function (Page $page) {
            if (empty($page->slug)) {
                $page->slug = Str::slug($page->title);
            }
        });
    }

    public function scopePublished($query)
    {
        return $query->where('is_published', true);
    }

    public function scopeOfType($query, string $type)
    {
        return $query->where('type', $type);
    }

    public function scopeBuiltIn($query)
    {
        return $query->whereIn('type', self::BUILTIN_TYPES);
    }

    /**
     * Resolve a CMS page's content by slug, trying common aliases.
     *
     * Why this exists:
     *   The legacy frontend looked pages up with `where('type', 'terms')`
     *   etc. — but `pages.type` is an ENUM('landing','static','blog'),
     *   so saving `type='terms'` truncated to empty string under MySQL
     *   strict mode and the lookup never matched. Admin saves looked
     *   "successful" but the public pages stayed blank.
     *
     *   `slug` is varchar + unique and is what the admin form actually
     *   stores. This resolver looks the page up by slug (or any of the
     *   known aliases) and returns the parsed JSON `content` array,
     *   or `[]` if no published page is found.
     *
     * @param  string  $primarySlug   Preferred slug (e.g. 'terms')
     * @param  array   $aliases       Other slugs to try as fallbacks
     * @return array
     */
    public static function findContentBySlug(string $primarySlug, array $aliases = []): array
    {
        $raw = static::findRawContentBySlug($primarySlug, $aliases);
        return is_array($raw) ? $raw : [];
    }

    /**
     * Like findContentBySlug() but returns the content AS STORED — could
     * be an array (structured JSON like hero/cta/sections), a string
     * (raw HTML — e.g. admin pasted a complete Privacy Policy markup),
     * or null when no published page exists.
     *
     * Use this when the calling view can render BOTH shapes (string +
     * array) — the legal pages do this so admins can paste raw HTML
     * for whole-page templates OR fill in the structured card layout,
     * either one works.
     */
    public static function findRawContentBySlug(string $primarySlug, array $aliases = []): mixed
    {
        $slugs = array_values(array_unique(array_filter([$primarySlug, ...$aliases])));
        if (empty($slugs)) {
            return null;
        }

        $page = static::query()
            ->where('is_published', true)
            ->whereIn('slug', $slugs)
            ->orderByRaw("FIELD(slug, '" . implode("','", array_map(fn ($s) => str_replace("'", "''", $s), $slugs)) . "')")
            ->first();

        return $page?->content;
    }

    /**
     * Canonical alias map for the built-in CMS pages. Admins sometimes
     * pick slugs like 'terms-of-service' or 'terms-and-conditions' or
     * 'agreement' instead of just 'terms'; the resolver tries them all.
     */
    public const SLUG_ALIASES = [
        'terms'    => ['terms-of-service', 'terms-and-conditions', 'tos', 'agreement', 'contract'],
        'privacy'  => ['privacy-policy', 'data-privacy'],
        'refund'   => ['refund-policy', 'return-policy', 'cancellation-policy'],
        'contact'  => ['contact-us', 'support'],
        'about'    => ['about-us', 'company'],
        'why-us'   => ['why_us', 'why', 'why-choose-us'],
        'hero'     => [],
        'features' => [],
        'testimonials' => ['testimonial'],
        'faq'      => ['faqs', 'frequently-asked-questions'],
        'cta'      => ['call-to-action'],
    ];
}
