<?php
declare(strict_types=1);

namespace Controllers;

use Helpers\Auth;
use Helpers\Request;
use Helpers\Response;
use Repositories\AdminCatalogRepository;

final class AdminCatalogController
{
    private function admin(): void
    {
        $u = Auth::requireUser();
        if (!Auth::isAdmin($u)) throw new \RuntimeException('Admin access required');
    }
public function uploadImage(): never
{
    $this->guard(function () {
        if (empty($_FILES['image'])) throw new \RuntimeException('No file uploaded');
        $file = $_FILES['image'];
        if ($file['error'] !== UPLOAD_ERR_OK) throw new \RuntimeException('Upload error');
        $allowed = ['image/jpeg','image/png','image/webp','image/gif'];
        if (!in_array($file['type'], $allowed, true)) throw new \RuntimeException('Invalid file type');
        if ($file['size'] > 5 * 1024 * 1024) throw new \RuntimeException('File too large (max 5MB)');

        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $filename = uniqid('img_', true) . '.' . strtolower($ext);
        $uploadDir = __DIR__ . '/../public/uploads/products/';
        if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
        if (!move_uploaded_file($file['tmp_name'], $uploadDir . $filename)) throw new \RuntimeException('Failed to save file');

        $baseUrl = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
        Response::success(['url' => $baseUrl . '/uploads/products/' . $filename]);
    });
}
    public function dashboard(): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->dashboard())); }
    public function leads(): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->leads())); }
    public function deliveryZones(): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->deliveryZones())); }
    public function saveDeliveryZone(): never { $this->guard(function(){ $d=Request::input(); foreach (['pincode','city','state','delivery_charge','delivery_estimate_days'] as $f) if (!isset($d[$f]) || $d[$f] === '') throw new \RuntimeException("$f is required"); (new AdminCatalogRepository())->upsertDeliveryZone($d); Response::success([], 'Delivery zone saved'); }); }

    public function categories(): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->categories())); }
    public function createCategory(): never { $this->guard(function(){ $d=$this->validateCategory(Request::input()); $id=(new AdminCatalogRepository())->createCategory($d); Response::success(['id'=>$id], 'Category created', 201); }); }
    public function updateCategory(string $id): never { $this->guard(function() use($id){ $d=$this->validateCategory(Request::input()); (new AdminCatalogRepository())->updateCategory((int)$id,$d); Response::success([], 'Category updated'); }); }
    public function deleteCategory(string $id): never { $this->guard(function() use($id){ (new AdminCatalogRepository())->deleteCategory((int)$id); Response::success([], 'Category disabled'); }); }

    public function products(): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->products(Request::query()))); }
    public function product(string $id): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->product((int)$id))); }
    public function createProduct(): never { $this->guard(function(){ $d=$this->validateProduct(Request::input()); $id=(new AdminCatalogRepository())->createProduct($d); Response::success(['id'=>$id], 'Product created', 201); }); }
    public function updateProduct(string $id): never { $this->guard(function() use($id){ $d=$this->validateProduct(Request::input()); (new AdminCatalogRepository())->updateProduct((int)$id,$d); Response::success([], 'Product updated'); }); }
    public function deleteProduct(string $id): never { $this->guard(function() use($id){ (new AdminCatalogRepository())->deleteProduct((int)$id); Response::success([], 'Product disabled'); }); }

    public function blogs(): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->blogs(Request::query()))); }
    public function blog(string $id): never { $this->guard(fn() => Response::success((new AdminCatalogRepository())->blog((int)$id))); }
    public function createBlog(): never { $this->guard(function(){ $d=$this->validateBlog(Request::input()); $id=(new AdminCatalogRepository())->createBlog($d); Response::success(['id'=>$id], 'Blog created', 201); }); }
    public function updateBlog(string $id): never { $this->guard(function() use($id){ $d=$this->validateBlog(Request::input()); (new AdminCatalogRepository())->updateBlog((int)$id,$d); Response::success([], 'Blog updated'); }); }
    public function deleteBlog(string $id): never { $this->guard(function() use($id){ (new AdminCatalogRepository())->deleteBlog((int)$id); Response::success([], 'Blog moved to draft'); }); }

    private function guard(callable $fn): never
    {
        try { $this->admin(); $fn(); }
        catch (\RuntimeException $e) { Response::error($e->getMessage(), str_contains($e->getMessage(), 'Admin') || str_contains($e->getMessage(), 'Authentication') ? 401 : 422); }
        catch (\Throwable $e) { Response::error('Admin operation failed', 500, ['detail'=>$e->getMessage()]); }
    }

    private function validateProduct(array $d): array
    {
        foreach (['category_id','name','slug','price'] as $f) if (!isset($d[$f]) || $d[$f] === '') throw new \RuntimeException("$f is required");
        if ((float)$d['price'] < 0) throw new \RuntimeException('price must be valid');
        if ((int)($d['stock_quantity'] ?? 0) < 0) throw new \RuntimeException('stock cannot be negative');
        $d['status'] = in_array($d['status'] ?? 'active', ['active','inactive','draft'], true) ? ($d['status'] ?? 'active') : 'draft';
        return $d;
    }

    private function validateCategory(array $d): array
    {
        foreach (['name','slug'] as $f) if (empty($d[$f])) throw new \RuntimeException("$f is required");
        $d['status'] = in_array($d['status'] ?? 'active', ['active','inactive'], true) ? ($d['status'] ?? 'active') : 'active';
        return $d;
    }

    private function validateBlog(array $d): array
    {
        foreach (['title','slug','content'] as $f) if (empty($d[$f])) throw new \RuntimeException("$f is required");
        $d['status'] = in_array($d['status'] ?? 'draft', ['draft','published'], true) ? ($d['status'] ?? 'draft') : 'draft';
        return $d;
    }
}
