<?php

require_once BASE_PATH
    . '/app/controllers/owner/OwnerBaseController.php';
require_once BASE_PATH
    . '/app/helpers/PostContent.php';
require_once BASE_PATH
    . '/app/models/Post.php';

require_once BASE_PATH
    . '/app/models/PostCategory.php';


class OwnerPostController
    extends OwnerBaseController
{
    private Post $postModel;
    private PostCategory $categoryModel;

    public function __construct()
    {
        $this->requireOwner();

        $this->postModel =
            new Post();

        $this->categoryModel =
            new PostCategory();
    }

    public function index(): void
    {
        $search =
            trim(
                $_GET['search'] ?? ''
            );

        $status =
            trim(
                $_GET['status'] ?? ''
            );

        $allowed = [
            '',
            'draft',
            'published',
            'hidden'
        ];

        if (
            !in_array(
                $status,
                $allowed,
                true
            )
        ) {
            $status = '';
        }

        $page =
            max(
                1,
                (int)
                ($_GET['page'] ?? 1)
            );

        $perPage = 15;

        $totalPosts =
            $this->postModel
                ->countForOwner(
                    $search,
                    $status
                );

        $totalPages =
            max(
                1,
                (int)
                ceil(
                    $totalPosts
                    / $perPage
                )
            );

        $page =
            min(
                $page,
                $totalPages
            );

        $posts =
            $this->postModel
                ->getForOwner(
                    $search,
                    $status,
                    $perPage,
                    ($page - 1)
                    * $perPage
                );

        require BASE_PATH
            . '/app/views/owner/posts/index.php';
    }

    public function create(): void
    {
        $categories =
            $this->categoryModel
                ->getActive();

        require BASE_PATH
            . '/app/views/owner/posts/create.php';
    }

    public function store(): void
    {
        $this->requirePost();
        $this->validateCsrf();

        try {

            $data =
                $this->validatePost();

            $data['author_id'] =
                (int)
                $_SESSION['user']['id'];

            $data['slug'] =
                $this->makeUniqueSlug(
                    $data['title']
                );

            $data['featured_image'] =
                $this->uploadFeaturedImage();

            $postId =
                $this->postModel
                    ->create($data);

            $this->flashSuccess(
                'Đã tạo bài viết.'
            );

            header(
                'Location: '
                . BASE_URL
                . '/?url=owner/post/edit&id='
                . $postId
            );

            exit;

        } catch (RuntimeException $e) {

            $this->flashError(
                $e->getMessage()
            );

            $this->redirect(
                'owner/post/create'
            );
        }
    }

    public function edit(): void
    {
        $id =
            (int)
            ($_GET['id'] ?? 0);

        $post =
            $this->postModel
                ->findById($id);

        if (!$post) {

            http_response_code(404);

            require BASE_PATH
                . '/app/views/errors/404.php';

            return;
        }

        $categories =
            $this->categoryModel
                ->getActive();

        require BASE_PATH
            . '/app/views/owner/posts/edit.php';
    }

    public function update(): void
    {
        $this->requirePost();
        $this->validateCsrf();

        $id =
            (int)
            ($_POST['post_id'] ?? 0);

        $post =
            $this->postModel
                ->findById($id);

        if (!$post) {

            $this->flashError(
                'Bài viết không tồn tại.'
            );

            $this->redirect(
                'owner/posts'
            );
        }

        try {

            $data =
                $this->validatePost();

            $data['slug'] =
                $this->makeUniqueSlug(
                    $data['title'],
                    $id
                );

            $newImage =
                $this->uploadFeaturedImage();

            if ($newImage !== null) {

                if (
                    !empty(
                        $post['featured_image']
                    )
                ) {

                    $oldFile =
                        BASE_PATH
                        . '/public/'
                        . ltrim(
                            $post['featured_image'],
                            '/'
                        );

                    if (is_file($oldFile)) {
                        @unlink($oldFile);
                    }
                }

                $data['featured_image'] =
                    $newImage;

            } else {

                $data['featured_image'] =
                    $post['featured_image'];
            }

            $this->postModel
                ->updatePost(
                    $id,
                    $data
                );

            $this->flashSuccess(
                'Đã cập nhật bài viết.'
            );

        } catch (RuntimeException $e) {

            $this->flashError(
                $e->getMessage()
            );
        }

        header(
            'Location: '
            . BASE_URL
            . '/?url=owner/post/edit&id='
            . $id
        );

        exit;
    }

    public function hide(): void
    {
        $this->requirePost();
        $this->validateCsrf();

        $id =
            (int)
            ($_POST['post_id'] ?? 0);

        $this->postModel
            ->hide($id);

        $this->flashSuccess(
            'Đã ẩn bài viết.'
        );

        $this->redirect(
            'owner/posts'
        );
    }

    public function delete(): void
    {
        $this->requirePost();
        $this->validateCsrf();

        $id =
            (int)
            ($_POST['post_id'] ?? 0);

        if ($id < 1) {

            $this->flashError(
                'Bài viết không hợp lệ.'
            );

            $this->redirect(
                'owner/posts'
            );
        }

        $post =
            $this->postModel
                ->findById($id);

        if (!$post) {

            $this->flashError(
                'Bài viết không tồn tại hoặc đã được xóa.'
            );

            $this->redirect(
                'owner/posts'
            );
        }

        try {

            $this->postModel
                ->deleteById($id);

            if (
                !empty(
                    $post['featured_image']
                )
            ) {

                $imagePath =
                    BASE_PATH
                    . '/public/'
                    . ltrim(
                        (string)
                        $post['featured_image'],
                        '/'
                    );

                if (is_file($imagePath)) {
                    @unlink($imagePath);
                }
            }

            $this->flashSuccess(
                'Đã xóa bài viết.'
            );

        } catch (Throwable $e) {

            $this->flashError(
                'Không thể xóa bài viết. Vui lòng thử lại.'
            );
        }

        $this->redirect(
            'owner/posts'
        );
    }


    private function validatePost(): array
    {
        $title =
            trim(
                $_POST['title'] ?? ''
            );

        $content =
    sanitize_post_html(
        (string) (
            $_POST['content']
            ?? ''
        )
    );

        if ($title === '') {

            throw new RuntimeException(
                'Tiêu đề không được để trống.'
            );
        }

        $plainContent =
    trim(
        html_entity_decode(
            strip_tags(
                $content
            ),
            ENT_QUOTES
            | ENT_HTML5,
            'UTF-8'
        )
    );


if ($plainContent === '') {

    throw new RuntimeException(
        'Nội dung bài viết không được để trống.'
    );
}

        $categoryId =
            (int)
            ($_POST['category_id'] ?? 0);

        if ($categoryId > 0) {

            $category =
                $this->categoryModel
                    ->findById(
                        $categoryId
                    );

            if (
                !$category
                || (int)
                $category['is_active'] !== 1
            ) {

                throw new RuntimeException(
                    'Danh mục bài viết không hợp lệ.'
                );
            }
        }

        $status =
            $_POST['status']
            ?? 'draft';

        if (
            !in_array(
                $status,
                [
                    'draft',
                    'published',
                    'hidden'
                ],
                true
            )
        ) {

            $status = 'draft';
        }

        return [
            'category_id' =>
                $categoryId,

            'title' =>
                $title,

            'excerpt' =>
                trim(
                    $_POST['excerpt'] ?? ''
                ),

            'content' =>
                $content,

            'status' =>
                $status
        ];
    }

    private function uploadFeaturedImage(): ?string
    {
        if (
            empty(
                $_FILES['featured_image']
            )

            || $_FILES[
                'featured_image'
            ]['error']
            === UPLOAD_ERR_NO_FILE
        ) {

            return null;
        }

        $file =
            $_FILES['featured_image'];

        if (
            $file['error']
            !== UPLOAD_ERR_OK
        ) {

            throw new RuntimeException(
                'Upload ảnh bài viết thất bại.'
            );
        }

        if (
            $file['size']
            > 5 * 1024 * 1024
        ) {

            throw new RuntimeException(
                'Ảnh bài viết tối đa 5MB.'
            );
        }

        $finfo =
            new finfo(
                FILEINFO_MIME_TYPE
            );

        $mime =
            $finfo->file(
                $file['tmp_name']
            );

        $allowed = [
            'image/jpeg' => 'jpg',
            'image/png' => 'png',
            'image/webp' => 'webp'
        ];

        if (
            !isset(
                $allowed[$mime]
            )
        ) {

            throw new RuntimeException(
                'Ảnh phải là JPG, PNG hoặc WEBP.'
            );
        }

        $directory =
            BASE_PATH
            . '/public/uploads/posts/';

        if (!is_dir($directory)) {

            mkdir(
                $directory,
                0755,
                true
            );
        }

        $filename =
            'post_'
            . bin2hex(
                random_bytes(10)
            )
            . '.'
            . $allowed[$mime];

        if (
            !move_uploaded_file(
                $file['tmp_name'],
                $directory . $filename
            )
        ) {

            throw new RuntimeException(
                'Không thể lưu ảnh bài viết.'
            );
        }

        return 'uploads/posts/'
            . $filename;
    }

    private function makeUniqueSlug(
        string $title,
        ?int $excludeId = null
    ): string {

        $slug =
            $this->slugify(
                $title
            );

        if ($slug === '') {
            $slug = 'post';
        }

        $base = $slug;
        $number = 2;

        while (
            $this->postModel
                ->slugExists(
                    $slug,
                    $excludeId
                )
        ) {

            $slug =
                $base
                . '-'
                . $number;

            $number++;
        }

        return $slug;
    }

    private function slugify(
        string $text
    ): string {

        $text =
            str_replace(
                ['Đ', 'đ'],
                ['D', 'd'],
                $text
            );

        $converted =
            iconv(
                'UTF-8',
                'ASCII//TRANSLIT//IGNORE',
                $text
            );

        if ($converted !== false) {
            $text = $converted;
        }

        $text =
            strtolower($text);

        $text =
            preg_replace(
                '/[^a-z0-9]+/',
                '-',
                $text
            );

        return trim(
            $text,
            '-'
        );
    }
}