<?php

namespace App\Http\Controllers\Admin;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Models\BlogPost;
use App\Models\BlogCategory;
use App\Models\BlogTag;
use App\Models\BlogPostTag;
use App\Models\ContentRevision;
use App\Services\ActivityLogger;
use App\Services\UploadService;

class BlogController extends Controller
{
    // -------------------------------------------------------------------------
    // LIST
    // -------------------------------------------------------------------------

    public function index(Request $request, array $params = []): void
    {
        $posts = BlogPost::allWithDetails();

        $this->renderAdmin('blog/index', [
            'pageTitle' => __('admin.blog.title'),
            'posts'     => $posts,
            'auth'      => $this->auth(),
            'csrf'      => $this->csrf(),
        ]);
    }

    // -------------------------------------------------------------------------
    // CREATE
    // -------------------------------------------------------------------------

    public function create(Request $request, array $params = []): void
    {
        $categories = BlogCategory::all('name');

        $this->renderAdmin('blog/form', [
            'pageTitle'  => __('admin.blog.create'),
            'post'       => null,
            'categories' => $categories,
            'postTags'   => [],
            'auth'       => $this->auth(),
            'csrf'       => $this->csrf(),
        ]);
    }

    public function store(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $title    = trim($request->input('title', ''));
        $slug     = trim($request->input('slug', ''));
        $content  = $request->input('content', '');
        $excerpt  = trim($request->input('excerpt', ''));
        $status   = $request->input('status', 'draft');
        $catId    = (int) $request->input('category_id', 0) ?: null;
        $seoTitle = trim($request->input('seo_title', ''));
        $seoDesc  = trim($request->input('seo_description', ''));
        $tagsRaw  = trim($request->input('tags', ''));

        if (empty($title)) {
            set_flash('error', __('messages.field_required'));
            Response::redirect(admin_url('blog/create'));
            return;
        }

        // Always normalize the slug, whether auto-generated or user-provided,
        // to guarantee a URL-safe value that matches the frontend route lookup.
        $slug = !empty($slug) ? slugify($slug) : slugify($title);

        $existing = BlogPost::findBySlug($slug);
        if ($existing) {
            $slug = $slug . '-' . bin2hex(random_bytes(4));
        }

        $featuredImage = UploadService::upload($request->file('featured_image') ?? [], 'blog', 'blog', true, true);

        // If no file was uploaded, check for a library-selected path
        if ($featuredImage === null) {
            $libraryPath = trim($request->input('featured_image_path', ''));
            if ($libraryPath !== '') {
                $featuredImage = $libraryPath;
            }
        }

        // Content scheduling fields
        $publishAt   = self::sanitizeDatetime($request->input('publish_at', ''));
        $unpublishAt = self::sanitizeDatetime($request->input('unpublish_at', ''));

        // Auto-correct status based on scheduling
        if ($status === 'scheduled' && $publishAt && strtotime($publishAt) <= time()) {
            $status = 'published';
        }
        if ($status === 'published' && $publishAt && strtotime($publishAt) > time()) {
            $status = 'scheduled';
        }
        if ($status === 'draft') {
            $publishAt = null;
        }

        $publishedAt = ($status === 'published') ? date('Y-m-d H:i:s') : null;

        $postId = BlogPost::create([
            'title'           => $title,
            'slug'            => $slug,
            'content'         => $content,
            'excerpt'         => $excerpt,
            'status'          => $status,
            'publish_at'      => $publishAt,
            'unpublish_at'    => $unpublishAt ?: null,
            'category_id'     => $catId,
            'author_id'       => $this->auth()->userId(),
            'featured_image'  => $featuredImage,
            'published_at'    => $publishedAt,
            'seo_title'       => $seoTitle,
            'seo_description' => $seoDesc,
            'og_image'        => trim($request->input('og_image', '')),
            'robots_meta'     => trim($request->input('robots_meta', '')),
            'canonical_url'   => trim($request->input('canonical_url', '')),
            'custom_css'      => $request->input('custom_css', ''),
            'custom_js'       => $request->input('custom_js', ''),
            'pagebuilder_enabled' => (int) $request->input('pagebuilder_enabled', 0),
            'is_featured'     => (int) $request->input('is_featured', 0),
            'created_at'      => date('Y-m-d H:i:s'),
            'updated_at'      => date('Y-m-d H:i:s'),
        ]);

        // Save tags
        $this->syncTags($postId, $tagsRaw);

        $this->clearPageCache();
        ActivityLogger::log('create', 'blog_post', $postId, $title);
        set_flash('success', __('messages.post_created', ['title' => $title]));
        Response::redirect(admin_url('blog'));
    }

    // -------------------------------------------------------------------------
    // EDIT / UPDATE
    // -------------------------------------------------------------------------

    public function edit(Request $request, array $params = []): void
    {
        $id   = (int) ($params['id'] ?? 0);
        $post = BlogPost::findForAdmin($id);

        if (!$post) {
            set_flash('error', __('messages.not_found', ['item' => 'Post']));
            Response::redirect(admin_url('blog'));
            return;
        }

        $categories = BlogCategory::all('name');
        $postTags   = BlogTag::findByPost($id);

        $this->renderAdmin('blog/form', [
            'pageTitle'  => __('admin.blog.edit'),
            'post'       => $post,
            'categories' => $categories,
            'postTags'   => $postTags,
            'auth'       => $this->auth(),
            'csrf'       => $this->csrf(),
        ]);
    }

    public function update(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $id   = (int) ($params['id'] ?? 0);
        $post = BlogPost::findForAdmin($id);

        if (!$post) {
            set_flash('error', __('messages.not_found', ['item' => 'Post']));
            Response::redirect(admin_url('blog'));
            return;
        }

        // Store revision of current state before update
        ContentRevision::store('blog_post', $id, $post, $this->auth()->userId());

        $title    = trim($request->input('title', ''));
        $slug     = trim($request->input('slug', ''));
        $content  = $request->input('content', '');
        $excerpt  = trim($request->input('excerpt', ''));
        $status   = $request->input('status', 'draft');
        $catId    = (int) $request->input('category_id', 0) ?: null;
        $seoTitle = trim($request->input('seo_title', ''));
        $seoDesc  = trim($request->input('seo_description', ''));
        $tagsRaw  = trim($request->input('tags', ''));

        if (empty($title)) {
            set_flash('error', __('messages.error.title_required'));
            Response::redirect(admin_url('blog/edit/' . $id));
            return;
        }

        // Always normalize the slug to guarantee a URL-safe value.
        $slug = !empty($slug) ? slugify($slug) : slugify($title);

        $slugConflict = BlogPost::findBySlug($slug);
        if ($slugConflict && (int) $slugConflict['id'] !== $id) {
            $slug = $slug . '-' . bin2hex(random_bytes(4));
        }

        $featuredImage = $post['featured_image'];

        $newUpload = UploadService::upload($request->file('featured_image') ?? [], 'blog', 'blog', true, true);

        if ($newUpload !== null) {
            // New file uploaded – delete old (direct upload) and use new
            if (!empty($featuredImage)) {
                UploadService::delete($featuredImage, true, true);
            }
            $featuredImage = $newUpload;
        } elseif ($request->input('remove_image') === '1') {
            // Remove requested – delete old file and clear reference
            UploadService::delete($post['featured_image'], true, true);
            $featuredImage = null;
        } else {
            // No new upload, no remove – check if a library image was selected
            $libraryPath = trim($request->input('featured_image_path', ''));
            if ($libraryPath !== '' && $libraryPath !== $post['featured_image']) {
                // Library path changed: update reference; do NOT delete old file
                // (it may be a media library image used elsewhere)
                $featuredImage = $libraryPath;
            }
        }

        // Content scheduling fields
        $publishAt   = self::sanitizeDatetime($request->input('publish_at', ''));
        $unpublishAt = self::sanitizeDatetime($request->input('unpublish_at', ''));

        // Auto-correct status based on scheduling
        if ($status === 'scheduled' && $publishAt && strtotime($publishAt) <= time()) {
            $status = 'published';
        }
        if ($status === 'published' && $publishAt && strtotime($publishAt) > time()) {
            $status = 'scheduled';
        }
        if ($status === 'draft') {
            $publishAt = null;
        }

        $publishedAt = $post['published_at'];
        if ($status === 'published' && empty($publishedAt)) {
            $publishedAt = date('Y-m-d H:i:s');
        }

        BlogPost::updateById($id, [
            'title'           => $title,
            'slug'            => $slug,
            'content'         => $content,
            'excerpt'         => $excerpt,
            'status'          => $status,
            'publish_at'      => $publishAt,
            'unpublish_at'    => $unpublishAt ?: null,
            'category_id'     => $catId,
            'featured_image'  => $featuredImage,
            'published_at'    => $publishedAt,
            'seo_title'       => $seoTitle,
            'seo_description' => $seoDesc,
            'og_image'        => trim($request->input('og_image', '')),
            'robots_meta'     => trim($request->input('robots_meta', '')),
            'canonical_url'   => trim($request->input('canonical_url', '')),
            'custom_css'      => $request->input('custom_css', ''),
            'custom_js'       => $request->input('custom_js', ''),
            'pagebuilder_enabled' => (int) $request->input('pagebuilder_enabled', 0),
            'is_featured'     => (int) $request->input('is_featured', 0),
            'updated_at'      => date('Y-m-d H:i:s'),
        ]);

        // Sync tags
        $this->syncTags($id, $tagsRaw);

        $this->clearPageCache();
        ActivityLogger::log('update', 'blog_post', $id, $title);
        set_flash('success', __('messages.post_updated'));
        Response::redirect(admin_url('blog'));
    }

    // -------------------------------------------------------------------------
    // DELETE
    // -------------------------------------------------------------------------

    public function delete(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $id   = (int) ($params['id'] ?? 0);
        $post = BlogPost::findForAdmin($id);

        if (!$post) {
            set_flash('error', __('messages.not_found', ['item' => 'Post']));
            Response::redirect(admin_url('blog'));
            return;
        }

        BlogPostTag::deleteForPost($id);
        UploadService::delete($post['featured_image'], true, true);
        BlogPost::deleteById($id);

        $this->clearPageCache();
        ActivityLogger::log('delete', 'blog_post', $id, $post['title'] ?? '');
        set_flash('success', __('messages.post_deleted'));
        Response::redirect(admin_url('blog'));
    }

    public function bulk(Request $request, array $params = []): void
    {
        $this->validateCsrf();
        $ids    = array_map('intval', $request->input('ids', []));
        $action = $request->input('bulk_action', '');

        if (empty($ids)) {
            Response::redirect(admin_url('blog'));
            return;
        }

        $count = 0;
        foreach ($ids as $id) {
            if ($action === 'delete') {
                $post = BlogPost::findForAdmin($id);
                if ($post) {
                    BlogPostTag::deleteForPost($id);
                    UploadService::delete($post['featured_image'], true, true);
                    BlogPost::deleteById($id);
                    $count++;
                }
            } elseif ($action === 'publish') {
                BlogPost::updateById($id, ['status' => 'published', 'published_at' => date('Y-m-d H:i:s')]);
                $count++;
            } elseif ($action === 'draft') {
                BlogPost::updateById($id, ['status' => 'draft']);
                $count++;
            }
        }

        if ($count > 0) {
            $this->clearPageCache();
        }
        set_flash('success', __('messages.bulk_action_done', ['count' => $count]));
        Response::redirect(admin_url('blog'));
    }

    // -------------------------------------------------------------------------
    // CLONE / DUPLICATE
    // -------------------------------------------------------------------------

    public function clonePost(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $id   = (int) ($params['id'] ?? 0);
        $post = BlogPost::findForAdmin($id);

        if (!$post) {
            set_flash('error', __('messages.not_found', ['item' => 'Post']));
            Response::redirect(admin_url('blog'));
            return;
        }

        // Generate a unique slug: {slug}-copy, {slug}-copy-2, ...
        $baseSlug = $post['slug'] . '-copy';
        $newSlug  = $baseSlug;
        $counter  = 2;
        while (BlogPost::findBySlug($newSlug)) {
            $newSlug = $baseSlug . '-' . $counter;
            $counter++;
        }

        $newId = BlogPost::create([
            'title'           => 'Copy of ' . $post['title'],
            'slug'            => $newSlug,
            'content'         => $post['content'],
            'excerpt'         => $post['excerpt'],
            'status'          => 'draft',
            'category_id'     => $post['category_id'] ?: null,
            'author_id'       => $this->auth()->userId(),
            'featured_image'  => null,   // do not share file references (avoids accidental deletion)
            'published_at'    => null,
            'seo_title'       => $post['seo_title'],
            'seo_description' => $post['seo_description'],
            'og_image'        => null,
            'robots_meta'     => null,
            'canonical_url'   => null,
            'custom_css'      => null,
            'custom_js'       => null,
            'created_at'      => date('Y-m-d H:i:s'),
            'updated_at'      => date('Y-m-d H:i:s'),
        ]);

        // Copy tags from original post
        $originalTagIds = BlogPostTag::tagIdsForPost($id);
        if (!empty($originalTagIds)) {
            BlogPostTag::syncForPost($newId, $originalTagIds);
        }

        set_flash('success', __('messages.post_duplicated'));
        Response::redirect(admin_url('blog'));
    }

    // -------------------------------------------------------------------------
    // HELPERS
    // -------------------------------------------------------------------------

    /**
     * Sanitize a datetime string from input (datetime-local format).
     */
    private static function sanitizeDatetime(string $value): ?string
    {
        $value = trim($value);
        if ($value === '') {
            return null;
        }
        $value = str_replace('T', ' ', $value);
        $ts = strtotime($value);
        if ($ts === false) {
            return null;
        }
        return date('Y-m-d H:i:s', $ts);
    }

    /**
     * Parse a comma-separated tag string, find-or-create each tag, sync pivot.
     */
    private function syncTags(int $postId, string $tagsRaw): void
    {
        if (trim($tagsRaw) === '') {
            BlogPostTag::syncForPost($postId, []);
            return;
        }

        $names  = array_filter(array_map('trim', explode(',', $tagsRaw)));
        $tagIds = [];

        foreach ($names as $name) {
            if ($name === '') {
                continue;
            }
            $tag = BlogTag::findOrCreateByName($name);
            if (!empty($tag['id'])) {
                $tagIds[] = (int) $tag['id'];
            }
        }

        BlogPostTag::syncForPost($postId, $tagIds);
    }
}
