<?php

namespace App\Services;

use App\Models\Order;
use App\Models\Outlet;
use App\Models\Purchase;
use App\Models\Restock;
use App\Models\StockOpname;
use App\Models\Warehouse;
use Illuminate\Database\Eloquent\Model;

class StockActivityLogService
{
    public const LOG_PURCHASE = 'purchase';

    public const LOG_DISTRIBUTION = 'distribution';

    public const LOG_SALE = 'sale';

    public const LOG_STOCK_OPNAME = 'stock_opname';

    /**
     * Log purchase activity (Incoming to Warehouse).
     */
    public static function purchase(
        Purchase $purchase,
        Model $product,
        int $quantity,
        int $previousStock,
        int $newStock,
        ?Model $causedBy = null
    ): void {
        self::logWarehouse(
            logName: self::LOG_PURCHASE,
            event: 'increase',
            description: "Purchase #{$purchase->hash_id}: Added {$quantity} stock to Warehouse.",
            performedOn: $product,
            warehouse: $purchase->warehouse,
            quantityChange: $quantity,
            previousStock: $previousStock,
            newStock: $newStock,
            extraProperties: [
                'purchase_id' => $purchase->id,
                'purchase_hash' => $purchase->hash_id,
            ],
            causedBy: $causedBy
        );
    }

    /**
     * Log distribution activity (Warehouse to Outlet).
     * This logs two events: Out from Warehouse, In to Outlet.
     */
    public static function distribution(
        Restock $restock,
        Model $product,
        int $quantity,
        int $warehousePreviousStock,
        int $warehouseNewStock,
        int $outletPreviousStock,
        int $outletNewStock,
        ?Model $causedBy = null
    ): void {
        // Log Warehouse Out
        self::logWarehouse(
            logName: self::LOG_DISTRIBUTION,
            event: 'decrease',
            description: "Restock #{$restock->hash_id}: Moved {$quantity} stock from Warehouse to Outlet.",
            performedOn: $product,
            warehouse: $restock->warehouse,
            quantityChange: -1 * abs($quantity),
            previousStock: $warehousePreviousStock,
            newStock: $warehouseNewStock,
            extraProperties: [
                'restock_id' => $restock->id,
                'restock_hash' => $restock->hash_id,
                'target_outlet_id' => $restock->outlet_id,
            ],
            causedBy: $causedBy
        );

        // Log Outlet In
        self::logOutlet(
            logName: self::LOG_DISTRIBUTION,
            event: 'increase',
            description: "Restock #{$restock->hash_id}: Received {$quantity} stock from Warehouse.",
            performedOn: $product,
            outlet: $restock->outlet,
            quantityChange: abs($quantity),
            previousStock: $outletPreviousStock,
            newStock: $outletNewStock,
            extraProperties: [
                'restock_id' => $restock->id,
                'restock_hash' => $restock->hash_id,
                'source_warehouse_id' => $restock->warehouse_id,
            ],
            causedBy: $causedBy
        );
    }

    /**
     * Log sale activity (Outlet to Customer).
     */
    public static function sale(
        Order $order,
        Model $product,
        int $quantity,
        int $previousStock,
        int $newStock,
        ?Model $causedBy = null
    ): void {
        self::logOutlet(
            logName: self::LOG_SALE,
            event: 'decrease',
            description: "Order #{$order->hash_id}: Sold {$quantity} items.",
            performedOn: $product,
            outlet: $order->outlet,
            quantityChange: -1 * abs($quantity),
            previousStock: $previousStock,
            newStock: $newStock,
            extraProperties: [
                'order_id' => $order->id,
                'order_hash' => $order->hash_id,
            ],
            causedBy: $causedBy ?? $order->user
        );
    }

    /**
     * Log stock opname activity (Adjustment in Outlet).
     */
    public static function stockOpname(
        StockOpname $stockOpname,
        Model $product,
        int $quantityChange,
        int $previousStock,
        int $newStock,
        ?string $note = null,
        ?Model $causedBy = null
    ): void {
        $event = $quantityChange > 0 ? 'increase' : 'decrease';

        self::logOutlet(
            logName: self::LOG_STOCK_OPNAME,
            event: $event,
            description: "Stock Opname #{$stockOpname->hash_id}: Adjusted stock by {$quantityChange}.",
            performedOn: $product,
            outlet: $stockOpname->outlet,
            quantityChange: $quantityChange,
            previousStock: $previousStock,
            newStock: $newStock,
            extraProperties: [
                'stock_opname_id' => $stockOpname->id,
                'stock_opname_hash' => $stockOpname->hash_id,
                'note' => $note,
            ],
            causedBy: $causedBy
        );
    }

    /**
     * Log stock related activity for Outlet.
     */
    public static function logOutlet(
        string $logName,
        string $event,
        string $description,
        Model $performedOn,
        Model $outlet,
        int $quantityChange,
        int $previousStock,
        int $newStock,
        array $extraProperties = [],
        ?Model $causedBy = null
    ): void {
        $causedBy = $causedBy ?: auth()->user();

        $properties = array_merge([
            'outlet_id' => $outlet->getKey(),
            'quantity_change' => $quantityChange,
            'previous_stock' => $previousStock,
            'new_stock' => $newStock,
            'location_type' => 'outlet',
            'location_name' => $outlet->name ?? 'Unknown Outlet',
        ], $extraProperties);

        activity($logName)
            ->performedOn($performedOn)
            ->causedBy($causedBy)
            ->withProperties($properties)
            ->event($event)
            ->log($description);
    }

    /**
     * Log stock related activity for Warehouse.
     */
    public static function logWarehouse(
        string $logName,
        string $event,
        string $description,
        Model $performedOn,
        Warehouse $warehouse,
        int $quantityChange,
        int $previousStock,
        int $newStock,
        array $extraProperties = [],
        ?Model $causedBy = null
    ): void {
        $causedBy = $causedBy ?: auth()->user();

        $properties = array_merge([
            'warehouse_id' => $warehouse->getKey(),
            'quantity_change' => $quantityChange,
            'previous_stock' => $previousStock,
            'new_stock' => $newStock,
            'location_type' => 'warehouse',
            'location_name' => $warehouse->name ?? 'Unknown Warehouse',
        ], $extraProperties);

        activity($logName)
            ->performedOn($performedOn)
            ->causedBy($causedBy)
            ->withProperties($properties)
            ->event($event)
            ->log($description);
    }
}
