<?php
declare(strict_types=1);

namespace Favo\Controllers;

use Favo\Core\Authorization;
use Favo\Services\PurchaseService;
use Favo\Services\LoyaltyService;
use Favo\Services\AuditService;
use Favo\Services\AutoUnlockService;
use Favo\Helpers\Response;

final class TransactionController
{
    private PurchaseService $purchases;
    private Authorization $auth;

    public function __construct()
    {
        $db = database_connection();
        $audit = new AuditService($db);
        $loyalty = new LoyaltyService($db, $audit);
        $autoUnlock = new AutoUnlockService($db);
        $this->purchases = new PurchaseService($db, $audit, $loyalty, $autoUnlock);
        $this->auth = new Authorization($db);
    }

    public function create(): void
    {
        $a = $this->auth->requireAccountType('SUPERADMIN', 'ADMIN', 'MERCHANT', 'STAFF');

        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            http_response_code(405);
            Response::json(['status' => 'error', 'message' => 'POST required']);
            return;
        }

        $merchantId = (int)($_POST['merchant_id'] ?? 0);
        $branchId = (int)($_POST['branch_id'] ?? 0);
        $accountType = (string)($a['account_type'] ?? '');

        if (!$this->auth->merchantScope($merchantId)) {
            http_response_code(403);
            Response::json(['status' => 'error', 'message' => 'Merchant scope denied']);
            return;
        }

        // Staff must always transact through an assigned branch.
        if ($accountType === 'STAFF' && ($branchId < 1 || !$this->auth->branchScope($branchId))) {
            http_response_code(403);
            Response::json(['status' => 'error', 'message' => 'Staff branch scope denied']);
            return;
        }

        if ($branchId > 0 && !$this->auth->branchScope($branchId)) {
            http_response_code(403);
            Response::json(['status' => 'error', 'message' => 'Branch scope denied']);
            return;
        }

        try {
            $uuid = trim((string)($_POST['transaction_uuid'] ?? ''));

            $id = $this->purchases->create([
                'transaction_uuid' => $uuid,
                'merchant_id' => $merchantId,
                'branch_id' => $branchId ?: null,
                'customer_id' => (int)($_POST['customer_id'] ?? 0),
                'program_id' => (int)($_POST['program_id'] ?? 0) ?: null,
                'staff_id' => $accountType === 'STAFF' ? (int)$a['id'] : null,
                'purchase_amount' => (float)($_POST['purchase_amount'] ?? 0),
                // Client-supplied reward values are intentionally ignored by PurchaseService.
            ], (int)$a['id']);

            Response::json([
                'status' => 'ok',
                'id' => $id,
                'idempotent' => $this->purchases->wasIdempotent(),
                'auto_unlocked' => $this->purchases->lastAutoUnlocked(),
            ]);
        } catch (\Throwable $e) {
            http_response_code(422);
            Response::json([
                'status' => 'error',
                'message' => $e->getMessage(),
            ]);
        }
    }
}
