<?php

namespace App\Services\Posts;

use App\Models\Post;
use App\Models\PostTarget;
use App\Models\User;
use App\Services\ContentSanitizer;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class PostService
{
    public function __construct(
        private PostCountersService $counters,
        private PostHashtagService  $hashtags,
    ) {}

    /**
     * Create a new text post.
     *
     * @param  User    $user
     * @param  string  $visibility
     * @param  string|null  $body
     * @param  array   $targets  [['type'=>'artwork','id'=>123], ...]
     * @return Post
     */
    public function createPost(
        User $user,
        string $type,
        string $visibility,
        ?string $body,
        array $targets = [],
        ?array $linkPreview = null,
        ?array $taggedUsers = null,
        ?Carbon $publishAt = null,
    ): Post {
        $sanitizedBody = $body ? ContentSanitizer::render($body) : null;

        $status = ($publishAt && $publishAt->isFuture())
            ? Post::STATUS_SCHEDULED
            : Post::STATUS_PUBLISHED;

        $meta = [];
        if ($linkPreview && ! empty($linkPreview['url'])) {
            $meta['link_preview'] = array_intersect_key($linkPreview, array_flip(['url', 'title', 'description', 'image', 'site_name']));
        }
        if ($taggedUsers && count($taggedUsers) > 0) {
            $meta['tagged_users'] = array_map(
                fn ($u) => ['id' => (int) $u['id'], 'username' => (string) $u['username'], 'name' => (string) ($u['name'] ?? $u['username'])],
                array_slice($taggedUsers, 0, 10),
            );
        }

        return DB::transaction(function () use ($user, $type, $visibility, $sanitizedBody, $targets, $meta, $status, $publishAt) {
            $post = Post::create([
                'user_id'    => $user->id,
                'type'       => $type,
                'visibility' => $visibility,
                'body'       => $sanitizedBody,
                'meta'       => $meta ?: null,
                'status'     => $status,
                'publish_at' => $publishAt,
            ]);

            foreach ($targets as $target) {
                PostTarget::create([
                    'post_id'     => $post->id,
                    'target_type' => $target['type'],
                    'target_id'   => $target['id'],
                ]);
            }

            // Sync hashtags extracted from the body
            if ($sanitizedBody) {
                $this->hashtags->sync($post, $sanitizedBody);
            }

            return $post;
        });
    }

    /**
     * Update body/visibility of an existing post.
     */
    public function updatePost(Post $post, ?string $body, ?string $visibility): Post
    {
        $updates = [];

        if ($body !== null) {
            $updates['body'] = ContentSanitizer::render($body);
        }

        if ($visibility !== null) {
            $updates['visibility'] = $visibility;
        }

        $post->update($updates);

        // Re-sync hashtags whenever body changes
        if (isset($updates['body'])) {
            $this->hashtags->sync($post, $updates['body']);
        }

        return $post->fresh();
    }

    /**
     * Soft-delete a post (cascades to targets/reactions/comments via DB).
     */
    public function deletePost(Post $post): void
    {
        $post->delete();
    }
}
