<?php

namespace Core\App\Controllers;

use Core\App\Models\CategoryModel;
use Core\App\Models\ProductModel;
use Core\App\Models\ProductSections;
use Core\App\Services\UploadService;
use Core\App\Services\AutoSeoService;
use Core\App\Services\GeminiImageService;
use Core\System\Request;
use Core\System\Response;

class ProductController
{
    protected ProductModel $products;
    protected ProductSections $sections;
    protected UploadService $uploads;
    protected AutoSeoService $autoSeo;

    public function __construct()
    {
        $this->products = new ProductModel();
        $this->sections = new ProductSections();
        $this->uploads  = new UploadService(ROOT_PATH . '/uploads', '/uploads');
        $this->autoSeo  = new AutoSeoService();
    }

    public function index()
    {
        $page    = max(1, (int)($_GET['page'] ?? 1));
        $perPage = 30;
        $filters = [];

        if (!empty($_GET['search'])) {
            $filters['search'] = $_GET['search'];
        }
        if (!empty($_GET['category_id'])) {
            $filters['category_id'] = (int)$_GET['category_id'];
        }

        $paginated    = $this->products->getPaginated($page, $perPage, $filters);
        $products     = $paginated['items'];
        $totalPages   = $paginated['pages'];
        $totalProducts = $paginated['total'];

        view_admin('products/index', [
            'products'      => $products,
            'totalPages'    => $totalPages,
            'totalProducts' => $totalProducts,
            'currentPage'   => $page,
        ]);
    }

    public function create()
    {
        view_admin('products/create', [
            'categories' => (new CategoryModel())->getAll(),
            'autoSeoEnabled' => $this->autoSeo->isEnabled(),
            'geminiImageGeneration' => $this->getGeminiImageGenerationConfig(),
        ]);
    }

    public function edit($id)
    {
        $id = (int) $id;
        $item = $this->products->getFullById($id);
        if (!$item) {
            Response::redirect('/admin/products');
        }

        view_admin('products/edit', [
            'item'       => $item,
            'categories' => (new CategoryModel())->getAll(),
            'autoSeoEnabled' => $this->autoSeo->isEnabled(),
            'geminiImageGeneration' => $this->getGeminiImageGenerationConfig(),
        ]);
    }

    public function store()
    {
        $data = $_POST;
        if (empty($data['slug']) && !empty($data['title'])) {
            $data['slug'] = $this->makeSlug($data['title']);
        }

        $data['status']      = $data['status'] ?? 'active';
        $data['is_featured'] = !empty($data['is_featured']) ? 1 : 0;
        $data['badge_text']  = $data['badge_text'] ?? null;
        $data['sale_price']  = $data['sale_price'] ?? null;

        if (!empty($_FILES['featured_image']['name'])) {
            $data['featured_image'] = $this->uploads->storeImage($_FILES['featured_image'], 'products');
        }

        $data['images'] = !empty($_FILES['images']['name'][0])
            ? $this->uploads->storeImages($_FILES['images'], 'products')
            : [];
        $data['images'] = $this->mergeGeneratedImagesIntoGallery($data['images'], $_POST);

        $data['variants'] = $this->decodeJsonField($data['variants'] ?? null, []);
        $data['layout']   = $this->decodeJsonField($data['layout']   ?? null, null);
        $data['offers']   = $this->decodeJsonField($data['offers']   ?? null, null);
        $data = $this->hydrateSeoPayload($data);
        $data = $this->applyAutoSeoSafely($data, true);

        $id = $this->products->createFull($data);

        $variantStock = $this->decodeJsonField($data['variant_stock'] ?? null, []);
        if (is_array($variantStock) && !empty($variantStock)) {
            $this->products->syncVariantStock($id, $variantStock);
        }

        $this->checkStockAlert($id);
        Response::redirect('/admin/products');
    }

    public function update($id)
    {
        $id = (int) $id;
        $data = Request::input();
        $current = $this->products->getById($id);
        if (!$current) {
            Response::redirect('/admin/products');
        }

        if (empty($data['slug']) && !empty($data['title'])) {
            $data['slug'] = $this->makeSlug($data['title']);
        }

        $data['is_featured'] = !empty($data['is_featured']) ? 1 : 0;

        if (!empty($_FILES['featured_image']['name'])) {
            $data['featured_image'] = $this->uploads->storeImage($_FILES['featured_image'], 'products');
            $this->uploads->deleteByWebPath($current['featured_image'] ?? null);
        } else {
            $data['featured_image'] = $current['featured_image'] ?? null;
        }

        $existingImages = $current['images'] ?? [];
        if (!empty($data['removed_images']) && is_array($data['removed_images'])) {
            foreach ($data['removed_images'] as $removedImage) {
                $this->uploads->deleteByWebPath($removedImage);
            }
            $existingImages = array_values(array_diff($existingImages, $data['removed_images']));
        }

        $newImages = !empty($_FILES['images']['name'][0])
            ? $this->uploads->storeImages($_FILES['images'], 'products')
            : [];
        $data['images'] = $this->mergeGeneratedImagesIntoGallery(array_values(array_merge($existingImages, $newImages)), $data);
        $data['variants'] = $this->decodeJsonField($data['variants'] ?? null, []);
        $data['layout']   = $this->decodeJsonField($data['layout']   ?? null, null);
        $data['offers']   = $this->decodeJsonField($data['offers']   ?? null, null);
        $data = $this->hydrateSeoPayload($data, $current);
        $data = $this->applyAutoSeoSafely($data, false);

        $this->products->updateFull($id, $data);

        $variantStock = $this->decodeJsonField($data['variant_stock'] ?? null, []);
        if (is_array($variantStock) && !empty($variantStock)) {
            $this->products->syncVariantStock($id, $variantStock);
        }

        $this->checkStockAlert($id);
        Response::redirect('/admin/products');
    }

    public function delete($id)
    {
        if (strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET')) !== 'POST') {
            http_response_code(405);
            exit('Method Not Allowed');
        }

        $id = (int) $id;
        $current = $this->products->getById($id);
        if ($current) {
            $this->uploads->deleteByWebPath($current['featured_image'] ?? null);
            foreach (($current['images'] ?? []) as $image) {
                $this->uploads->deleteByWebPath($image);
            }
        }

        $this->products->deleteFull($id);
        $this->sections->deleteByProduct($id);
        Response::redirect('/admin/products');
    }

    private function decodeJsonField($value, $default)
    {
        if (!is_string($value) || trim($value) === '') {
            return $default;
        }

        $decoded = json_decode($value, true);
        return json_last_error() === JSON_ERROR_NONE ? $decoded : $default;
    }

    private function makeSlug(string $text): string
    {
        $text = trim(mb_strtolower($text));
        $text = preg_replace('/[^\p{L}\p{N}]+/u', '-', $text);
        return trim($text, '-') ?: 'product';
    }

    private function applyAutoSeoSafely(array $data, bool $allowRemoteAi = false): array
    {
        try {
            return $this->autoSeo->applyToProductData($data, ['allow_remote_ai' => $allowRemoteAi]);
        } catch (\Throwable $e) {
            return $data;
        }
    }

    private function hydrateSeoPayload(array $data, ?array $current = null): array
    {
        $fields = [
            'meta_title',
            'meta_description',
            'og_title',
            'og_description',
            'og_image',
            'schema_brand',
            'schema_gtin',
            'schema_mpn',
        ];

        $payload = [];
        $rawPayload = $data['seo_share_payload'] ?? null;
        if (is_string($rawPayload) && trim($rawPayload) !== '') {
            $decoded = json_decode($rawPayload, true);
            if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
                $payload = $decoded;
            }
        }

        foreach ($fields as $field) {
            if (array_key_exists($field, $data)) {
                $data[$field] = is_string($data[$field]) ? trim($data[$field]) : $data[$field];
                continue;
            }

            if (array_key_exists($field, $payload)) {
                $data[$field] = is_string($payload[$field]) ? trim($payload[$field]) : $payload[$field];
                continue;
            }

            if ($current !== null && array_key_exists($field, $current)) {
                $data[$field] = $current[$field];
            }
        }

        unset($data['seo_share_payload']);

        return $data;
    }

    private function getGeminiImageGenerationConfig(): array
    {
        try {
            return (new GeminiImageService())->getUiConfig();
        } catch (\Throwable $e) {
            return [
                'has_api_key' => false,
                'enabled' => false,
                'model' => '',
                'available' => false,
            ];
        }
    }

    private function mergeGeneratedImagesIntoGallery(array $images, array $input): array
    {
        $generatedImages = $input['generated_images'] ?? [];
        if (!is_array($generatedImages)) {
            $generatedImages = [];
        }

        $discardedImages = $input['discard_generated_images'] ?? [];
        if (!is_array($discardedImages)) {
            $discardedImages = [];
        }

        $cleanGenerated = [];
        foreach ($generatedImages as $path) {
            $path = trim((string)$path);
            if ($path === '' || strpos($path, '/uploads/products/generated/') !== 0) {
                continue;
            }
            $cleanGenerated[] = $path;
        }

        foreach ($discardedImages as $path) {
            $this->uploads->deleteByWebPath((string)$path);
        }

        return array_values(array_unique(array_merge($images, $cleanGenerated)));
    }

    private function checkStockAlert(int $productId): void
    {
        try {
            if (!$this->products->isBelowAlert($productId)) {
                return;
            }

            $product = $this->products->getById($productId);
            if (!$product) {
                return;
            }

            $db = db();
            $stmt = $db->prepare("SELECT 1 FROM admin_notifications WHERE type = 'stock_alert' AND reference_id = ? AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR) LIMIT 1");
            $stmt->execute([$productId]);
            if ($stmt->fetchColumn()) {
                return;
            }

            $db->prepare("INSERT INTO admin_notifications (type, reference_id, title, is_read, archived) VALUES ('stock_alert', ?, ?, 0, 0)")
                ->execute([$productId, __('notifications.stock_alert', 'Low stock warning') . ': ' . $product['title']]);
        } catch (\Throwable $e) {
        }
    }
}
