<?php

namespace Modules\Assets\Services;

use App\Models\ActivityLogModel;
use App\Models\AssetTypeModel;
use App\Models\EmployeeAssetAssignmentModel;

class EmployeeAssetService
{
    protected EmployeeAssetAssignmentModel $assignments;
    protected AssetTypeModel $types;
    protected ActivityLogModel $activity;

    public function __construct()
    {
        $this->assignments = new EmployeeAssetAssignmentModel();
        $this->types       = new AssetTypeModel();
        $this->activity    = new ActivityLogModel();
    }

    public function assign(array $input, ?int $actingUserId): array
    {
        $employeeId  = (int) ($input['employee_id'] ?? 0);
        $assetTypeId = (int) ($input['asset_type_id'] ?? 0);
        $assetName   = trim($input['asset_name'] ?? '');
        $assignedDate = trim($input['assigned_date'] ?? '');

        if ($employeeId <= 0 || $assetTypeId <= 0 || $assetName === '' || $assignedDate === '') {
            return ['success' => false, 'errors' => ['form' => 'Employee, asset type, item name, and assigned date are required.']];
        }

        $type = $this->types->find($assetTypeId);
        if (! $type) {
            return ['success' => false, 'errors' => ['asset_type_id' => 'Asset type not found.']];
        }

        $identifier = trim($input['identifier'] ?? '') ?: null;
        if ($type['requires_identifier'] && $identifier === null) {
            return ['success' => false, 'errors' => ['identifier' => 'This asset type requires a serial number, IMEI, or identifier.']];
        }

        $data = [
            'employee_id'         => $employeeId,
            'asset_type_id'       => $assetTypeId,
            'asset_name'          => $assetName,
            'identifier'          => $identifier,
            'quantity'            => max(0.01, (float) ($input['quantity'] ?? 1)),
            'assigned_date'       => $assignedDate,
            'status'              => 'assigned',
            'condition_on_assign' => trim($input['condition_on_assign'] ?? '') ?: null,
            'notes'               => $input['notes'] ?: null,
            'assigned_by'         => $actingUserId,
            'created_by'          => $actingUserId,
            'updated_by'          => $actingUserId,
        ];

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

        $id = $this->assignments->getInsertID();
        $this->activity->log(
            'employee_assets',
            'assigned',
            $actingUserId,
            "Assigned {$assetName} to employee #{$employeeId}",
            (string) $id
        );

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

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

        if ($assignment['status'] !== 'assigned') {
            return ['success' => false, 'errors' => ['status' => 'Only active assignments can be edited.']];
        }

        $assetTypeId = (int) ($input['asset_type_id'] ?? $assignment['asset_type_id']);
        $type = $this->types->find($assetTypeId);
        if (! $type) {
            return ['success' => false, 'errors' => ['asset_type_id' => 'Asset type not found.']];
        }

        $identifier = trim($input['identifier'] ?? '') ?: null;
        if ($type['requires_identifier'] && $identifier === null) {
            return ['success' => false, 'errors' => ['identifier' => 'This asset type requires a serial number, IMEI, or identifier.']];
        }

        $data = [
            'asset_type_id'       => $assetTypeId,
            'asset_name'          => trim($input['asset_name'] ?? $assignment['asset_name']),
            'identifier'          => $identifier,
            'quantity'            => max(0.01, (float) ($input['quantity'] ?? $assignment['quantity'])),
            'assigned_date'       => trim($input['assigned_date'] ?? $assignment['assigned_date']),
            'condition_on_assign' => trim($input['condition_on_assign'] ?? '') ?: null,
            'notes'               => $input['notes'] ?: null,
            'updated_by'          => $actingUserId,
        ];

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

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

        return ['success' => true];
    }

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

        if ($assignment['status'] !== 'assigned') {
            return ['success' => false, 'errors' => ['status' => 'This asset is not currently assigned.']];
        }

        $returnedDate = trim($input['returned_date'] ?? date('Y-m-d'));
        $returnStatus = $input['return_status'] ?? 'returned';

        if (! in_array($returnStatus, ['returned', 'lost', 'damaged'], true)) {
            $returnStatus = 'returned';
        }

        $data = [
            'status'              => $returnStatus,
            'returned_date'       => $returnedDate,
            'condition_on_return' => trim($input['condition_on_return'] ?? '') ?: null,
            'notes'               => $input['notes'] ?: $assignment['notes'],
            'returned_by'         => $actingUserId,
            'updated_by'          => $actingUserId,
        ];

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

        $this->activity->log(
            'employee_assets',
            $returnStatus,
            $actingUserId,
            "Marked asset assignment #{$id} as {$returnStatus}",
            (string) $id
        );

        return ['success' => true];
    }

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

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

        return ['success' => true];
    }
}
