<?php

declare(strict_types=1);

namespace App\Services\Blog;

use App\Models\BlogPost;
use App\Models\BlogPostReview;
use Carbon\CarbonInterface;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;

final class RandomBlogPostReviewGenerator
{
    /**
     * Create synthetic guest reviews for demos or staging. Not for misrepresenting real reader feedback in production.
     *
     * @param  CarbonInterface|null  $reviewedFrom  Inclusive start of date range (start of day). Both ends required to apply.
     * @param  CarbonInterface|null  $reviewedTo  Inclusive end of date range (end of day). Both ends required to apply.
     */
    public function generate(
        BlogPost $post,
        int $count,
        ?CarbonInterface $reviewedFrom = null,
        ?CarbonInterface $reviewedTo = null
    ): int {
        $count = max(1, min(100, $count));
        $title = $post->title;
        $snippet = Str::limit(strip_tags((string) ($post->excerpt !== '' && $post->excerpt !== null ? $post->excerpt : $title)), 100);

        $useRange = $reviewedFrom !== null && $reviewedTo !== null;

        for ($i = 0; $i < $count; $i++) {
            $attributes = [
                'blog_post_id' => $post->id,
                'user_id' => null,
                'guest_name' => fake()->name(),
                'guest_email' => fake()->boolean(55) ? fake()->safeEmail() : null,
                'rating' => fake()->randomElement([2, 3, 4, 4, 4, 4, 5, 5, 5, 5]),
                'body' => $this->makeBody($title, $snippet),
                'is_approved' => true,
            ];

            if ($useRange) {
                $at = $this->randomDateTimeBetween($reviewedFrom, $reviewedTo);
                $review = new BlogPostReview($attributes);
                $review->created_at = $at;
                $review->updated_at = $at;
                BlogPostReview::withoutTimestamps(static function () use ($review): void {
                    $review->save();
                });
            } else {
                BlogPostReview::query()->create($attributes);
            }
        }

        return $count;
    }

    private function randomDateTimeBetween(CarbonInterface $from, CarbonInterface $to): Carbon
    {
        $start = Carbon::instance($from);
        $end = Carbon::instance($to);

        if ($end->lessThan($start)) {
            [$start, $end] = [$end->copy(), $start->copy()];
        }

        $min = $start->timestamp;
        $max = $end->timestamp;

        if ($min >= $max) {
            return $start->copy();
        }

        $ts = random_int($min, $max);

        return Carbon::createFromTimestamp($ts, config('app.timezone'));
    }

    private function makeBody(string $title, string $snippet): string
    {
        $lead = fake()->randomElement([
            "I read {$title} end to end—really clear structure.",
            "Stumbled on this while researching; the angle on {$snippet} landed well.",
            "Shared this with my team after seeing the headline on {$title}.",
            "Honest take: {$title} goes deeper than most posts in this space.",
            "The opening hooked me; by the middle I was taking notes on {$title}.",
            "Not my usual beat, but {$title} explained the tradeoffs without fluff.",
        ]);

        $middle = fake()->randomElement([
            fake()->sentences(fake()->numberBetween(1, 2), true),
            'Would love a follow-up with more examples.',
            'Screenshots or diagrams would make it even stronger.',
            'Matched what I have seen in practice—useful sanity check.',
            'A few sections could be shorter, but the conclusions are solid.',
        ]);

        $close = fake()->randomElement([
            'Bookmarked for later.',
            'Left a rating to nudge others to read it.',
            'Thanks for publishing this.',
            'Looking forward to the next post.',
        ]);

        return trim($lead.' '.$middle.' '.$close);
    }
}
