<?php

namespace Modules\Inventory\Services;

use App\Models\ActivityLogModel;
use App\Models\InventoryAssetModel;

class AssetInventoryService
{
    protected InventoryAssetModel $assets;
    protected ActivityLogModel $activity;

    protected const STATUSES = ['active', 'in_repair', 'disposed', 'lost'];

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

    public function create(array $input, ?int $actingUserId): array
    {
        $tag = strtoupper(trim($input['asset_tag'] ?? ''));
        if ($tag === '') {
            $tag = $this->assets->nextTag();
        }

        if ($this->assets->isTagTaken($tag)) {
            return ['success' => false, 'errors' => ['asset_tag' => 'That asset tag is already in use.']];
        }

        $status = $input['status'] ?? 'active';
        if (! in_array($status, self::STATUSES, true)) {
            return ['success' => false, 'errors' => ['status' => 'Invalid asset status.']];
        }

        $data = $this->mapInput($input);
        $data['asset_tag']  = $tag;
        $data['status']     = $status;
        $data['created_by'] = $actingUserId;
        $data['updated_by'] = $actingUserId;

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

        $id = $this->assets->getInsertID();
        $this->activity->log('asset_inventory', 'created', $actingUserId, "Created asset #{$id} ({$tag})", (string) $id);

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

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

        $tag = strtoupper(trim($input['asset_tag'] ?? $asset['asset_tag']));
        if ($this->assets->isTagTaken($tag, $id)) {
            return ['success' => false, 'errors' => ['asset_tag' => 'That asset tag is already in use.']];
        }

        $status = $input['status'] ?? $asset['status'];
        if (! in_array($status, self::STATUSES, true)) {
            return ['success' => false, 'errors' => ['status' => 'Invalid asset status.']];
        }

        $data = $this->mapInput($input);
        $data['asset_tag']  = $tag;
        $data['status']     = $status;
        $data['updated_by'] = $actingUserId;

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

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

        return ['success' => true];
    }

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

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

        return ['success' => true];
    }

    protected function mapInput(array $input): array
    {
        $productId = $input['product_id'] ?? null;

        return [
            'name'           => trim($input['name'] ?? ''),
            'product_id'     => ($productId !== null && $productId !== '') ? (int) $productId : null,
            'category'       => trim($input['category'] ?? '') ?: null,
            'location'       => trim($input['location'] ?? '') ?: null,
            'serial_number'  => trim($input['serial_number'] ?? '') ?: null,
            'purchase_date'  => trim($input['purchase_date'] ?? '') ?: null,
            'purchase_cost'  => (float) ($input['purchase_cost'] ?? 0),
            'notes'          => trim($input['notes'] ?? '') ?: null,
        ];
    }
}
