<?php

namespace App\Filament\Resources\StockTransferResource\Pages;

use App\Exceptions\InsufficientStockException;
use App\Filament\Resources\Concerns\ReportsStockShortfall;
use App\Filament\Resources\StockTransferResource;
use App\Models\Inventory\StockTransfer;
use App\Services\AuditLog;
use App\Support\SerialInput;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Validation\ValidationException;
use InvalidArgumentException;

class CreateStockTransfer extends CreateRecord
{
    use ReportsStockShortfall;

    protected static string $resource = StockTransferResource::class;

    protected function handleRecordCreation(array $data): StockTransfer
    {
        StockTransferResource::assertSourceBranchAccessible((int) $data['from_branch_id']);

        try {
            $transfer = StockTransferResource::apply($data);
        } catch (InsufficientStockException $e) {
            throw static::stockShortfall($e, static::shortfallField($data));
        } catch (InvalidArgumentException $e) {
            // BatchService::transferPortion() guards the LOT, which the branch
            // total cannot: a branch can hold plenty across its lots while the
            // one picked here is short.
            throw ValidationException::withMessages([
                'data.stock_batch_id' => $e->getMessage(),
            ]);
        }

        AuditLog::record('stock_transfer.created', $transfer, [
            'from' => $transfer->fromBranch?->name,
            'to' => $transfer->toBranch?->name,
            'product' => $transfer->product?->name,
            'quantity' => $transfer->quantity,
            'note' => $transfer->note,
        ]);

        return $transfer;
    }

    /**
     * A serial transfer hides the quantity input — the count comes from the
     * picked serials — so the message has to land on whichever field is
     * actually on screen, or it would be reported against nothing.
     *
     * @param  array<string, mixed>  $data
     */
    private static function shortfallField(array $data): string
    {
        return SerialInput::ids($data['serial_ids'] ?? []) !== []
            ? 'data.serial_ids'
            : 'data.quantity';
    }
}
