<?php
/**
 * Product Management API
 * ----------------------
 * Handles CRUD for products with related images and variants.
 * Uses PDO + Transactions for data integrity.
 * Secure file uploads with validation.
 */

// --- BOOTSTRAPPING & CONFIGURATION ---
ini_set('display_errors', 1);
error_reporting(E_ALL);
header("Content-Type: application/json; charset=UTF-8");

require_once '../config/cors.php';
require_once '../config/database.php';

// --- CONSTANTS ---
define('PRODUCT_UPLOAD_DIR', __DIR__ . '/../uploads/products/');
define('MAX_FILE_SIZE', 50 * 1024 * 1024); // 50MB
define('MAX_IMAGE_COUNT', 10);

$allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

// --- DB CONNECTION ---
try {
    $database = new Database();
    $db = $database->getConnection();
} catch (Exception $e) {
    http_response_code(503);
    echo json_encode(['error' => 'Service unavailable. DB connection failed.']);
    exit();
}

// --- HELPERS ---
function sendJsonResponse($statusCode, $data) {
    http_response_code($statusCode);
    echo json_encode($data);
    exit();
}

function generateUuidV4() {
    return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand(0, 0xffff), mt_rand(0, 0xffff),
        mt_rand(0, 0xffff),
        mt_rand(0, 0x0fff) | 0x4000,
        mt_rand(0, 0x3fff) | 0x8000,
        mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
    );
}

function getImageUrl($imageName) {
    if (empty($imageName)) return null;
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https://" : "http://";
    $host = $_SERVER['HTTP_HOST'];
    $basePath = str_replace($_SERVER['DOCUMENT_ROOT'], '', realpath(PRODUCT_UPLOAD_DIR));
    return $protocol . $host . $basePath . '/' . $imageName;
}

function validateUploadedFiles($files, $maxCount, $maxSize, $allowedMimes) {
    if (empty($files) || (isset($files['error'][0]) && $files['error'][0] === UPLOAD_ERR_NO_FILE)) return;

    if (count($files['name']) > $maxCount) {
        throw new Exception("Max {$maxCount} images allowed.", 400);
    }

    foreach ($files['error'] as $key => $error) {
        if ($error !== UPLOAD_ERR_OK) {
            throw new Exception("File upload error: {$files['name'][$key]} (Code: {$error})", 400);
        }
        if ($files['size'][$key] > $maxSize) {
            throw new Exception("File too large: {$files['name'][$key]} (Max 50MB).", 400);
        }
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $files['tmp_name'][$key]);
        finfo_close($finfo);
        if (!in_array($mime, $allowedMimes)) {
            throw new Exception("Invalid file type: {$files['name'][$key]}", 400);
        }
    }
}

function deleteProductImages($db, $productId) {
    $stmt = $db->prepare("SELECT url FROM product_images WHERE product_id = :pid");
    $stmt->execute([':pid' => $productId]);
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $filePath = PRODUCT_UPLOAD_DIR . $row['url'];
        if (file_exists($filePath)) unlink($filePath);
    }
    $db->prepare("DELETE FROM product_images WHERE product_id = :pid")->execute([':pid' => $productId]);
}

function insertProductImages($db, $productId, $files) {
    if (empty($files) || (isset($files['error'][0]) && $files['error'][0] === UPLOAD_ERR_NO_FILE)) return;

    $stmt = $db->prepare("INSERT INTO product_images (product_id, url, position) VALUES (:pid, :url, :pos)");
    foreach ($files['name'] as $i => $name) {
        $ext = pathinfo($name, PATHINFO_EXTENSION);
        $newFile = uniqid("prod_" . substr($productId, 0, 8) . "_", true) . '.' . strtolower($ext);
        $dest = PRODUCT_UPLOAD_DIR . $newFile;

        if (move_uploaded_file($files['tmp_name'][$i], $dest)) {
            $stmt->execute([':pid' => $productId, ':url' => $newFile, ':pos' => $i]);
        }
    }
}

function handleProductVariants($db, $productId, $variants, $baseSku) {
    $db->prepare("DELETE FROM product_variants WHERE product_id = :pid")->execute([':pid' => $productId]);

    if (!empty($variants)) {
        $stmt = $db->prepare(
            "INSERT INTO product_variants (product_id, variant_name, price_diff, stock, sku) 
             VALUES (:pid, :vname, :pdiff, :stock, :sku)"
        );
        foreach ($variants as $variant) {
            $suffix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', $variant['variant_name']), 0, 4));
            $vsku = "{$baseSku}-{$suffix}";
            $stmt->execute([
                ':pid' => $productId,
                ':vname' => $variant['variant_name'],
                ':pdiff' => $variant['price_diff'] ?? 0,
                ':stock' => $variant['stock'] ?? 0,
                ':sku' => $vsku
            ]);
        }
    }
}

// --- ENSURE UPLOAD DIR EXISTS ---
if (!is_dir(PRODUCT_UPLOAD_DIR)) mkdir(PRODUCT_UPLOAD_DIR, 0775, true);

// --- ROUTING ---
$method = $_SERVER['REQUEST_METHOD'];

try {
    switch ($method) {
        case 'GET':    handleGetRequest($db); break;
        case 'POST':   handlePostRequest($db); break;
        case 'DELETE': handleDeleteRequest($db); break;
        default: sendJsonResponse(405, ['error' => 'Method not allowed']);
    }
} catch (Exception $e) {
    if ($db->inTransaction()) $db->rollBack();
    $code = in_array($e->getCode(), [400,404,405]) ? $e->getCode() : 500;
    sendJsonResponse($code, ['error' => $e->getMessage()]);
}

function handleGetRequest($db) {
    $id = filter_input(INPUT_GET, 'id', FILTER_DEFAULT);

    if ($id) {
        // --- SINGLE PRODUCT FETCHING (NO CHANGES NEEDED HERE) ---
        $stmt = $db->prepare("SELECT p.*, c.name as category_name 
                                FROM products p 
                                LEFT JOIN categories c ON p.category_id = c.id 
                                WHERE p.id = :id");
        $stmt->execute([':id' => $id]);
        $product = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$product) throw new Exception("Product not found", 404);

        $imgs = $db->prepare("SELECT id, url FROM product_images WHERE product_id = :id ORDER BY position ASC");
        $imgs->execute([':id' => $id]);
        $images = $imgs->fetchAll(PDO::FETCH_ASSOC);
        foreach ($images as &$img) $img['url'] = getImageUrl($img['url']);
        $product['images'] = $images;

        $vars = $db->prepare("SELECT * FROM product_variants WHERE product_id = :id");
        $vars->execute([':id' => $id]);
        $product['variants'] = $vars->fetchAll(PDO::FETCH_ASSOC);

        sendJsonResponse(200, $product);

    } else {
        // --- ALL PRODUCTS LISTING (UPDATED LOGIC) ---

        // 1. Fetch all products (added 'description' as requested)
        $sql = "SELECT p.id, p.name, p.brand, p.description, p.base_price, p.stock, p.is_active, 
                       c.name as category_name
                FROM products p 
                LEFT JOIN categories c ON p.category_id = c.id 
                ORDER BY p.created_at DESC";
        $stmt = $db->query($sql);
        $products = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (empty($products)) {
            sendJsonResponse(200, ['products' => []]);
            return;
        }

        // 2. Get all product IDs from the result
        $productIds = array_column($products, 'id');
        $placeholders = implode(',', array_fill(0, count($productIds), '?'));

        // 3. Fetch all images for those products in a single query
        $imgSql = "SELECT product_id, url FROM product_images WHERE product_id IN ($placeholders) ORDER BY position ASC";
        $imgStmt = $db->prepare($imgSql);
        $imgStmt->execute($productIds);
        $allImages = $imgStmt->fetchAll(PDO::FETCH_ASSOC);

        // 4. Group images by product_id for easy lookup
        $imagesByProductId = [];
        foreach ($allImages as $img) {
            $imagesByProductId[$img['product_id']][] = getImageUrl($img['url']);
        }

        // 5. Attach images to each product
        foreach ($products as &$p) {
            // Assign all images for the current product
            $p['images'] = $imagesByProductId[$p['id']] ?? [];
            
            // Assign the first image as the main_image
            $p['main_image'] = $p['images'][0] ?? null;
        }

        sendJsonResponse(200, ['products' => $products]);
    }
}
function handlePostRequest($db) {
    if (!isset($_POST['product_data'])) throw new Exception('Missing product_data field', 400);
    $data = json_decode($_POST['product_data'], true);
    if (json_last_error() !== JSON_ERROR_NONE) throw new Exception('Invalid JSON in product_data', 400);

    $files = $_FILES['images'] ?? null;
    validateUploadedFiles($files, MAX_IMAGE_COUNT, MAX_FILE_SIZE, $GLOBALS['allowedMimeTypes']);

    $db->beginTransaction();

    if (!empty($data['id'])) {
        // --- UPDATE ---
        $pid = $data['id'];
        $check = $db->prepare("SELECT sku FROM products WHERE id = :id");
        $check->execute([':id' => $pid]);
        $sku = $check->fetchColumn();
        if (!$sku) throw new Exception("Product not found", 404);

        $fields = ['name','brand','description','base_price','stock','category_id','is_active'];
        $updates = [];
        $params = [':id' => $pid];

        foreach ($fields as $f) {
            if (isset($data[$f])) {
                $updates[] = "{$f} = :{$f}";
                $params[":{$f}"] = ($f === 'is_active') ? (int)$data[$f] : $data[$f];
            }
        }

        if ($updates) {
            $sql = "UPDATE products SET ".implode(",", $updates)." WHERE id = :id";
            $stmt = $db->prepare($sql);
            $stmt->execute($params);
        }

        if ($files && (!isset($files['error'][0]) || $files['error'][0] !== UPLOAD_ERR_NO_FILE)) {
            deleteProductImages($db, $pid);
            insertProductImages($db, $pid, $files);
        }

        if (isset($data['variants'])) handleProductVariants($db, $pid, $data['variants'], $sku);

        $db->commit();
        sendJsonResponse(200, ['message' => 'Product updated']);
    } else {
        // --- CREATE ---
        foreach (['name','brand','base_price','category_id'] as $f) {
            if (empty($data[$f])) throw new Exception("Missing field: $f", 400);
        }

        $pid = generateUuidV4();
        $sku = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/','',$data['name']),0,4).uniqid());

        $stmt = $db->prepare("INSERT INTO products 
            (id,name,brand,description,base_price,sku,stock,category_id,is_active) 
            VALUES (:id,:name,:brand,:desc,:price,:sku,:stock,:cid,:active)");
        $ok = $stmt->execute([
            ':id'=>$pid, ':name'=>$data['name'], ':brand'=>$data['brand'],
            ':desc'=>$data['description']??null, ':price'=>$data['base_price'],
            ':sku'=>$sku, ':stock'=>$data['stock']??0,
            ':cid'=>$data['category_id'], ':active'=>isset($data['is_active'])?(int)$data['is_active']:1
        ]);

        if (!$ok) throw new Exception("Failed to create product", 500);

        insertProductImages($db, $pid, $files);
        handleProductVariants($db, $pid, $data['variants']??[], $sku);

        $db->commit();
        sendJsonResponse(201, ['message'=>'Product created','product_id'=>$pid]);
    }
}

function handleDeleteRequest($db) {
    $id = filter_input(INPUT_GET, 'id', FILTER_DEFAULT);
    if (!$id) throw new Exception("Product ID required (?id=...)", 400);

    $db->beginTransaction();
    $chk = $db->prepare("SELECT id FROM products WHERE id = :id");
    $chk->execute([':id'=>$id]);
    if ($chk->rowCount()===0) throw new Exception("Product not found", 404);

    deleteProductImages($db, $id);
    $db->prepare("DELETE FROM product_variants WHERE product_id = :id")->execute([':id'=>$id]);
    $db->prepare("DELETE FROM products WHERE id = :id")->execute([':id'=>$id]);

    $db->commit();
    sendJsonResponse(200, ['message'=>'Product deleted']);
}
?>
