<?php

namespace App\Modules\Inventory\Imports;

use App\Modules\Inventory\Models\Category;
use App\Modules\Inventory\Models\Product;
use App\Modules\Inventory\Models\Unit;
use Illuminate\Validation\Rule;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;

class ProductImport implements ToModel, WithHeadingRow, WithValidation, WithMapping
{
    private $categories;
    private $units;

    public function __construct()
    {
        // 禁用標題格式化，保留中文標題
        HeadingRowFormatter::default('none');

        // 快取所有類別與單位，避免 N+1 查詢
        $this->categories = Category::pluck('id', 'name');
        $this->units = Unit::pluck('id', 'name');
    }

    /**
    * @param mixed $row
    *
    * @return array
    */
    public function map($row): array
    {
        // 強制將代號與條碼轉為字串，避免純數字被當作整數處理導致 max:5 驗證錯誤
        if (isset($row['商品代號'])) {
            $row['商品代號'] = (string) $row['商品代號'];
        }
        if (isset($row['條碼'])) {
            $row['條碼'] = (string) $row['條碼'];
        }
        
        return $row;
    }

    /**
    * @param array $row
    *
    * @return \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        // 查找關聯 ID
        $categoryId = $this->categories[$row['類別名稱']] ?? null;
        $baseUnitId = $this->units[$row['基本單位']] ?? null;
        $largeUnitId = isset($row['大單位']) ? ($this->units[$row['大單位']] ?? null) : null;

        // 若必要關聯找不到，理論上 Validation 會攔截，但此處做防禦性編程
        if (!$categoryId || !$baseUnitId) {
            return null;
        }

        $code = $row['商品代號'] ?? null;
        $barcode = $row['條碼'] ?? null;

        // Upsert 邏輯：優先以條碼查找，次之以商品代號查找
        $product = null;
        if (!empty($barcode)) {
            $product = Product::where('barcode', $barcode)->first();
        }

        if (!$product && !empty($code)) {
            $product = Product::where('code', $code)->first();
        }

        $data = [
            'name' => $row['商品名稱'],
            'category_id' => $categoryId,
            'brand' => $row['品牌'] ?? null,
            'specification' => $row['規格'] ?? null,
            'base_unit_id' => $baseUnitId,
            'large_unit_id' => $largeUnitId,
            'conversion_rate' => $row['換算率'] ?? null,
            'purchase_unit_id' => null,
            'cost_price' => $row['成本價'] ?? null,
            'price' => $row['售價'] ?? null,
            'member_price' => $row['會員價'] ?? null,
            'wholesale_price' => $row['批發價'] ?? null,
        ];

        if ($product) {
            // 更新現有商品
            $product->update($data);
            return null; // 返回 null 以避免 Maatwebsite/Excel 嘗試再次 insert
        }

        // 建立新商品：處理代碼與條碼自動生成
        if (empty($code)) {
            $code = $this->generateRandomCode();
        }
        if (empty($barcode)) {
            $barcode = $this->generateRandomBarcode();
        }

        $data['code'] = $code;
        $data['barcode'] = $barcode;

        return new Product($data);
    }

    /**
     * 生成隨機 8 碼代號 (大寫英文+數字)
     */
    private function generateRandomCode(): string
    {
        $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;
    }

    /**
     * 生成隨機 13 碼條碼 (純數字)
     */
    private function generateRandomBarcode(): string
    {
        $barcode = '';
        
        do {
            $barcode = '';
            for ($i = 0; $i < 13; $i++) {
                $barcode .= rand(0, 9);
            }
        } while (Product::where('barcode', $barcode)->exists());

        return $barcode;
    }

    public function rules(): array
    {
        return [
            '商品代號' => ['nullable', 'string', 'min:2', 'max:8'],
            '條碼' => ['nullable', 'string'],
            '商品名稱' => ['required', 'string'],
            '類別名稱' => ['required', function($attribute, $value, $fail) {
                if (!isset($this->categories[$value])) {
                    $fail("找不到類別: " . $value);
                }
            }],
            '基本單位' => ['required', function($attribute, $value, $fail) {
                if (!isset($this->units[$value])) {
                    $fail("找不到單位: " . $value);
                }
            }],
            '大單位' => ['nullable', function($attribute, $value, $fail) {
                if ($value && !isset($this->units[$value])) {
                    $fail("找不到單位: " . $value);
                }
            }],

            '換算率' => ['nullable', 'numeric', 'min:0.0001', 'required_with:大單位'],
            '成本價' => ['nullable', 'numeric', 'min:0'],
            '售價' => ['nullable', 'numeric', 'min:0'],
            '會員價' => ['nullable', 'numeric', 'min:0'],
            '批發價' => ['nullable', 'numeric', 'min:0'],
        ];
    }
}
