<?php

namespace App\Services;

use App\Models\ProductVariant;
use App\Models\StockMutation;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class StockMutationService
{
    private const QUALITY_MAP = [
        'stock' => 'good',
        'reject_stock' => 'reject',
        'retail_stock' => 'retail',
    ];

    public function paginated(Model $model, int $perPage = 20): LengthAwarePaginator
    {
        return StockMutation::query()
            ->where('stockable_type', get_class($model))
            ->where('stockable_id', $model->id)
            ->with('user:id,username,email')
            ->latest()
            ->paginate($perPage);
    }

    public function recordInitial(Model $model, array $stockData, string $description = 'Stok awal'): void
    {
        $userId = auth()->id();

        foreach (self::QUALITY_MAP as $field => $quality) {
            $quantity = (int) ($stockData[$field] ?? 0);
            if ($quantity > 0) {
                StockMutation::create([
                    'user_id' => $userId,
                    'stockable_type' => get_class($model),
                    'stockable_id' => $model->id,
                    'type' => 'in',
                    'quantity' => $quantity,
                    'stock_before' => 0,
                    'stock_after' => $quantity,
                    'stock_quality' => $quality,
                    'description' => $description,
                ]);
            }
        }
    }

    public function recordAdjustment(Model $model, array $oldData, array $newData, string $description = 'Penyesuaian stok'): void
    {
        $userId = auth()->id();

        foreach (self::QUALITY_MAP as $field => $quality) {
            $old = (int) ($oldData[$field] ?? 0);
            $new = (int) ($newData[$field] ?? 0);
            $diff = $new - $old;

            if ($diff !== 0) {
                StockMutation::create([
                    'user_id' => $userId,
                    'stockable_type' => get_class($model),
                    'stockable_id' => $model->id,
                    'type' => $diff > 0 ? 'in' : 'out',
                    'quantity' => $diff,
                    'stock_before' => $old,
                    'stock_after' => $new,
                    'stock_quality' => $quality,
                    'description' => $description,
                ]);
            }
        }
    }

    public function recordBulkInitial(Collection $variants, array $stockDataMap, string $description = 'Stok awal'): void
    {
        $userId = auth()->id();
        $now = now();
        $mutations = [];

        foreach ($variants as $variant) {
            $stockData = $stockDataMap[$variant->id] ?? [];
            foreach (self::QUALITY_MAP as $field => $quality) {
                $quantity = (int) ($stockData[$field] ?? 0);
                if ($quantity > 0) {
                    $mutations[] = [
                        'user_id' => $userId,
                        'stockable_type' => ProductVariant::class,
                        'stockable_id' => $variant->id,
                        'type' => 'in',
                        'quantity' => $quantity,
                        'stock_before' => 0,
                        'stock_after' => $quantity,
                        'stock_quality' => $quality,
                        'description' => $description,
                        'created_at' => $now,
                        'updated_at' => $now,
                    ];
                }
            }
        }

        if ($mutations !== []) {
            DB::table('stock_mutations')->insert($mutations);
        }
    }

    public function recordBulkAdjustment(Collection $variants, array $oldDataMap, array $newDataMap, string $description = 'Penyesuaian stok'): void
    {
        $userId = auth()->id();
        $now = now();
        $mutations = [];

        foreach ($variants as $variant) {
            $oldData = $oldDataMap[$variant->id] ?? [];
            $newData = $newDataMap[$variant->id] ?? [];

            foreach (self::QUALITY_MAP as $field => $quality) {
                $old = (int) ($oldData[$field] ?? 0);
                $new = (int) ($newData[$field] ?? 0);
                $diff = $new - $old;

                if ($diff !== 0) {
                    $mutations[] = [
                        'user_id' => $userId,
                        'stockable_type' => ProductVariant::class,
                        'stockable_id' => $variant->id,
                        'type' => $diff > 0 ? 'in' : 'out',
                        'quantity' => $diff,
                        'stock_before' => $old,
                        'stock_after' => $new,
                        'stock_quality' => $quality,
                        'description' => $description,
                        'created_at' => $now,
                        'updated_at' => $now,
                    ];
                }
            }
        }

        if ($mutations !== []) {
            DB::table('stock_mutations')->insert($mutations);
        }
    }

    public function recordTransfer(
        Model $model,
        int $quantity,
        string $fromQuality,
        string $toQuality,
        int $fromBefore,
        int $toBefore,
        string $description = 'Transfer stok',
    ): void {
        DB::transaction(function () use ($model, $quantity, $fromQuality, $toQuality, $fromBefore, $toBefore, $description) {
            $userId = auth()->id();

            StockMutation::create([
                'user_id' => $userId,
                'stockable_type' => get_class($model),
                'stockable_id' => $model->id,
                'type' => 'out',
                'quantity' => -$quantity,
                'stock_before' => $fromBefore,
                'stock_after' => $fromBefore - $quantity,
                'stock_quality' => $fromQuality,
                'description' => $description,
            ]);

            StockMutation::create([
                'user_id' => $userId,
                'stockable_type' => get_class($model),
                'stockable_id' => $model->id,
                'type' => 'in',
                'quantity' => $quantity,
                'stock_before' => $toBefore,
                'stock_after' => $toBefore + $quantity,
                'stock_quality' => $toQuality,
                'description' => $description,
            ]);
        });
    }
}
