<?php

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Session;
use App\Core\Response;
use App\Models\Post;
use App\Models\Category;
use App\Models\Comment;
use App\Models\Vote;
use App\Services\NotificationService;

class PostController extends Controller
{
    private Post $postModel;
    private Category $categoryModel;
    private Comment $commentModel;
    private Vote $voteModel;

    public function __construct()
    {
        $this->postModel = new Post();
        $this->categoryModel = new Category();
        $this->commentModel = new Comment();
        $this->voteModel = new Vote();
    }

    public function index(Request $request): Response
    {
        $sort = $request->get('sort', 'latest');
        $page = max(1, (int)$request->get('page', 1));
        $limit = 20;
        $offset = ($page - 1) * $limit;

        $posts = $this->postModel->getLatest($limit, $offset, $sort);
        $categories = $this->categoryModel->all();

        $db = \App\Core\Database::getInstance();
        $stats = [
            'members' => (int)$db->query("SELECT COUNT(*) FROM users")->fetchColumn(),
            'topics'  => (int)$db->query("SELECT COUNT(*) FROM posts WHERE status='active'")->fetchColumn(),
            'posts'   => (int)$db->query("SELECT COUNT(*) FROM comments")->fetchColumn(),
            'online'  => 1,
        ];

        return $this->render('home', compact('posts', 'categories', 'stats', 'sort'));
    }

    public function show(Request $request, string $slug): Response
    {
        $post = $this->postModel->findBySlug($slug);
        if (!$post) return new Response('Post not found', 404);

        // Increment view count
        \App\Core\Database::getInstance()->prepare("UPDATE posts SET view_count = view_count + 1 WHERE id = ?")->execute([$post['id']]);

        $comments = $this->commentModel->getByPost($post['id']);
        $title = htmlspecialchars($post['title']);
        return $this->render('posts.show', compact('post', 'comments', 'title'));
    }

    public function showCreateForm(Request $request): Response
    {
        $categories = $this->categoryModel->all();
        return $this->render('posts.create', compact('categories'));
    }

    public function store(Request $request): Response
    {
        $title = trim($request->post('title', ''));
        $content = trim($request->post('content', ''));
        $categoryId = (int)$request->post('category_id', 0);
        $type = $request->post('type', 'reddit');
        $userId = Session::get('user_id');

        if (empty($title) || empty($content) || !$categoryId) {
            Session::flash('error', 'All fields are required');
            return Response::redirect('/post/create');
        }

        $slug = $this->generateSlug($title);
        $postId = $this->postModel->create([
            'user_id' => $userId,
            'category_id' => $categoryId,
            'title' => $title,
            'slug' => $slug,
            'content' => $content,
            'type' => in_array($type, ['reddit', 'question']) ? $type : 'reddit',
        ]);

        Session::flash('success', 'Post created successfully');
        return Response::redirect('/post/' . $slug);
    }

    public function showEditForm(Request $request, string $slug): Response
    {
        $post = $this->postModel->findBySlug($slug);
        if (!$post) return new Response('Not found', 404);
        if (Session::get('user_id') != $post['user_id'] && Session::get('role') != 3) {
            return Response::redirect('/');
        }
        $categories = $this->categoryModel->all();
        return $this->render('posts.edit', compact('post', 'categories'));
    }

    public function update(Request $request, int $id): Response
    {
        $post = $this->postModel->find($id);
        if (!$post) return new Response('Not found', 404);
        if (Session::get('user_id') != $post['user_id'] && Session::get('role') != 3) {
            return Response::redirect('/');
        }

        $this->postModel->update($id, [
            'title' => trim($request->post('title', '')),
            'content' => trim($request->post('content', '')),
            'category_id' => (int)$request->post('category_id', $post['category_id']),
        ]);

        Session::flash('success', 'Post updated successfully');
        return Response::redirect('/post/' . $post['slug']);
    }

    public function vote(Request $request): Response
    {
        if (!Session::has('user_id')) {
            return Response::json(['error' => 'Unauthorized'], 401);
        }

        $postId = $request->post('post_id') ? (int)$request->post('post_id') : null;
        $commentId = $request->post('comment_id') ? (int)$request->post('comment_id') : null;
        $type = (int)$request->post('type', 1);

        if ($type !== 1 && $type !== -1) {
            return Response::json(['error' => 'Invalid vote type'], 400);
        }

        $result = $this->voteModel->vote(Session::get('user_id'), $postId, $commentId, $type);
        return Response::json($result);
    }

    public function storeComment(Request $request): Response
    {
        $postId = (int)$request->post('post_id', 0);
        $content = trim($request->post('content', ''));
        $parentId = $request->post('parent_id') ? (int)$request->post('parent_id') : null;

        if (!$postId || empty($content)) {
            Session::flash('error', 'Comment cannot be empty');
            return Response::redirect($_SERVER['HTTP_REFERER'] ?? '/');
        }

        $post = $this->postModel->find($postId);
        if (!$post) return new Response('Not found', 404);

        $commentId = $this->commentModel->create([
            'post_id' => $postId,
            'user_id' => Session::get('user_id'),
            'parent_id' => $parentId,
            'content' => $content,
        ]);

        // Notify post owner
        if ($post['user_id'] != Session::get('user_id')) {
            (new NotificationService())->notifyNewComment(
                $post['user_id'],
                Session::get('user_id'),
                $post['title'],
                $post['slug']
            );
        }

        return Response::redirect('/post/' . $post['slug'] . '#comment-' . $commentId);
    }

    public function acceptComment(Request $request): Response
    {
        $commentId = (int)$request->post('comment_id', 0);
        if (!$commentId) return Response::redirect('/');

        $comment = $this->commentModel->find($commentId);
        if (!$comment) return Response::redirect('/');

        $post = $this->postModel->find($comment['post_id']);
        if (!$post || $post['user_id'] != Session::get('user_id')) {
            return Response::redirect('/');
        }

        $this->commentModel->accept($commentId, $post['id']);

        if ($comment['user_id'] != Session::get('user_id')) {
            (new NotificationService())->notifyBestAnswer($comment['user_id'], $post['title'], $post['slug']);
        }

        return Response::redirect('/post/' . $post['slug']);
    }

    public function category(Request $request, string $slug): Response
    {
        $currentCategory = $this->categoryModel->findBySlug($slug);
        if (!$currentCategory) return new Response('Not found', 404);

        $posts = $this->postModel->getByCategory($currentCategory['id']);
        $categories = $this->categoryModel->all();

        $db = \App\Core\Database::getInstance();
        $stats = [
            'members' => (int)$db->query("SELECT COUNT(*) FROM users")->fetchColumn(),
            'topics'  => (int)$db->query("SELECT COUNT(*) FROM posts WHERE status='active'")->fetchColumn(),
            'posts'   => (int)$db->query("SELECT COUNT(*) FROM comments")->fetchColumn(),
            'online'  => 1,
        ];

        return $this->render('home', compact('posts', 'categories', 'currentCategory', 'stats'));
    }

    private function generateSlug(string $title): string
    {
        $slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $title), '-'));
        $base = $slug;
        $i = 1;
        while ($this->postModel->findBySlug($slug)) {
            $slug = $base . '-' . $i++;
        }
        return $slug;
    }
}
