<?php

namespace ViartasCore\Comments\Controllers\Web;

use Illuminate\Http\Request;
use ViartasCore\Comments\Models\Comment;
use ViartasCore\Core\Controllers\WebController;

class FrontendCommentController extends WebController
{
    /**
     * Get a model class from model_type
     */
    protected function getModelClass(string $modelType): string
    {
        $modelMap = config('comments.model_map', []);

        if (!isset($modelMap[$modelType])) {
            abort(404, "Unknown model type: {$modelType}");
        }

        return $modelMap[$modelType];
    }

    /**
     * Get comments for display (API endpoint)
     */
    public function index(Request $request, string $modelType, int $modelId)
    {
        $modelClass = $this->getModelClass($modelType);
        $model = $modelClass::findOrFail($modelId);

        $comments = Comment::with(['user', 'allReplies' => function ($q) {
                $q->approved()->with('user');
            }])
            ->where('commentable_type', $modelClass)
            ->where('commentable_id', $modelId)
            ->approved()
            ->root()
            ->orderBy('created_at', 'desc')
            ->paginate(config('comments.frontend_per_page', 10));

        // Stats
        $stats = [
            'total' => Comment::where('commentable_type', $modelClass)
                ->where('commentable_id', $modelId)
                ->approved()
                ->count(),
            'average_rating' => Comment::where('commentable_type', $modelClass)
                ->where('commentable_id', $modelId)
                ->approved()
                ->whereNotNull('rating')
                ->avg('rating'),
            'rating_distribution' => $this->getRatingDistribution($modelClass, $modelId),
        ];

        return response()->json([
            'success' => true,
            'comments' => $comments->map(fn($c) => $this->formatCommentResponse($c)),
            'pagination' => [
                'current_page' => $comments->currentPage(),
                'last_page' => $comments->lastPage(),
                'per_page' => $comments->perPage(),
                'total' => $comments->total(),
            ],
            'stats' => $stats,
        ]);
    }

    /**
     * Store a new comment (from frontend)
     */
    public function store(Request $request, string $modelType, int $modelId)
    {
        $modelClass = $this->getModelClass($modelType);
        $model = $modelClass::findOrFail($modelId);

        $rules = [
            'content' => 'required|string|min:3|max:5000',
            'parent_id' => 'nullable|integer|exists:comments,id',
            'rating' => 'nullable|integer|min:1|max:5',
        ];

        // Guest fields required if not logged in
        if (!auth()->check()) {
            $rules['guest_name'] = 'required|string|max:100';
            $rules['guest_email'] = 'required|email|max:255';
        }

        // Honeypot check
        if ($request->filled('website')) {
            // Bot detected
            return response()->json([
                'success' => true, // Fake success to confuse bots
                'message' => __('comments.submitted'),
            ]);
        }

        $request->validate($rules);

        // Check for duplicate comment
        $duplicate = Comment::where('commentable_type', $modelClass)
            ->where('commentable_id', $modelId)
            ->where('content', $request->content)
            ->where('created_at', '>', now()->subMinutes(5))
            ->exists();

        if ($duplicate) {
            return response()->json([
                'success' => false,
                'message' => __('comments.duplicate'),
            ], 422);
        }

        // Rate limiting
        $recentComments = Comment::where('ip_address', $request->ip())
            ->where('created_at', '>', now()->subMinutes(config('comments.rate_limit_minutes', 1)))
            ->count();

        if ($recentComments >= config('comments.rate_limit_count', 3)) {
            return response()->json([
                'success' => false,
                'message' => __('comments.rate_limit'),
            ], 429);
        }

        // Auto-approve settings
        $autoApprove = config('comments.auto_approve', false);
        $autoApproveLoggedIn = config('comments.auto_approve_logged_in', true);

        $isApproved = $autoApprove || ($autoApproveLoggedIn && auth()->check());

        $comment = Comment::create([
            'commentable_type' => $modelClass,
            'commentable_id' => $modelId,
            'parent_id' => $request->parent_id,
            'user_id' => auth()->id(),
            'guest_name' => auth()->check() ? null : $request->guest_name,
            'guest_email' => auth()->check() ? null : $request->guest_email,
            'content' => $request->content,
            'rating' => $request->rating,
            'status' => $isApproved ? Comment::STATUS_APPROVED : Comment::STATUS_PENDING,
            'is_approved' => $isApproved,
            'approved_at' => $isApproved ? now() : null,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
        ]);

        $comment->load('user');

        $message = $isApproved
            ? __('comments.submitted_approved')
            : __('comments.submitted_pending');

        return response()->json([
            'success' => true,
            'message' => $message,
            'comment' => $isApproved ? $this->formatCommentResponse($comment) : null,
            'is_approved' => $isApproved,
        ]);
    }

    /**
     * Get rating distribution
     */
    protected function getRatingDistribution(string $modelClass, int $modelId): array
    {
        $distribution = [];
        for ($i = 5; $i >= 1; $i--) {
            $distribution[$i] = Comment::where('commentable_type', $modelClass)
                ->where('commentable_id', $modelId)
                ->approved()
                ->where('rating', $i)
                ->count();
        }
        return $distribution;
    }

    /**
     * Format comment for frontend response
     */
    protected function formatCommentResponse(Comment $comment): array
    {
        return [
            'id' => $comment->id,
            'content' => nl2br(e($comment->content)),
            'content_raw' => $comment->content,
            'author_name' => $comment->author_name,
            'author_initials' => $comment->author_initials,
            'rating' => $comment->rating,
            'created_at' => $comment->created_at->format('M d, Y'),
            'created_at_human' => $comment->created_at->diffForHumans(),
            'is_author' => auth()->check() && auth()->id() === $comment->user_id,
            'replies' => $comment->allReplies
                ->filter(fn($r) => $r->is_approved)
                ->map(fn($r) => $this->formatCommentResponse($r))
                ->values()
                ->toArray(),
        ];
    }
}
