<?php

namespace App\Modules\Inventory\Services;

use App\Modules\Inventory\Contracts\ProductServiceInterface;
use App\Modules\Inventory\Models\Product;
use App\Modules\Inventory\Models\Category;
use App\Modules\Inventory\Models\Unit;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ProductService implements ProductServiceInterface
{
    /**
     * Upsert product from external POS source.
     *
     * @param array $data
     * @return Product
     */
    public function upsertFromPos(array $data)
    {
        return DB::transaction(function () use ($data) {
            $externalId = $data['external_pos_id'] ?? null;

            if (!$externalId) {
                throw new \Exception("External POS ID is required for syncing.");
            }

            // Try to find by external_pos_id
            $product = Product::where('external_pos_id', $externalId)->first();

            if (!$product) {
                // If not found, create new
                // Optional: Check SKU conflict if needed, but for now trust POS ID
                $product = new Product();
                $product->external_pos_id = $externalId;
            }

            // Map allowed fields
            $product->name = $data['name'];
            $product->barcode = $data['barcode'] ?? $product->barcode;
            $product->price = $data['price'] ?? 0;
            
            // Map newly added extended fields
            if (isset($data['brand'])) $product->brand = $data['brand'];
            if (isset($data['specification'])) $product->specification = $data['specification'];
            if (isset($data['cost_price'])) $product->cost_price = $data['cost_price'];
            if (isset($data['member_price'])) $product->member_price = $data['member_price'];
            if (isset($data['wholesale_price'])) $product->wholesale_price = $data['wholesale_price'];
            
            // Generate Code if missing (use code or external_id)
            if (empty($product->code)) {
                $product->code = $data['code'] ?? $product->external_pos_id;
            }
            
            // Handle Category — 每次同步都更新（若有傳入）
            if (!empty($data['category']) || empty($product->category_id)) {
                $categoryName = $data['category'] ?? '未分類';
                $category = Category::firstOrCreate(
                    ['name' => $categoryName],
                    ['code' => 'CAT-' . strtoupper(bin2hex(random_bytes(4)))]
                );
                $product->category_id = $category->id;
            }

            // Handle Base Unit — 每次同步都更新（若有傳入）
            if (!empty($data['unit']) || empty($product->base_unit_id)) {
                $unitName = $data['unit'] ?? '個';
                $unit = Unit::firstOrCreate(['name' => $unitName]);
                $product->base_unit_id = $unit->id;
            }
            
            $product->is_active = $data['is_active'] ?? true;
            
            $product->save();

            return $product;
        });
    }

    /**
     * 透過外部 POS ID 查找產品。
     *
     * @param string $externalPosId
     * @return Product|null
     */
    public function findByExternalPosId(string $externalPosId)
    {
        return Product::where('external_pos_id', $externalPosId)->first();
    }

    /**
     * 透過多個外部 POS ID 查找產品。
     *
     * @param array $externalPosIds
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function findByExternalPosIds(array $externalPosIds)
    {
        return Product::whereIn('external_pos_id', $externalPosIds)->get();
    }

    /**
     * 透過多個 ERP 商品代碼查找產品（供販賣機 API 使用）。
     *
     * @param array $codes
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function findByCodes(array $codes)
    {
        return Product::whereIn('code', $codes)->get();
    }

    public function createProduct(array $data)
    {
        if (empty($data['code'])) {
            $data['code'] = $this->generateRandomCode();
        }

        if (empty($data['barcode'])) {
            $data['barcode'] = $this->generateRandomBarcode();
        }

        return Product::create($data);
    }

    public function updateProduct(Product $product, array $data)
    {
        if (empty($data['code'])) {
            $data['code'] = $this->generateRandomCode();
        }

        if (empty($data['barcode'])) {
            $data['barcode'] = $this->generateRandomBarcode();
        }

        $product->update($data);
        return $product;
    }

    public function generateRandomCode()
    {
        $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $code = '';
        
        do {
            $code = '';
            for ($i = 0; $i < 8; $i++) {
                $code .= $characters[rand(0, strlen($characters) - 1)];
            }
        } while (Product::where('code', $code)->exists());

        return $code;
    }

    public function generateRandomBarcode()
    {
        $barcode = '';
        
        do {
            $barcode = '';
            for ($i = 0; $i < 13; $i++) {
                $barcode .= rand(0, 9);
            }
        } while (Product::where('barcode', $barcode)->exists());

        return $barcode;
    }

    public function findByBarcodeOrCode(?string $barcode, ?string $code)
    {
        $product = null;
        if (!empty($barcode)) {
            $product = Product::where('barcode', $barcode)->first();
        }
        if (!$product && !empty($code)) {
            $product = Product::where('code', $code)->first();
        }
        return $product;
    }
}
