<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Models\ContractPublicSignResult;
use App\Models\ContractPublicViewResult;
use App\Services\ContractService;
use ApiException;

/**
 * Public contract pages — no login required.
 */
final class PublicContractController
{
    private ContractService $contracts;

    public function __construct(?ContractService $contracts = null)
    {
        $this->contracts = $contracts ?? contract_service();
    }

    public function showBySignToken(string $signToken): void
    {
        require_once dirname(__DIR__) . '/includes/contract_details.php';

        $result = $this->contracts->viewPublicContract($signToken);
        $contract = is_array($result->contract) ? $result->contract : [];
        $rawData = $result->rawData();
        $errorCode = $result->errorCode;
        $httpStatus = $result->httpStatus;
        $signTokenDisplay = trim($signToken);
        $formAction = function_exists('app_path') && $signTokenDisplay !== ''
            ? app_path('/contracts/sign/' . rawurlencode($signTokenDisplay))
            : ('/contracts/sign/' . rawurlencode($signTokenDisplay));
        $legacySignUrl = function_exists('app_path') && $signTokenDisplay !== ''
            ? app_path('/contract/' . rawurlencode($signTokenDisplay))
            : ('/contract/' . rawurlencode($signTokenDisplay));

        $signResult = null;
        if (function_exists('auth_start')) {
            auth_start();
            $signResult = $_SESSION['last_public_sign_response'] ?? null;
            unset($_SESSION['last_public_sign_response']);
        }

        $status = strtolower(trim((string)($contract['contract_status'] ?? '')));
        $canSign = $result->success && $status !== 'signed';

        if (!$result->success) {
            http_response_code($httpStatus >= 400 ? $httpStatus : 404);
        }

        require dirname(__DIR__) . '/views/contracts/public_view.php';
    }

    public function submitSign(string $signToken): void
    {
        if (empty($_POST['terms_accepted'])) {
            if (function_exists('auth_start')) {
                auth_start();
                $_SESSION['last_public_sign_response'] = [
                    'success' => false,
                    'message' => __('public_sign_terms_required'),
                ];
            }
            $this->redirectToSignPage($signToken);
        }

        try {
            $payload = $this->contracts->buildPublicSignPayloadFromPost($_POST);
        } catch (ApiException $e) {
            if (function_exists('auth_start')) {
                auth_start();
                $_SESSION['last_public_sign_response'] = [
                    'success' => false,
                    'message' => $e->getMessage(),
                ];
            }
            $this->redirectToSignPage($signToken);
        }

        $payload['terms_accepted'] = true;
        $result = $this->contracts->signContractPublic($signToken, $payload);
        $this->storeSignResult($result);
        $this->redirectToSignPage($signToken);
    }

    private function storeSignResult(ContractPublicSignResult $result): void
    {
        if (!function_exists('auth_start')) {
            return;
        }

        auth_start();
        $_SESSION['last_public_sign_response'] = [
            'success' => $result->success,
            'message' => $result->message,
            'contract' => $result->contract,
            'api_response' => $result->apiResponse,
            'error_code' => $result->errorCode,
        ];
    }

    private function redirectToSignPage(string $signToken): void
    {
        $signToken = trim($signToken);
        $path = '/contracts/sign/' . rawurlencode($signToken);
        if (function_exists('redirect')) {
            redirect($path);
        }

        header('Location: ' . $path, true, 302);
        exit;
    }
}
