<?php

namespace Modules\Inventory\Services;

use App\Models\ActivityLogModel;
use App\Models\ProductBatchModel;

class BatchService
{
    protected ProductBatchModel $batches;
    protected ActivityLogModel $activity;

    public function __construct()
    {
        $this->batches  = new ProductBatchModel();
        $this->activity = new ActivityLogModel();
    }

    public function create(array $input, ?int $actingUserId): array
    {
        $productId   = (int) ($input['product_id'] ?? 0);
        $batchNumber = trim($input['batch_number'] ?? '');

        if ($productId <= 0 || $batchNumber === '') {
            return ['success' => false, 'errors' => ['batch_number' => 'Product and batch number are required.']];
        }

        if ($this->batches->isBatchTaken($productId, $batchNumber)) {
            return ['success' => false, 'errors' => ['batch_number' => 'That batch number already exists for this product.']];
        }

        $data = $this->mapInput($input);
        $data['product_id']    = $productId;
        $data['batch_number']  = $batchNumber;
        $data['created_by']    = $actingUserId;
        $data['updated_by']    = $actingUserId;

        if (! $this->batches->insert($data, true)) {
            return ['success' => false, 'errors' => $this->batches->errors()];
        }

        $id = $this->batches->getInsertID();
        $this->activity->log('batches', 'created', $actingUserId, "Created batch #{$id} ({$batchNumber})", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function update(int $id, array $input, ?int $actingUserId): array
    {
        $batch = $this->batches->find($id);
        if (! $batch) {
            return ['success' => false, 'errors' => ['id' => 'Batch not found.']];
        }

        $productId   = (int) ($input['product_id'] ?? $batch['product_id']);
        $batchNumber = trim($input['batch_number'] ?? $batch['batch_number']);

        if ($this->batches->isBatchTaken($productId, $batchNumber, $id)) {
            return ['success' => false, 'errors' => ['batch_number' => 'That batch number already exists for this product.']];
        }

        $data = $this->mapInput($input);
        $data['product_id']   = $productId;
        $data['batch_number'] = $batchNumber;
        $data['updated_by']   = $actingUserId;

        if (! $this->batches->update($id, $data)) {
            return ['success' => false, 'errors' => $this->batches->errors()];
        }

        $this->activity->log('batches', 'updated', $actingUserId, "Updated batch #{$id}", (string) $id);

        return ['success' => true];
    }

    public function delete(int $id, ?int $actingUserId): array
    {
        $batch = $this->batches->find($id);
        if (! $batch) {
            return ['success' => false, 'error' => 'Batch not found.'];
        }

        $this->batches->delete($id);
        $this->activity->log('batches', 'deleted', $actingUserId, "Deleted batch #{$id}", (string) $id);

        return ['success' => true];
    }

    protected function mapInput(array $input): array
    {
        $warehouseId = $input['warehouse_id'] ?? null;
        $status      = $input['status'] ?? 'active';
        $expiryDate  = trim($input['expiry_date'] ?? '') ?: null;
        $mfgDate     = trim($input['manufactured_date'] ?? '') ?: null;

        if ($status === 'active' && $expiryDate && $expiryDate < date('Y-m-d')) {
            $status = 'expired';
        }

        return [
            'warehouse_id'      => ($warehouseId !== null && $warehouseId !== '') ? (int) $warehouseId : null,
            'quantity'          => (float) ($input['quantity'] ?? 0),
            'manufactured_date' => $mfgDate,
            'expiry_date'       => $expiryDate,
            'status'            => $status,
            'notes'             => trim($input['notes'] ?? '') ?: null,
        ];
    }
}
