<?php

namespace Dashboard\Controllers\Store;

use Curl\Curl;
use Dashboard\Core\Controller;
use Dashboard\Services\CategoryService;
use Dashboard\Services\ProductService;
use PDO;

class OrderController extends Controller
{
    public function __construct()
    {
        abort_perm('MANAGE_STORE');
    }

    public function index()
    {
        if (isset($_GET["page"])) {
            if (!is_numeric($_GET["page"])) {
                $_GET["page"] = 1;
            }
            $page = intval(get("page"));
        } else {
            $page = 1;
        }

        $visiblePageCount = 5;
        $limit = 50;
	    
		    $status = null;
		    if (isset($_GET["status"])) {
			    $status = get("status");
		    }

        $orders = db()->query("SELECT count(id) FROM Orders");
        $itemsCount = $orders->fetchColumn();
        $pageCount = ceil($itemsCount / $limit);
        if ($page > $pageCount) {
            $page = 1;
        }
        $visibleItemsCount = $page * $limit - $limit;
        $orders = db()->query("SELECT O.*, A.username, A.realname FROM Orders O INNER JOIN Accounts A ON O.accountID = A.id ORDER BY O.id DESC LIMIT $visibleItemsCount, $limit");

        if (isset($_GET["search"])) {
            if (get("search") != null) {
                $orders = db()->prepare("SELECT O.*, A.username, A.realname FROM Orders O INNER JOIN Accounts A ON O.accountID = A.id WHERE (A.realname LIKE :search OR A.username LIKE :search) ORDER BY O.id DESC");
                $orders->execute(array(
                    "search" => '%' . get("search") . '%'
                ));
            }
        } else if (isset($_GET["status"])) {
	        if ($status == "success") {
		        $orders = db()->query("SELECT O.*, A.username, A.realname FROM Orders O INNER JOIN Accounts A ON O.accountID = A.id WHERE O.status = 1 ORDER BY O.id DESC");
	        }
	        if ($status == "waiting") {
		        $orders = db()->query("SELECT O.*, A.username, A.realname FROM Orders O INNER JOIN Accounts A ON O.accountID = A.id WHERE O.status = 0 AND O.paymentAPI = 'manual' ORDER BY O.id DESC");
	        }
	        if ($status == "error") {
		        $orders = db()->query("SELECT O.*, A.username, A.realname FROM Orders O INNER JOIN Accounts A ON O.accountID = A.id WHERE O.status = 0 AND O.paymentAPI != 'manual' ORDER BY O.id DESC");
	        }
        }

        $orders = array_map(function ($order) {
	          $paymentGateway = db()->prepare("SELECT * FROM PaymentGateways WHERE slug = ?");
		        $paymentGateway->execute(array($order["paymentAPI"]));
		        $paymentGateway = $paymentGateway->fetch(PDO::FETCH_ASSOC);

            $order["paymentGateway"] = $paymentGateway ? $paymentGateway["name"] : $order["paymentAPI"];

            return $order;
        }, $orders->fetchAll(PDO::FETCH_ASSOC));

        return view('store.orders.index', compact('orders', 'page', 'visiblePageCount', 'pageCount'));
    }
		
		public function create()
		{
			$categories = db()->query("SELECT id, name, parentID FROM ProductCategories ORDER BY priority DESC");
			$categories = $categories->fetchAll(PDO::FETCH_ASSOC);
			
			$products = db()->query("SELECT id, name, categoryID, price, discountedPrice, discountExpiryDate FROM Products ORDER BY priority DESC");
			$products = $products->fetchAll(PDO::FETCH_ASSOC);
			
			$listingTree = ProductService::buildTree($categories, $products);
			
			return view('store.orders.create', compact('listingTree'));
		}
	
		public function store()
		{
			validate([
				'userID' => 'required|numeric',
				'total' => 'required',
				'status' => 'required|in:success,waiting',
				'product' => 'required|array',
				'quantity' => 'required|array',
				'unitPrice' => 'required|array',
			]);
			
			$total = input('total');
			
			$insertOrder = db()->prepare("INSERT INTO Orders (accountID, total, subtotal, discount, tax, earnings, cashback, credit, type, status, paymentAPI, paymentID, creationDate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
			$insertOrder->execute([
				post('userID'),
				$total,
				$total,
				0,
				0,
				$total,
				0,
				0,
				1,
				0,
				"manual",
				"",
				datetime()
			]);
			$orderID = db()->lastInsertId();
			
			// add order items
			foreach ($_POST['product'] as $key => $productID) {
				$productID = strip_tags($productID);
				$quantity = strip_tags($_POST['quantity'][$key]);
				$unitPrice = strip_tags($_POST['unitPrice'][$key]);
				
				$insertOrderProduct = db()->prepare("INSERT INTO OrderProducts (orderID, productID, quantity, unitPrice) VALUES (?, ?, ?, ?)");
				$insertOrderProduct->execute([$orderID, $productID, $quantity, $unitPrice]);
			}
			
			if (input('status') == 'success') {
				$curl = new Curl();
				$curl->post(websiteUrl() . "/callback/manual", [
					"apiKey" => settings('apiKey'),
					"orderID" => $orderID,
					"paymentID" => "MANUAL-$orderID"
				]);
			}
			
			redirect(url('dashboard.store.orders.show', ['id' => $orderID]));
		}

    public function show($id)
    {
        $order = db()->prepare("SELECT O.*, A.username, A.realname, A.credit as userCredits FROM Orders O INNER JOIN Accounts A ON A.id = O.accountID WHERE O.id = ?");
        $order->execute(array($id));
        $order = $order->fetch();

        if (!$order) return view('404');
	    
		    // Show Tebex order if Tebex module is enabled
		    if (!moduleIsDisabled('tebex_store')) {
			    return self::showTebexOrder($order);
		    }

        $orderProducts = null;
        $commandLogs = null;

        if ($order["type"] == 1) {
	        $orderProducts = db()->prepare("SELECT OP.id as orderProductID, P.id, P.name, P.categoryID, PC.name as categoryName, OP.quantity, OP.unitPrice FROM OrderProducts OP INNER JOIN Products P ON OP.productID = P.id INNER JOIN ProductCategories PC ON PC.id = P.categoryID WHERE OP.orderID = ?");
	        $orderProducts->execute(array($order["id"]));
	        $orderProducts = array_map(function ($orderProduct) {
		        $orderProductVariableValues = db()->prepare("SELECT V.*, OPVV.value FROM OrderProductVariableValues OPVV INNER JOIN StoreVariables V ON V.id = OPVV.variableID  WHERE orderProductID = ?");
		        $orderProductVariableValues->execute([$orderProduct["orderProductID"]]);
		        $orderProduct["variables"] = $orderProductVariableValues->fetchAll(PDO::FETCH_ASSOC);
		        
		        return $orderProduct;
	        }, $orderProducts->fetchAll(PDO::FETCH_ASSOC));
					
	        global $categoryList;
	        $orderProducts = CategoryService::getCategoryList($orderProducts, array_column($orderProducts, "categoryID"));
	        
	        $commandLogs = db()->prepare("SELECT CL.id, CL.command, S.name as serverName, P.name as productName, CL.status, CL.updatedAt FROM CommandLogs CL INNER JOIN ProductCommands PC ON PC.id = CL.commandID INNER JOIN Servers S ON S.id = PC.serverID INNER JOIN Products P ON P.id = PC.productID WHERE CL.dataType = ? AND CL.dataID = ?");
	        $commandLogs->execute(array('order', $order["id"]));
	        $commandLogs = $commandLogs->fetchAll(PDO::FETCH_ASSOC);
        } elseif ($order["type"] == 2) {
	        $orderProduct = db()->prepare("SELECT * FROM OrderCredits WHERE orderID = ?");
	        $orderProduct->execute(array($order["id"]));
	        $orderProduct = $orderProduct->fetch(PDO::FETCH_ASSOC);
					
          $orderProducts = [];
          $orderProducts[] = [
            "name" => credits($orderProduct["amount"]),
            "quantity" => 1,
            "unitPrice" => $order["earnings"]
          ];
        } elseif ($order["type"] == 3) {
            $orderProducts = db()->prepare("SELECT CP.* FROM OrderCreditPackages OCP INNER JOIN CreditPackages CP ON OCP.packageID = CP.id WHERE OCP.orderID = ?");
            $orderProducts->execute(array($order["id"]));
            $orderProducts = array_map(function ($orderProduct) use ($order) {
							$orderProduct["quantity"] = 1;
	            $orderProduct["unitPrice"] = $order["earnings"];
							return $orderProduct;
            }, $orderProducts->fetchAll(PDO::FETCH_ASSOC));
        }
				
				// Creator Code Logs
	      $orderCreatorCode = db()->prepare("SELECT CC.code, OCC.codeID, OCC.discount, OCC.revenueShare FROM OrderCreatorCodes OCC INNER JOIN CreatorCodes CC ON CC.id = OCC.codeID WHERE OCC.orderID = ?");
	      $orderCreatorCode->execute(array($order["id"]));
	      $orderCreatorCode = $orderCreatorCode->fetch(PDO::FETCH_ASSOC);
				$order["creatorCode"] = null;
				if ($orderCreatorCode) {
					$order["creatorCode"] = $orderCreatorCode;
				}
	    
	      $paymentGateway = db()->prepare("SELECT * FROM PaymentGateways WHERE slug = ?");
		    $paymentGateway->execute(array($order["paymentAPI"]));
		    $paymentGateway = $paymentGateway->fetch(PDO::FETCH_ASSOC);

        $order["paymentGateway"] = $paymentGateway ? $paymentGateway["name"] : $order["paymentAPI"];

        return view('store.orders.show', compact('order', 'orderProducts', 'commandLogs'));
    }
		
		public function showTebexOrder($order)
		{
			$orderProducts = db()->prepare("SELECT P.id, P.name, OP.quantity, OP.unitPrice FROM OrderProducts OP INNER JOIN TebexProducts P ON OP.productID = P.id WHERE OP.orderID = ?");
			$orderProducts->execute(array($order["id"]));
			$orderProducts = $orderProducts->fetchAll(PDO::FETCH_ASSOC);
			
			return view('store.orders.show', compact('order', 'orderProducts'));
		}

    public function complete($id)
    {
      $curl = new Curl();
      $curl->post(websiteUrl() . "/callback/manual", [
        "apiKey" => settings('apiKey'),
        "orderID" => $id,
        "paymentID" => "MANUAL-$id"
      ]);
      return back()->flash('success', t__('Order completed successfully!'));
    }

    public function destroy($id)
    {
        $deleteStoreHistory = db()->prepare("DELETE FROM Orders WHERE id = ?");
        $deleteStoreHistory->execute(array($id));
        return back();
    }
}