<?php
require_once __DIR__ . '/functions.php';

$tenant = enrep_tenant_segment($_POST['tenant'] ?? $_GET['tenant'] ?? null);
if ($tenant !== '' && !defined('CONFIG_LOADED')) {
    require_once '../../' . $tenant . '/config.php';
}

assetmanager_require_user();

$con = $GLOBALS['con'] ?? null;
if (!$con instanceof mysqli) {
    assetmanager_json_response(['success' => false, 'message' => 'Tenant database connection unavailable.']);
}
$con->set_charset('utf8mb4');

if (!assetmanager_table_exists($con, 'assetmanager_hire') || !assetmanager_table_exists($con, 'assetmanager_activity') || !assetmanager_table_exists($con, 'assetmanager_maintenance')) {
    assetmanager_json_response(['success' => false, 'setup_required' => true, 'message' => 'Asset Manager hire tables are not installed yet.']);
}

$clientnumber = enrep_request_int('clientnumber', 0);
$contractId = enrep_request_int('contract_id', 0);
if ($clientnumber <= 0 || $contractId <= 0) {
    assetmanager_json_response(['success' => false, 'message' => 'Hire agreement is required.']);
}
assetmanager_json_require_client_access($con, $clientnumber);
assetmanager_json_require_module($con, $tenant, $clientnumber, 'hire', 'Hire');

$stmt = $con->prepare("
    SELECT id, reference AS contract_ref, status_key, payload_json AS contract_payload_json
    FROM assetmanager_hire
    WHERE id=? AND tenant_key=? AND clientnumber=? AND record_type='contract'
    LIMIT 1
");
if (!$stmt) {
    assetmanager_json_response(['success' => false, 'message' => 'Hire agreement could not be loaded.']);
}
$stmt->bind_param('isi', $contractId, $tenant, $clientnumber);
$stmt->execute();
$contract = $stmt->get_result()->fetch_assoc();
$stmt->close();
if (!$contract) {
    assetmanager_json_response(['success' => false, 'message' => 'Hire agreement was not found.']);
}
if (!in_array((string)$contract['status_key'], ['active', 'on_hire', 'open'], true)) {
    assetmanager_json_response(['success' => false, 'message' => 'Only active hire agreements can be received back.']);
}

$payload = assetmanager_decode_json($contract['contract_payload_json'] ?? '');
$hireAssets = is_array($payload['hire_assets'] ?? null) ? $payload['hire_assets'] : (is_array($payload['hire_asset'] ?? null) ? [$payload['hire_asset']] : []);
if (empty($hireAssets)) {
    assetmanager_json_response(['success' => false, 'message' => 'This hire agreement has no hire plant recorded.']);
}

$returnItems = assetmanager_request_json_array('return_items_json');
if (empty($returnItems)) {
    assetmanager_json_response(['success' => false, 'message' => 'Return checks are required.']);
}
$chargeback = assetmanager_request_json_array('chargeback_json');
$chargeAmount = (float)($chargeback['amount'] ?? 0);
$chargeAccepted = !empty($chargeback['accepted']);
$chargeReason = substr(trim((string)($chargeback['reason'] ?? '')), 0, 1000);
$createdMaintenance = [];

$returnByKey = [];
foreach ($returnItems as $item) {
    if (!is_array($item)) {
        continue;
    }
    $source = (string)($item['source'] ?? '');
    $sourceId = (int)($item['source_id'] ?? 0);
    if ($source !== '' && $sourceId > 0) {
        $returnByKey[$source . '|' . $sourceId] = $item;
    }
}

$userId = assetmanager_actor_user_id();
$now = date('Y-m-d H:i:s');
$updatedAssets = [];
$hasChargeableReturn = $chargeAmount > 0;

foreach ($hireAssets as $index => $asset) {
    if (!is_array($asset)) {
        continue;
    }
    $source = (string)($asset['source'] ?? '');
    $sourceId = (int)($asset['source_id'] ?? 0);
    if (!in_array($source, ['enrep_item', 'assetmanager_item'], true) || $sourceId <= 0) {
        continue;
    }
    assetmanager_json_require_asset_access($con, $tenant, $clientnumber, $source, $sourceId);
    $key = $source . '|' . $sourceId;
    $return = $returnByKey[$key] ?? [];
    $condition = trim((string)($return['condition_key'] ?? ''));
    if ($condition === '') {
        assetmanager_json_response(['success' => false, 'message' => 'Condition is required for ' . (string)($asset['title'] ?? 'hire plant') . '.']);
    }
    if (!in_array($condition, ['good', 'fair'], true)) {
        $hasChargeableReturn = true;
    }
    $runtimeRequired = trim((string)($asset['handover']['runtime_unit'] ?? '')) !== '' || trim((string)($asset['handover']['runtime_reading'] ?? '')) !== '';
    $runtimeReading = trim((string)($return['runtime_reading'] ?? ''));
    $runtimeUnit = trim((string)($return['runtime_unit'] ?? ($asset['handover']['runtime_unit'] ?? 'Hours')));
    if ($runtimeRequired && $runtimeReading === '') {
        assetmanager_json_response(['success' => false, 'message' => 'Return operating reading is required for ' . (string)($asset['title'] ?? 'hire plant') . '.']);
    }
    $maintenanceRequired = !empty($return['maintenance_required']);
    $takeOutOfService = !empty($return['take_out_of_service']);
    $maintenanceSummary = substr(trim((string)($return['maintenance_summary'] ?? '')), 0, 255);
    if ($maintenanceRequired && $maintenanceSummary === '') {
        $maintenanceSummary = 'Hire return issue - ' . (string)($asset['title'] ?? 'hire plant');
    }

    $asset['return'] = [
        'condition_key' => $condition,
        'condition_notes' => substr(trim((string)($return['condition_notes'] ?? '')), 0, 1000),
        'runtime_reading' => $runtimeReading,
        'runtime_unit' => $runtimeUnit,
        'maintenance_required' => $maintenanceRequired ? 1 : 0,
        'take_out_of_service' => $takeOutOfService ? 1 : 0,
        'maintenance_summary' => $maintenanceSummary,
        'received_at' => $now,
        'received_by' => $userId,
    ];
    $hireAssets[$index] = $asset;

    $assetId = assetmanager_resolve_asset_id($con, $tenant, $clientnumber, $source, $sourceId, (string)($asset['title'] ?? 'Asset'), true);
    if ($assetId > 0) {
        $rowStmt = $con->prepare("SELECT custom_fields_json FROM assetmanager_assets WHERE id=? AND tenant_key=? AND clientnumber=? LIMIT 1");
        if ($rowStmt) {
            $rowStmt->bind_param('isi', $assetId, $tenant, $clientnumber);
            $rowStmt->execute();
            $assetRow = $rowStmt->get_result()->fetch_assoc();
            $rowStmt->close();
            $custom = assetmanager_decode_json($assetRow['custom_fields_json'] ?? '');
            $custom['hire_state'] = 'available';
            $custom['last_hire_return_at'] = $now;
            $custom['last_hire_condition'] = $condition;
            if ($runtimeReading !== '') {
                $custom['current_hours'] = $runtimeReading;
                $custom['current_hours_unit'] = $runtimeUnit;
            }
            $customJson = assetmanager_encode_json($custom);
            $assetStatus = $takeOutOfService ? 'under_repair' : 'active';
            $updateStmt = $con->prepare("UPDATE assetmanager_assets SET custom_fields_json=?, status_key=?, current_runtime_value=?, current_runtime_unit=?, updated_at=? WHERE id=? AND tenant_key=? AND clientnumber=?");
            if ($updateStmt) {
                $runtimeValue = $runtimeReading !== '' && is_numeric($runtimeReading) ? (float)$runtimeReading : null;
                $runtimeUnitForUpdate = $runtimeReading !== '' ? $runtimeUnit : null;
                $updateStmt->bind_param('ssdssisi', $customJson, $assetStatus, $runtimeValue, $runtimeUnitForUpdate, $now, $assetId, $tenant, $clientnumber);
                $updateStmt->execute();
                $updateStmt->close();
            }
        }

        $eventType = 'returned';
        $eventSummary = 'Hire item returned';
        $eventPayloadJson = assetmanager_encode_json([
            'source' => $source,
            'source_id' => $sourceId,
            'asset_title' => (string)($asset['title'] ?? 'Asset'),
            'condition' => $condition,
            'runtime_reading' => $runtimeReading,
            'runtime_unit' => $runtimeUnit,
            'notes' => $asset['return']['condition_notes'],
            'maintenance_required' => $maintenanceRequired ? 1 : 0,
            'take_out_of_service' => $takeOutOfService ? 1 : 0,
        ]);
        $eventStmt = $con->prepare("
            INSERT INTO assetmanager_activity
                (tenant_key, clientnumber, asset_id, module_key, parent_type, parent_id, activity_type, activity_at, summary, reading_value, reading_unit, payload_json, created_by, created_at)
            VALUES (?, ?, ?, 'hire', 'contract', ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ");
        if ($eventStmt) {
            $readingValue = $runtimeReading !== '' && is_numeric($runtimeReading) ? (float)$runtimeReading : null;
            $eventStmt->bind_param('siiisssdssis', $tenant, $clientnumber, $assetId, $contractId, $eventType, $now, $eventSummary, $readingValue, $runtimeUnit, $eventPayloadJson, $userId, $now);
            $eventStmt->execute();
            $eventStmt->close();
        }
        if ($runtimeReading !== '') {
            $usageType = 'hire_return';
            $usageSummary = 'Hire return reading';
            $usagePayload = assetmanager_encode_json([
                'contract_id' => $contractId,
                'condition' => $condition,
                'notes' => $asset['return']['condition_notes'],
                'maintenance_required' => $maintenanceRequired ? 1 : 0,
                'take_out_of_service' => $takeOutOfService ? 1 : 0,
            ]);
            $usageStmt = $con->prepare("
                INSERT INTO assetmanager_activity
                    (tenant_key, clientnumber, asset_id, module_key, parent_type, parent_id, activity_type, activity_at, summary, reading_value, reading_unit, payload_json, created_by, created_at)
                VALUES (?, ?, ?, 'usage', 'hire_contract', ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ");
            if ($usageStmt) {
                $readingValue = is_numeric($runtimeReading) ? (float)$runtimeReading : null;
                $usageStmt->bind_param('siiisssdssis', $tenant, $clientnumber, $assetId, $contractId, $usageType, $now, $usageSummary, $readingValue, $runtimeUnit, $usagePayload, $userId, $now);
                $usageStmt->execute();
                $usageStmt->close();
            }
        }

        if ($maintenanceRequired) {
            $workType = 'repair';
            $workStatus = 'open';
            $priority = in_array($condition, ['damaged', 'mechanical_fault', 'missing'], true) ? 'high' : 'normal';
            $dueAt = null;
            $assignedTo = null;
            $workDetailsJson = assetmanager_encode_json([
                'source' => $source,
                'source_id' => $sourceId,
                'contract_id' => $contractId,
                'contract_ref' => (string)($contract['contract_ref'] ?? ''),
                'condition' => $condition,
                'notes' => $asset['return']['condition_notes'],
                'created_from' => 'hire_return',
                'take_out_of_service' => $takeOutOfService ? 1 : 0,
            ]);
            $workStmt = $con->prepare("
                INSERT INTO assetmanager_maintenance
                    (tenant_key, clientnumber, asset_id, record_type, status_key, priority_key, summary, due_at, completed_at, assigned_to, payload_json, created_by, created_at, updated_at)
                VALUES (?, ?, ?, 'work_order', ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?)
            ");
            if ($workStmt) {
                $workStmt->bind_param('siissssisiss', $tenant, $clientnumber, $assetId, $workStatus, $priority, $maintenanceSummary, $dueAt, $assignedTo, $workDetailsJson, $userId, $now, $now);
                if ($workStmt->execute()) {
                    $createdMaintenance[] = (int)$workStmt->insert_id;
                }
                $workStmt->close();
            }
        }
        $updatedAssets[] = $assetId;
    }
}

$returnSignatureRelativePath = '';
if ($hasChargeableReturn || $chargeAmount > 0) {
    if (!$chargeAccepted) {
        assetmanager_json_response(['success' => false, 'message' => 'Customer chargeback acceptance is required.']);
    }
    $signatureData = trim((string)($_POST['signature_data'] ?? ''));
    if (!preg_match('#^data:image/png;base64,#', $signatureData)) {
        assetmanager_json_response(['success' => false, 'message' => 'Customer chargeback signature is required.']);
    }
    $binary = base64_decode(substr($signatureData, strpos($signatureData, ',') + 1), true);
    if ($binary === false || strlen($binary) < 100) {
        assetmanager_json_response(['success' => false, 'message' => 'Customer chargeback signature could not be read.']);
    }
    $tenantRoot = realpath(dirname(__DIR__) . '/../' . $tenant);
    if ($tenantRoot === false) {
        assetmanager_json_response(['success' => false, 'message' => 'Tenant storage path could not be resolved.']);
    }
    $relativeSignatureDir = 'assetmanager/agreements/client_' . $clientnumber . '/contract_' . $contractId . '/return-signatures';
    $signatureDir = $tenantRoot . '/' . $relativeSignatureDir;
    if (!is_dir($signatureDir) && !mkdir($signatureDir, 0755, true)) {
        assetmanager_json_response(['success' => false, 'message' => 'Return signature folder could not be created.']);
    }
    $signatureName = 'return-chargeback-' . date('YmdHis') . '.png';
    $signaturePath = $signatureDir . '/' . $signatureName;
    if (file_put_contents($signaturePath, $binary) === false) {
        assetmanager_json_response(['success' => false, 'message' => 'Customer chargeback signature could not be saved.']);
    }
    $returnSignatureRelativePath = $relativeSignatureDir . '/' . $signatureName;
}

$payload['hire_assets'] = $hireAssets;
$payload['return'] = [
    'status' => 'received_back',
    'received_at' => $now,
    'received_by' => $userId,
    'notes' => enrep_request_string('return_notes', '', 2000),
    'created_maintenance' => $createdMaintenance,
    'chargeback' => [
        'required' => $hasChargeableReturn ? 1 : 0,
        'accepted' => $chargeAccepted ? 1 : 0,
        'amount' => $chargeAmount,
        'reason' => $chargeReason,
        'signature_path' => $returnSignatureRelativePath,
        'signed_at' => $returnSignatureRelativePath !== '' ? $now : '',
    ],
];
$payloadJson = assetmanager_encode_json($payload);
$status = 'returned';

$stmt = $con->prepare("UPDATE assetmanager_hire SET status_key=?, completed_at=?, payload_json=?, updated_at=? WHERE id=? AND tenant_key=? AND clientnumber=? AND record_type='contract'");
if (!$stmt) {
    assetmanager_json_response(['success' => false, 'message' => 'Hire return could not be prepared.']);
}
$stmt->bind_param('ssssisi', $status, $now, $payloadJson, $now, $contractId, $tenant, $clientnumber);
$ok = $stmt->execute();
$stmt->close();

if ($ok) {
    assetmanager_audit($con, $tenant, $clientnumber, $userId, 'hire_contract', $contractId, 'receive_back', [], [
        'assets' => $updatedAssets,
        'return' => $payload['return'],
    ]);
}

assetmanager_json_response([
    'success' => $ok,
    'message' => $ok ? 'Hire received back.' : 'Hire return could not be saved.',
]);
