<?php

namespace Main\Controllers\Chest;

use Main\Core\Controller;
use Main\Services\CategoryService;
use Main\Services\DeliveryService;
use Main\Services\SeoService;
use PDO;

class ChestController extends Controller
{
		protected string $route_type = 'chest';
		
    public function index()
    {
	      SeoService::set('chest.index');
				
        $chests = db()->prepare("SELECT C.*, P.name as productName, PC.id as categoryID, PC.name as categoryName, P.imageID, P.imageType FROM Chests C INNER JOIN Products P ON C.productID = P.id INNER JOIN ProductCategories PC ON P.categoryID = PC.id WHERE C.accountID = ? AND C.status = ? AND C.isLocked = ? ORDER BY C.id DESC");
        $chests->execute(array(auth()->user()->id(), 0, 0));
        $chests = array_map(function ($item) {
					$categoryList = CategoryService::getCategoryPath($item["categoryID"]);
					$item["category"] = [
						'id' => $item["categoryID"],
						'name' => $item["categoryName"],
						'list' => $categoryList !== null ? implode(' / ', $categoryList) : ''
					];
					
					$variables = db()->prepare("SELECT V.*, CV.value FROM ChestProductVariableValues CV INNER JOIN StoreVariables V ON V.id = CV.variableID WHERE CV.chestID = ?");
					$variables->execute(array($item["id"]));
	        $variables = $variables->fetchAll(PDO::FETCH_ASSOC);
					$item["product"] = [
						'id' => $item["productID"],
						'name' => $item["productName"],
						'image' => "/assets/core/images/store/products/" . $item["imageID"] . "." . $item["imageType"],
						'variables' => $variables,
					];
					
					return $item;
        }, $chests->fetchAll(PDO::FETCH_ASSOC));
	    
				// Group chests by product and variables
		    $groupedChests = [];
		    $counts = [];
		    foreach ($chests as $chest) {
			    $productID = $chest['product']['id'];
			    $variablesKey = implode(',', array_map(fn($var) => $var['id'] . ':' . $var['value'], $chest['product']['variables']));
			    $groupKey = $productID . '-' . $variablesKey;
			    
			    if (!isset($counts[$groupKey])) {
				    $counts[$groupKey] = 0;
				    $groupedChests[$groupKey] = $chest;
			    }
			    
			    $counts[$groupKey]++;
		    }
		    foreach ($groupedChests as $key => &$chest) {
			    $chest['amount'] = $counts[$key];
		    }
		    $chests = array_values($groupedChests);
				$groupedChests = null; // Free memory
	      $counts = null; // Free memory
				
        $logs = db()->prepare("SELECT CH.*, P.name as productName, OA.realname as otherAccountDisplayName FROM ChestsHistory CH INNER JOIN Chests C ON CH.chestID = C.id INNER JOIN Products P ON C.productID = P.id LEFT JOIN Accounts OA ON OA.id = CH.otherAccountID WHERE CH.accountID = ? ORDER BY CH.id DESC LIMIT 5");
		    $logs->execute(array(auth()->user()->id()));
		    $logs = $logs->fetchAll();
				
        return $this->view('chest.index', compact('chests', 'logs'));
    }

    public function deliver($id)
    {
        validate([
            'amount' => 'required|numeric',
        ]);

        $chest = db()->prepare("SELECT id, productID FROM Chests WHERE id = ? AND accountID = ? AND isLocked = ? AND status = ?");
        $chest->execute(array($id, auth()->user()->id(), 0, 0));
        $chest = $chest->fetch();
				
				if (!$chest) abort_404();
	    
		    $variables = db()->prepare("SELECT V.*, CV.value FROM ChestProductVariableValues CV INNER JOIN StoreVariables V ON V.id = CV.variableID WHERE CV.chestID = ?");
		    $variables->execute(array($chest["id"]));
		    $chest["variables"] = $variables->fetchAll(PDO::FETCH_ASSOC);
		    
		    $similarChests = db()->prepare("SELECT C.id, C.productID FROM Chests C INNER JOIN Products P ON C.productID = P.id WHERE C.accountID = ? AND C.status = ? AND C.isLocked = ? AND P.id = ? AND C.id != ?");
		    $similarChests->execute(array(auth()->user()->id(), 0, 0, $chest["productID"], $chest["id"]));
		    $similarChests = $similarChests->fetchAll(PDO::FETCH_ASSOC);
		    $availableChests = [$chest["id"]];
		    foreach ($similarChests as $similarChest) {
			    $variables = db()->prepare("SELECT V.*, CV.value FROM ChestProductVariableValues CV INNER JOIN StoreVariables V ON V.id = CV.variableID WHERE CV.chestID = ?");
			    $variables->execute(array($similarChest["id"]));
			    $variables = $variables->fetchAll(PDO::FETCH_ASSOC);
			    
			    if (json_encode($chest["variables"]) == json_encode($variables)) {
				    $availableChests[] = $similarChest["id"];
			    }
		    }
		    $similarChests = null; // Free memory
	      $amount = count($availableChests);
	    
		    if ($amount >= input("amount")) {
			    $product = db()->prepare("SELECT P.*, PC.name as categoryName FROM Products P INNER JOIN ProductCategories PC ON P.categoryID = PC.id WHERE P.id = ?");
			    $product->execute(array($chest["productID"]));
			    $product = $product->fetch();
					
					if (!$product) abort_404();
			    
			    $deliverList = [];
			    $availableChests = array_slice($availableChests, 0, input("amount"));
			    $variablesForDelivery = [];
			    foreach ($chest["variables"] as $variable) {
				    $variablesForDelivery[$variable["identifier"]] = $variable["value"];
			    }
			    
			    foreach ($availableChests as $availableChestID) {
				    // Lock chest items to prevent duplication
				    $lockTheChest = db()->prepare("UPDATE Chests SET isLocked = ? WHERE id = ? AND accountID = ?");
				    $lockTheChest->execute(array(1, $availableChestID, auth()->user()->id()));
				    
				    // Add to deliver list
				    $deliverList[] = [
					    'id' => $product["id"],
					    'quantity' => 1,
					    'variables' => $variablesForDelivery,
					    'chestID' => $availableChestID
				    ];
			    }
			    
			    // Deliver product
			    DeliveryService::deliver(
				    $deliverList,
				    auth()->user()->id(),
				    "chest",
				    "0",
			    );
			    
			    // Unlock chest items
			    foreach ($availableChests as $availableChestID) {
				    $updateChest = db()->prepare("UPDATE Chests SET isLocked = ?, status = ? WHERE id = ? AND accountID = ? AND status = ?");
				    $updateChest->execute(array(0, 1, $availableChestID, auth()->user()->id(), 0));
				    
				    $insertChestHistory = db()->prepare("INSERT INTO ChestsHistory (accountID, chestID, type, creationDate) VALUES (?, ?, ?, ?)");
				    $insertChestHistory->execute(array(auth()->user()->id(), $availableChestID, 1, datetime()));
			    }
			    
			    return back()->flash("success", t__('The product has been successfully delivered! Have fun!'));
		    } else {
			    return back()->flash("error", t__('You can receive a maximum of %amount%!', ['%amount%' => $amount]));
		    }
    }
	
		public function logs()
		{
			SeoService::set('chest.logs');
			
			$logs = db()->prepare("SELECT CH.*, P.name as productName, PC.id as categoryID, PC.name as categoryName, OA.realname as otherAccountDisplayName FROM ChestsHistory CH INNER JOIN Chests C ON CH.chestID = C.id INNER JOIN Products P ON C.productID = P.id INNER JOIN ProductCategories PC ON P.categoryID = PC.id LEFT JOIN Accounts OA ON OA.id = CH.otherAccountID WHERE CH.accountID = ? ORDER BY CH.id DESC LIMIT 50");
			$logs->execute(array(auth()->user()->id()));
			$logs = array_map(function ($item) {
				$categoryList = CategoryService::getCategoryPath($item["categoryID"]);
				$item["categoryList"] = $categoryList !== null ? implode(' / ', $categoryList) : '';
				
				return $item;
			}, $logs->fetchAll());
			
			return $this->view('chest.logs', compact('logs'));
		}
}