<?php

namespace App\Traits;

use App\Enums\FileKey;
use App\Enums\PostStatus;
use App\Enums\PostType;
use App\Enums\StatusEnum;
use App\Models\AiTemplate;
use App\Models\PostTemplate;
use App\Models\SocialPost;
use Carbon\Carbon;

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use App\Traits\Fileable;
trait PostManager
{

    use Fileable;

    /**
     * save post
     * @param array $data
     * @param mixed $user
     */
    public function savePosts(array $data, $user)
    {
        $now = now();


        DB::beginTransaction();

        try {
            $posts = [];

            foreach ($data['accounts'] as $account) {
                $posts[] = [
                    'user_id' => $user->id,
                    'account_id' => $account['account_id'],
                    'platform_id' => $account['platform_id'] ?? null,
                    'campaign_id' => $data['campaign_id'] ?? null,
                    'content' => $data['content'] ?? null,
                    'link' => !empty($data['links']) ? json_encode($data['links']) : null,
                    'status' => PostStatus::PENDING->value,
                    'post_type' => PostType::fromString($account['post_type'] ?? 'feed')->value,
                    'is_scheduled' => $data['is_scheduled'] ?? StatusEnum::false->status(),
                    'schedule_time' => $data['scheduled_time'] ? Carbon::parse($data['scheduled_time']) : null,
                    'is_draft' => $data['is_draft'] ?? StatusEnum::false->status(),
                    'created_at' => $now,
                    'updated_at' => $now,
                ];
            }

            SocialPost::insert($posts);

            $insertedPosts = SocialPost::latest()->take(count($posts))->get();

            foreach ($insertedPosts as $post) {
                foreach ($data['files'] ?? [] as $index => $file) {
                    if (!empty($file['id'])) {
                        $galleryFile = $user->files()->find($file['id']);
                        if ($galleryFile) {
                            $post->files()->attach($galleryFile->id, [
                                'caption' => $file['caption'] ?? null,
                                'alt' => $file['alt'] ?? null,
                                'order' => $file['order'] ?? null
                            ]);
                        }
                    } elseif (!empty($file['upload'])) {
                        $storedFile = $this->storeFile(
                            file: $file['upload'],
                            location: config('settings.file_path.gallery.path')
                        );

                        $savedFile = $this->saveFile(
                            $post,
                            $storedFile,
                            FileKey::POST_FILE->value
                        );

                        $post->files()->attach($savedFile->id, [
                            'caption' => $file['caption'] ?? null,
                            'alt' => $file['alt'] ?? null,
                            'order' => $file['order'] ?? null
                        ]);
                    }
                }
            }

            DB::commit();

            return $insertedPosts;
        } catch (\Exception $e) {
            DB::rollBack();
            report($e);
            throw $e;
        }
    }


    /**
     * update post
     * @param array $data
     * @param mixed $user
     * @param mixed $campaign
     * @return void
     */
    public function updatePosts(array $data, $user, $campaign = null)
    {
        $campaignId = $campaign?->id ?? ($data['campaign_id'] ?? null);

        $existingPosts = SocialPost::where('campaign_id', $campaignId)
            ->when(!$campaignId, fn($q) => $q->where('user_id', $user->id))
            ->get()
            ->keyBy('account_id');

        foreach ($data['accounts'] as $account) {
            $accountId = $account['account_id'];

            if ($existingPosts->has($accountId)) {
                $post = $existingPosts[$accountId];

                $post->update([
                    'content' => $data['content'] ?? null,
                    'link' => !empty($data['links']) ? json_encode($data['links']) : null,
                    'post_type' => PostType::fromString($account['post_type'] ?? 'feed')->value,
                    'is_scheduled' => $data['is_scheduled'] ?? StatusEnum::false->status(),
                    'schedule_time' => $data['scheduled_time'] ?? null,
                    'is_draft' => $data['is_draft'] ?? StatusEnum::false->status(),
                ]);

                $this->syncFiles($post, $data['files'] ?? [], $user);

            } else {
                $newPost = SocialPost::create([
                    'user_id' => $user->id,
                    'account_id' => $accountId,
                    'platform_id' => $account['platform_id'] ?? null,
                    'campaign_id' => $campaignId,
                    'content' => $data['content'] ?? null,
                    'link' => !empty($data['links']) ? json_encode($data['links']) : null,
                    'status' => PostStatus::PENDING->value,
                    'post_type' => PostType::fromString($account['post_type'] ?? 'feed')->value,
                    'is_scheduled' => $data['is_scheduled'] ?? StatusEnum::false->status(),
                    'schedule_time' => $data['scheduled_time'] ?? null,
                    'is_draft' => $data['is_draft'] ?? StatusEnum::false->status(),
                ]);

                $this->syncFiles($newPost, $data['files'] ?? [], $user);
            }
        }

        $newAccountIds = collect($data['accounts'])->pluck('account_id')->all();

        if ($campaignId) {
            SocialPost::where('campaign_id', $campaignId)
                ->whereNotIn('account_id', $newAccountIds)
                ->each(fn($post) => $post->files()->detach() && $post->delete());
        }
    }

    /**
     * Sync files between old posts and new posts
     * @param mixed $post
     * @param array $files
     * @param mixed $user
     * @return void
     */
    protected function syncFiles($post, array $files, $user)
    {
        $post->files()->detach();

        foreach ($files as $file) {
            if (!empty($file['id'])) {
                $galleryFile = $user->files()->find($file['id']);
                if ($galleryFile) {
                    $post->files()->attach($galleryFile->id, [
                        'caption' => $file['caption'] ?? null,
                        'alt' => $file['alt'] ?? null,
                        'order' => $file['order'] ?? null,
                    ]);
                }
            }
        }
    }



    /**
     * publish a post
     *
     * @param SocialPost $post
     * @return void
     */
    public function publishPost(SocialPost $post): void
    {
        $account = $post->account;

        if (!$account)
            return;

        $class = 'App\\Http\\Services\\Account\\' . ucfirst($account->platform->slug) . '\\Account';
        $service = new $class();

        $response = $service->send($post);

        $is_success = Arr::get($response, 'status', false);
        $post->status = strval($is_success ? PostStatus::value('SUCCESS') : PostStatus::value('FAILED'));
        $post->platform_response = $response;

        // Extract and save platform_post_id for analytics
        if ($is_success) {
            $post->posted_at = now();
            $platformPostId = $this->extractPlatformPostId($response, $account->platform->slug);
            if ($platformPostId) {
                $post->platform_post_id = $platformPostId;
            }
        }

        $post->save();
    }

    /**
     * Extract platform post ID from response
     *
     * @param array $response
     * @param string $platform
     * @return string|null
     */
    protected function extractPlatformPostId(array $response, string $platform): ?string
    {
        // Try to get post_id directly from response
        if (!empty($response['post_id'])) {
            return (string) $response['post_id'];
        }

        // Try to get video_id (YouTube returns this)
        if (!empty($response['video_id'])) {
            return (string) $response['video_id'];
        }

        // Try to get id directly from response
        if (!empty($response['id'])) {
            return (string) $response['id'];
        }

        // Extract from URL based on platform
        $url = $response['url'] ?? null;
        if (!$url) {
            return null;
        }

        $platform = strtolower($platform);

        switch ($platform) {
            case 'twitter':
                // URL format: https://twitter.com/tweet/status/1234567890 or https://x.com/i/status/1234567890
                if (preg_match('/status\/(\d+)/', $url, $matches)) {
                    return $matches[1];
                }
                break;

            case 'facebook':
                // URL format: https://facebook.com/{page_id}/posts/{post_id} or contains post ID
                if (preg_match('/posts\/(\d+)/', $url, $matches)) {
                    return $matches[1];
                }
                if (preg_match('/(\d+)$/', $url, $matches)) {
                    return $matches[1];
                }
                break;

            case 'instagram':
                // URL format: https://www.instagram.com/p/{shortcode}/ - shortcode is the ID
                if (preg_match('/\/p\/([A-Za-z0-9_-]+)/', $url, $matches)) {
                    return $matches[1];
                }
                break;

            case 'linkedin':
                // URL format varies - might contain activity ID or urn
                if (preg_match('/activity-(\d+)/', $url, $matches)) {
                    return $matches[1];
                }
                if (preg_match('/urn:li:share:(\d+)/', $url, $matches)) {
                    return 'urn:li:share:' . $matches[1];
                }
                break;

            case 'tiktok':
                // URL format: https://www.tiktok.com/@user/video/1234567890
                if (preg_match('/video\/(\d+)/', $url, $matches)) {
                    return $matches[1];
                }
                break;

            case 'youtube':
                // URL format: https://youtube.com/watch?v=VIDEO_ID or https://youtu.be/VIDEO_ID
                if (preg_match('/[?&]v=([^&]+)/', $url, $matches)) {
                    return $matches[1];
                }
                if (preg_match('/youtu\.be\/([^?&]+)/', $url, $matches)) {
                    return $matches[1];
                }
                break;

            case 'threads':
                // URL format: https://www.threads.net/@user/post/{post_id}
                if (preg_match('/post\/(\d+)/', $url, $matches)) {
                    return $matches[1];
                }
                // Also check for ID in URL path
                if (preg_match('/\/(\d+)\/?$/', $url, $matches)) {
                    return $matches[1];
                }
                break;
        }

        return null;
    }

    /**
     * publish a post
     *
     * @param SocialPost $post
     * @return void
     */
    public function updatePostMetrics(SocialPost $post): void
    {
        $account = $post->account;

        if (!$account || !$post->facebook_post_id) {
            return;
        }

        $class = 'App\\Http\\Services\\Account\\' . ucfirst($account->platform->slug) . '\\Account';
        if (!class_exists($class)) {
            return;
        }

        $service = new $class();

        $response = $service->getInsight($post, $account);

        $is_success = Arr::get($response, 'status', false);

        $post->status = strval($is_success ? PostStatus::value('SUCCESS') : PostStatus::value('FAILED'));
        $post->platform_response = $response;
        $post->save();

        if ($is_success && !empty($response['metrics'])) {
            $post->metrics()->updateOrCreate(
                ['post_id' => $post->id],
                $response['metrics']
            );
        }
    }


    public function getMedia($user)
    {
        return $user->files()
            ->where('type', FileKey::GALLERY_FILE->value)
            ->with('platforms.platform')
            ->get()
            ->map(fn($file) => [
                'id' => $file->id,
                'title' => $file->name,
                'type' => optional($file->platforms->first())->type,
                'size' => $file->size,
                'date' => $file->created_at->format('d F Y, h:i A'),
                'thumbnail' => imageURL($file, 'gallery'),
                'isVideo' => (getFileTypeFromExtension($file->extension) === 'video'),
                'platform' => optional($file->platforms->first()->platform)->slug,
                'alt' => $file->name,
            ]);
    }

    public function getTemplates($user)
    {
        return PostTemplate::where('user_id', $user->id)
            ->search(['title'])
            ->filter(['platform_id'])
            ->with(['platform', 'files'])
            ->latest()
            ->get()
            ->map(fn($template) => [
                'id' => $template->id,
                'title' => $template->title,
                'description' => $template->description,
                'content' => $template->content,
                'platform' => $template->platform,
                'images' => $template->files->map(fn($file) => [
                    'id' => $file->id,
                    'url' => imageURL($file, 'gallery'),
                    'thumbnail' => imageURL($file, 'gallery'),
                    'alt' => $file->pivot->alt ?? $file->name,
                    'isVideo' => (getFileTypeFromExtension($file->extension) === 'video'),
                ])->toArray(),
            ]);
    }

    public function getAiTemplates($user)
    {
        return AiTemplate::where('user_id', auth()->id())
            ->with('platform')
            ->when($filters['search'] ?? null, fn($q, $search) => $q->where('name', 'like', "%{$search}%"))
            ->when($filters['platform_id'] ?? null, fn($q, $platformId) => $q->where('platform_id', $platformId))
            ->latest()
            ->get();
    }

    public function updateSinglePost(int $postId, array $data, $user): SocialPost
    {
        $post = SocialPost::where('id', $postId)
            ->where('user_id', $user->id)
            ->firstOrFail();

        $post->update([
            'content' => $data['content'] ?? $post->content,
            'link' => !empty($data['links']) ? json_encode($data['links']) : $post->link,
            'post_type' => PostType::fromString(
                collect($data['postTypes'])->first() ?? 'feed'
            )->value,
            'is_scheduled' => $data['is_scheduled'] ?? $post->is_scheduled,
            'schedule_time' => $data['scheduled_time'] ?? $post->schedule_time,
            'is_draft' => $data['is_draft'] ?? $post->is_draft,
        ]);

        $this->syncFiles($post, $data['files'] ?? [], $user);

        return $post;
    }



}
