<?php

namespace App\Domain\Website\Services;

use App\Domain\Shared\Models\Academy;
use App\Domain\Website\Models\ContactSubmission;
use App\Domain\Website\Models\Media;
use App\Domain\Website\Models\WebsiteFaq;
use App\Domain\Website\Models\WebsiteNews;
use App\Domain\Website\Models\WebsitePartner;
use App\Domain\Website\Models\WebsiteTestimonial;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class WebsiteDataService
{
    public function getActivities(Academy $academy): Collection
    {
        $result = Cache::remember(
            "website.{$academy->id}.activities",
            3600,
            fn () => DB::table('activities')
                ->where('academy_id', $academy->id)
                ->where('is_active', true)
                ->orderBy('sort_order')
                ->get()
        );

        if (!$result instanceof Collection) {
            Cache::forget("website.{$academy->id}.activities");
            return DB::table('activities')
                ->where('academy_id', $academy->id)
                ->where('is_active', true)
                ->orderBy('sort_order')
                ->get();
        }

        return $result;
    }

    public function getPrograms(Academy $academy): Collection
    {
        $result = Cache::remember(
            "website.{$academy->id}.programs",
            3600,
            fn () => DB::table('training_programs')
                ->where('academy_id', $academy->id)
                ->where('status', 'active')
                ->orderBy('sort_order')
                ->get()
        );

        if (!$result instanceof Collection) {
            Cache::forget("website.{$academy->id}.programs");
            return DB::table('training_programs')
                ->where('academy_id', $academy->id)
                ->where('status', 'active')
                ->orderBy('sort_order')
                ->get();
        }

        return $result;
    }

    /**
     * @param  bool  $includeInactive  also return branches that are switched off,
     *                                 so a site can announce a location before it
     *                                 opens instead of hiding it until launch day.
     */
    public function getBranches(Academy $academy, bool $includeInactive = false): Collection
    {
        $key = "website.{$academy->id}.branches".($includeInactive ? '.all' : '');

        $result = Cache::remember(
            $key,
            3600,
            fn () => $this->branchQuery($academy, $includeInactive)->get()
        );

        if (!$result instanceof Collection) {
            Cache::forget($key);
            return $this->branchQuery($academy, $includeInactive)->get();
        }

        return $result;
    }

    /**
     * The branches a public site may show.
     *
     * `branches` is soft-deleted, and this query bypasses Eloquent — so without
     * the deleted_at check a branch removed in the ERP keeps appearing on the
     * website until someone notices.
     */
    private function branchQuery(Academy $academy, bool $includeInactive = false)
    {
        return DB::table('branches')
            ->where('academy_id', $academy->id)
            ->when(! $includeInactive, fn ($q) => $q->where('is_active', true))
            ->whereNull('deleted_at')
            // Open branches first, so an announced-but-closed location never
            // pushes a working one below the fold.
            ->orderByDesc('is_active')
            ->orderByDesc('is_main')
            ->orderBy('id');
    }

    public function getStats(Academy $academy): array
    {
        return Cache::remember(
            "website.{$academy->id}.stats",
            21600,
            function () use ($academy) {
                return [
                    'participants' => DB::table('participants')
                        ->where('academy_id', $academy->id)
                        ->where('status', 'active')
                        ->count(),
                    'trainers' => DB::table('trainers')
                        ->where('academy_id', $academy->id)
                        ->where('status', 'active')
                        ->count(),
                    'branches' => DB::table('branches')
                        ->where('academy_id', $academy->id)
                        ->where('is_active', true)
                        ->count(),
                    'programs' => DB::table('training_programs')
                        ->where('academy_id', $academy->id)
                        ->where('status', 'active')
                        ->count(),
                    'activities' => DB::table('activities')
                        ->where('academy_id', $academy->id)
                        ->where('is_active', true)
                        ->count(),
                ];
            }
        );
    }

    public function getTestimonials(Academy $academy, int $limit = 10): Collection
    {
        return WebsiteTestimonial::withoutGlobalScope('academy')
            ->where('academy_id', $academy->id)
            ->where('is_featured', true)
            ->orderBy('sort_order')
            ->limit($limit)
            ->get();
    }

    public function getFaqs(Academy $academy): Collection
    {
        return WebsiteFaq::withoutGlobalScope('academy')
            ->where('academy_id', $academy->id)
            ->where('is_published', true)
            ->orderBy('sort_order')
            ->get();
    }

    public function getNews(Academy $academy, int $limit = 6): Collection
    {
        return WebsiteNews::withoutGlobalScope('academy')
            ->where('academy_id', $academy->id)
            ->whereNotNull('published_at')
            ->where('published_at', '<=', now())
            ->orderByDesc('published_at')
            ->limit($limit)
            ->get();
    }

    public function getPartners(Academy $academy): Collection
    {
        return WebsitePartner::withoutGlobalScope('academy')
            ->where('academy_id', $academy->id)
            ->where('is_active', true)
            ->orderBy('sort_order')
            ->get();
    }

    public function getGalleryImages(Academy $academy, int $limit = 12): Collection
    {
        return Media::withoutGlobalScope('academy')
            ->where('academy_id', $academy->id)
            ->where('collection', 'gallery')
            ->orderBy('sort_order')
            ->limit($limit)
            ->get();
    }

    public function getMediaForCollection(Academy $academy, string $collection): Collection
    {
        return Media::withoutGlobalScope('academy')
            ->where('academy_id', $academy->id)
            ->where('collection', $collection)
            ->orderBy('sort_order')
            ->get();
    }

    public function submitContactForm(Academy $academy, array $data): ContactSubmission
    {
        return ContactSubmission::create([
            'academy_id' => $academy->id,
            'name' => $data['name'],
            'phone' => $data['phone'],
            'email' => $data['email'] ?? null,
            'message' => $data['message'],
        ]);
    }
}
