<?php

namespace App\Http\Controllers;

use App\Models\KbArticle;
use App\Models\KbCategory;
use App\Models\License;
use App\Models\Product;
use App\Services\EnvatoService;
use App\Services\PurchaseCodeService;
use Illuminate\Http\Request;

class KbPublicController extends Controller
{
    protected $envatoService;
    protected $purchaseCodeService;

    public function __construct(EnvatoService $envatoService, PurchaseCodeService $purchaseCodeService)
    {
        $this->envatoService = $envatoService;
        $this->purchaseCodeService = $purchaseCodeService;
    }

    public function index()
    {
        $categories = KbCategory::where('is_active', true)->withCount('children')->with('product')->orderBy('name')->get();
        $latest = KbArticle::where('is_published', true)
            ->whereHas('category', function($query) {
                $query->where('is_active', true);
            })
            ->with('category', 'product')
            ->latest()
            ->limit(6)
            ->get();

        return view('kb.index', compact('categories', 'latest'));
    }

    public function category(string $slug)
    {
        $category = KbCategory::where('slug', $slug)->with('product')->firstOrFail();

        $user = auth()->user();
        $hasAccess = false;
        $accessSource = '';
        $error = null;

        // Determine if access is restricted for this category
        $requiresAccess = (bool) ($category->requires_serial || $category->product_id);

        // If access is not required, show the category directly
        if (!$requiresAccess) {
            $articles = KbArticle::where('kb_category_id', $category->id)
                ->where('is_published', true)
                ->whereHas('category', function($query) {
                    $query->where('is_active', true);
                })
                ->with('category', 'product')
                ->latest()
                ->paginate(10);

            $relatedCategories = KbCategory::where('id', '!=', $category->id)
                ->where('is_published', true)
                ->with('product')
                ->inRandomOrder()
                ->limit(4)
                ->get();

            return view('kb.category', compact('category', 'articles', 'relatedCategories'));
        }

        // For protected categories, require authentication
        if (!auth()->check()) {
            return redirect()->route('login')->with('error', 'You must be logged in to access this category.');
        }

        $user = auth()->user();
        $hasAccess = false;
        $accessSource = '';
        $providedRawCode = request()->query('raw_code');
        $error = null;

        // If raw code provided, verify it and ensure the license's product actually grants access
        if ($providedRawCode) {
            $rawResult = $this->purchaseCodeService->verifyRawCode(
                $providedRawCode,
                $category->product_id // Verify against the category's product
            );

            if ($rawResult['success']) {
                $license = $rawResult['license'] ?? null;
                $productId = $rawResult['product_id'] ?? ($license->product_id ?? null);
                $product = $productId ? Product::find($productId) : null;

                // Check if product is linked to this category (direct relationship only)
                if ($product && $product->id == $category->product_id) {
                    $hasAccess = true;
                    $accessSource = 'raw_code';
                    
                    // Store access token in session for security (avoid showing license code in URL)
                    $accessToken = 'kb_access_' . $category->id . '_' . time() . '_' . substr(md5($license->license_key), 0, 8);
                    session([$accessToken => [
                        'license_id' => $license->id,
                        'product_id' => $product->id,
                        'category_id' => $category->id,
                        'expires_at' => now()->addHours(24)
                    ]]);
                    
                    // Redirect to clean URL without license code
                    return redirect()->route('kb.category', ['slug' => $category->slug, 'token' => $accessToken]);
                } else {
                    $error = $rawResult['message'] ?? trans('license_status.license_code_not_for_product');
                    // Redirect to clean URL with error message
                    return redirect()->route('kb.category', ['slug' => $category->slug])->with('error', $error);
                }
            } else {
                $error = $rawResult['message'] ?? trans('app.invalid_license_code_or_not_belong_to_product');
                // Redirect to clean URL with error message
                return redirect()->route('kb.category', ['slug' => $category->slug])->with('error', $error);
            }
        }

        // Check for access token in URL or session
        $accessToken = request()->query('token');
        if ($accessToken && session()->has($accessToken)) {
            $tokenData = session($accessToken);
            
            // Check if token is still valid
            if ($tokenData['expires_at'] > now() && $tokenData['category_id'] == $category->id) {
                $hasAccess = true;
                $accessSource = 'token';
            } else {
                // Token expired or invalid
                session()->forget($accessToken);
            }
        }

        // If access granted, show the category
        if ($hasAccess) {
            $articles = KbArticle::where('kb_category_id', $category->id)
                ->where('is_published', true)
                ->whereHas('category', function($query) {
                    $query->where('is_active', true);
                })
                ->with('category', 'product')
                ->latest()
                ->paginate(10);

            $relatedCategories = KbCategory::where('id', '!=', $category->id)
                ->where('is_published', true)
                ->with('product')
                ->inRandomOrder()
                ->limit(4)
                ->get();

            return view('kb.category', compact('category', 'articles', 'relatedCategories', 'accessSource'));
        }

        // No access - show purchase prompt

        return view('kb.category-purchase', compact('category'))->with('error', $error);
    }

    public function article(string $slug)
    {
        $article = KbArticle::where('slug', $slug)
            ->where('is_published', true)
            ->whereHas('category', function($query) {
                $query->where('is_active', true);
            })
            ->with('category', 'product')
            ->firstOrFail();

        $user = auth()->user();
        $hasAccess = false;
        $accessSource = '';
        $error = null;

        // Check if article requires access
        // Article requires access if it has explicit requirements OR is linked to a product (directly or via category)
        $requiresAccess = (bool) ($article->requires_serial ||
                                 $article->product_id ||
                                 ($article->category && ($article->category->requires_serial || $article->category->product_id)));

        // If no access required, show article
        if (!$requiresAccess) {
            $article->increment('views');
            $relatedArticles = KbArticle::where('kb_category_id', $article->kb_category_id)
                ->where('id', '!=', $article->id)
                ->where('is_published', true)
                ->whereHas('category', function($query) {
                    $query->where('is_active', true);
                })
                ->with('category', 'product')
                ->latest()
                ->limit(3)
                ->get();

            return view('kb.article', compact('article', 'relatedArticles'));
        }

        // For protected articles, require authentication
        if (!auth()->check()) {
            return redirect()->route('login')->with('error', 'You must be logged in to access this article.');
        }

        $providedRawCode = request()->query('raw_code');

        // Determine which product to verify against
        $productIdToVerify = $article->product_id ?: ($article->category ? $article->category->product_id : null);

        // If user is logged in, first check their licenses (no raw code needed)
        if ($this->checkArticleAccess($article, $user)) {
            $hasAccess = true;
            $accessSource = 'user_license';
        }

        // If a raw code was provided, also allow verification via raw code (Envato/db)
        if (!$hasAccess && $providedRawCode) {
            // Determine which product to verify against
            $productIdToVerify = $article->product_id ?: ($article->category ? $article->category->product_id : null);
            
            $rawResult = $this->purchaseCodeService->verifyRawCode(
                $providedRawCode,
                $productIdToVerify
            );

            if ($rawResult['success']) {
                $license = $rawResult['license'] ?? null;
                $productId = $rawResult['product_id'] ?? ($license->product_id ?? null);
                $product = $productId ? Product::find($productId) : null;

                // Check if the product matches the article's product or category's product
                $articleProductId = $article->product_id ?: ($article->category ? $article->category->product_id : null);
                
                // Check if product is linked to this article/category (direct relationship only)
                if ($product && $product->id == $articleProductId) {
                    $hasAccess = true;
                    $accessSource = 'raw_code';
                    
                    // Store access token in session for security (avoid showing license code in URL)
                    $accessToken = 'kb_article_access_' . $article->id . '_' . time() . '_' . substr(md5($license->license_key), 0, 8);
                    session([$accessToken => [
                        'license_id' => $license->id,
                        'product_id' => $product->id,
                        'article_id' => $article->id,
                        'expires_at' => now()->addHours(24)
                    ]]);
                    
                    // Redirect to clean URL without license code
                    return redirect()->route('kb.article', ['slug' => $article->slug, 'token' => $accessToken]);
                } else {
                    $error = $rawResult['message'] ?? trans('license_status.license_code_not_for_product');
                    // Redirect to clean URL with error message
                    return redirect()->route('kb.article', ['slug' => $article->slug])->with('error', $error);
                }
            } else {
                $error = $rawResult['message'] ?? trans('app.invalid_license_code_or_not_belong_to_product');
                // Redirect to clean URL with error message
                return redirect()->route('kb.article', ['slug' => $article->slug])->with('error', $error);
            }
        }

        // Check for access token in URL or session
        $accessToken = request()->query('token');
        if ($accessToken && session()->has($accessToken)) {
            $tokenData = session($accessToken);
            
            // Check if token is still valid
            if ($tokenData['expires_at'] > now() && $tokenData['article_id'] == $article->id) {
                $hasAccess = true;
                $accessSource = 'token';
            } else {
                // Token expired or invalid
                session()->forget($accessToken);
            }
        }
        if ($hasAccess) {
            $article->increment('views');
            $relatedArticles = KbArticle::where('kb_category_id', $article->kb_category_id)
                ->where('id', '!=', $article->id)
                ->where('is_published', true)
                ->whereHas('category', function($query) {
                    $query->where('is_active', true);
                })
                ->with('category', 'product')
                ->latest()
                ->limit(3)
                ->get();

            return view('kb.article', compact('article', 'relatedArticles', 'accessSource'));
        }

        // No access - show purchase prompt

        return view('kb.article-purchase', compact('article'))->with('error', $error);
    }

    public function search(Request $request)
    {
        $q = trim($request->get('q', ''));
        $results = collect();
        $resultsWithAccess = collect();
        $categoriesWithAccess = collect();
        $articles = collect();
        $categories = collect();

        // Get all categories with access information for display
        $allCategories = KbCategory::where('is_active', true)
            ->with('product', 'articles')
            ->get();

        // Process categories access
        $user = auth()->user();
        $allCategories->each(function ($category) use ($user) {
            $category->hasAccess = $this->checkCategoryAccess($category, $user);
        });

        if ($q !== '') {
            // Search articles with case-insensitive search (secure)
            $searchTerm = '%' . strtolower($q) . '%';
            $articles = KbArticle::where('is_published', true)
                ->whereHas('category', function($query) {
                    $query->where('is_active', true);
                })
                ->where(function ($query) use ($searchTerm) {
                    $query->whereRaw('LOWER(title) LIKE ?', [$searchTerm])
                          ->orWhereRaw('LOWER(content) LIKE ?', [$searchTerm])
                          ->orWhereRaw('LOWER(excerpt) LIKE ?', [$searchTerm]);
                })
                ->with('category', 'product')
                ->get();

            // Search categories with case-insensitive search (secure)
            $categories = KbCategory::where('is_active', true)
                ->where(function ($query) use ($searchTerm) {
                    $query->whereRaw('LOWER(name) LIKE ?', [$searchTerm])
                          ->orWhereRaw('LOWER(description) LIKE ?', [$searchTerm]);
                })
                ->with('product')
                ->get();

            // Add search_type to results
            $articles->each(function ($article) {
                $article->search_type = 'article';
            });

            $categories->each(function ($category) {
                $category->search_type = 'category';
            });

            // Combine results
            $results = $articles->concat($categories);

            // Filter results based on access
            foreach ($results as $item) {
                $hasAccess = true; // Default to accessible

                if ($item instanceof KbArticle) {
                    $hasAccess = $this->checkArticleAccess($item, $user);
                } elseif ($item instanceof KbCategory) {
                    $hasAccess = $this->checkCategoryAccess($item, $user);
                }

                // Add hasAccess property for view
                $item->hasAccess = $hasAccess;

                // Always add to results, regardless of access (but mark locked items)
                if ($item instanceof KbArticle) {
                    $resultsWithAccess->push($item);
                } else {
                    $categoriesWithAccess->push($item);
                    $resultsWithAccess->push($item); // Also add to main results for display
                }
            }

            // Add pagination for results (limit to 10 per page)
            $resultsWithAccess = $resultsWithAccess->forPage(request('page', 1), 10);
        } else {
            // If no search query, use all categories for display
            $categoriesWithAccess = $allCategories;
        }

        // Add highlighting helper for search terms
        $highlightQuery = $q;
        
        return view('kb.search', compact('q', 'results', 'resultsWithAccess', 'categoriesWithAccess', 'highlightQuery'));
    }

    /**
     * Check if user has access to a category
     */
    private function checkCategoryAccess($category, $user)
    {
        $requiresAccess = (bool) ($category->requires_serial || $category->product_id);

        if (!$requiresAccess) {
            return true; // No access required
        }

        if (!$user) {
            return false; // User not logged in
        }

        // If category is linked to a product, user must have an active license for that product
        if ($category->product_id) {
            // Check if user has an active license for that specific product
            $hasLicense = $user->licenses()
                ->where('product_id', $category->product_id)
                ->where('status', 'active')
                ->where(function ($query) {
                    $query->whereNull('license_expires_at')
                          ->orWhere('license_expires_at', '>', now());
                })
                ->exists();

            return $hasLicense;
        }

        return false; // Requires access but no product_id
    }

    /**
     * Check if user has access to an article
     */
    private function checkArticleAccess($article, $user)
    {
        $requiresAccess = (bool) ($article->requires_serial ||
                                 $article->requires_purchase_code ||
                                 $article->product_id ||
                                 ($article->category && ($article->category->requires_serial || $article->category->product_id)));

        if (!$requiresAccess) {
            return true; // No access required
        }

        if (!$user) {
            return false; // User not logged in
        }

        // If article is linked directly to a product, user must have an active license for that product
        if ($article->product_id) {
            $hasLicense = $user->licenses()
                ->where('product_id', $article->product_id)
                ->where('status', 'active')
                ->where(function ($query) {
                    $query->whereNull('license_expires_at')
                          ->orWhere('license_expires_at', '>', now());
                })
                ->exists();

            return $hasLicense;
        }

        // Otherwise, if category defines a product_id, check that product
        if ($article->category && $article->category->product_id) {
            $catProductId = $article->category->product_id;
            $hasLicense = $user->licenses()
                ->where('product_id', $catProductId)
                ->where('status', 'active')
                ->where(function ($query) {
                    $query->whereNull('license_expires_at')
                          ->orWhere('license_expires_at', '>', now());
                })
                ->exists();

            return $hasLicense;
        }

        return false; // Requires access but no product mapping found
    }

}