<?php
declare(strict_types=1);

use Portal\Auth\AuthService;
use Portal\Bitrix24Client;
use Portal\Bitrix24Exception;
use Portal\Controller\AuthController;
use Portal\Controller\DealController;
use Portal\Controller\LeadController;
use Portal\Repository\CompanyRepository;
use Portal\Repository\ContactRepository;
use Portal\Repository\DealFieldRepository;
use Portal\Repository\DealRepository;
use Portal\Repository\LeadFieldRepository;
use Portal\Repository\LeadRepository;
use Portal\Repository\PageContextRepository;
use Portal\Repository\StatusRepository;
use Portal\Repository\UserRepository;
use Portal\Session;
use Portal\View;

require dirname(__DIR__) . '/src/helpers.php';
require dirname(__DIR__) . '/src/autoload.php';

$config = require dirname(__DIR__) . '/config/config.php';
$debug = (bool)$config['debug'];

/** Страница ошибки и завершение запроса. */
function abort(int $code, string $title, string $message, bool $debug = false, ?Throwable $e = null): never
{
    global $config;

    http_response_code($code);

    $view = new View(dirname(__DIR__) . '/views');
    echo $view->render('errors/error', [
        'appName' => (string)($config['app_name'] ?? 'Партнерский портал PIX Robotics'),
        'code' => $code,
        'title' => $title,
        'message' => $message,
        'debug' => $debug,
        'exception' => $e,
    ]);

    exit;
}

// Отсутствующие обязательные настройки — понятная страница вместо падения посреди запроса
$missingSettings = [];
if ($config['bitrix24_webhook_url'] === '') {
    $missingSettings[] = 'BITRIX24_WEBHOOK_URL';
}
if ($config['deal_partner_field'] === '') {
    $missingSettings[] = 'DEAL_PARTNER_FIELD';
}
if ($config['lead_partner_field'] === '') {
    $missingSettings[] = 'LEAD_PARTNER_FIELD';
}
if ($missingSettings !== []) {
    abort(
        500,
        'Портал не настроен',
        'Заполните параметры в файле .env: ' . implode(', ', $missingSettings) . '. Инструкция — в README.md.',
    );
}

Session::start();

// Путь запроса относительно папки public (портал может лежать в подпапке)
$basePath = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? '/')), '/');
$basePath = $basePath === '/' ? '' : $basePath;
$path = (string)parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
if ($basePath !== '' && str_starts_with($path, $basePath)) {
    $path = substr($path, strlen($basePath));
}
$path = '/' . trim($path, '/');
$method = strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET');

try {
    $client = new Bitrix24Client($config['bitrix24_webhook_url']);
    $view = new View(dirname(__DIR__) . '/views');

    $contacts = new ContactRepository($client);
    $companies = new CompanyRepository($client);
    $users = new UserRepository($client);
    $dealFields = new DealFieldRepository($client);
    $deals = new DealRepository($client, $config['deal_partner_field'], $config['partner_value_prefix']);
    $leads = new LeadRepository($client, $config['lead_partner_field'], $config['partner_value_prefix']);
    $leadFields = new LeadFieldRepository($client);
    $statuses = new StatusRepository($client);
    $pageContext = new PageContextRepository($client, $statuses, $dealFields, $leadFields, $companies, $contacts, $users);

    $authController = new AuthController(
        new AuthService($contacts, $companies, $config['password_field']),
        $view,
        (string)$config['app_name'],
    );
    $dealController = new DealController(
        $view,
        $deals,
        $pageContext,
        $contacts,
        $users,
        $statuses,
        (string)$config['app_name'],
        (int)$config['page_size'],
    );
    $leadController = new LeadController(
        $view,
        $leads,
        $pageContext,
        $contacts,
        $statuses,
        $leadFields,
        (string)$config['app_name'],
        (int)$config['page_size'],
    );

    if ($path === '/') {
        redirect(site_url(Session::isAuthenticated() ? 'deals' : 'login'));
    }

    if ($path === '/login') {
        $method === 'POST' ? $authController->login() : $authController->showForm();
        return;
    }

    if ($path === '/logout') {
        $authController->logout();
        return;
    }

    if ($path === '/deals' && $method === 'GET') {
        if (!Session::isAuthenticated()) {
            redirect(site_url('login'));
        }
        $dealController->index();
        return;
    }

    // Детали сделки для popup: GET — прочитать, POST — «Сохранить»
    // (пока только перечитывает сделку из Битрикс24)
    if ($path === '/deals/details' && in_array($method, ['GET', 'POST'], true)) {
        if (!Session::isAuthenticated()) {
            http_response_code(401);
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode(['error' => 'Требуется авторизация.'], JSON_UNESCAPED_UNICODE);

            return;
        }
        $requestCsrf = (string)($_POST['csrf_token'] ?? $_GET['csrf_token'] ?? '');
        if ($method === 'POST' && !Session::checkCsrf($requestCsrf)) {
            http_response_code(403);
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode(['error' => 'Недействительный CSRF-токен.'], JSON_UNESCAPED_UNICODE);

            return;
        }
        $dealController->details();
        return;
    }

    if ($path === '/leads' && $method === 'GET') {
        if (!Session::isAuthenticated()) {
            redirect(site_url('login'));
        }
        $leadController->index();
        return;
    }

    // Детали лида для popup (только просмотр)
    if ($path === '/leads/details' && $method === 'GET') {
        if (!Session::isAuthenticated()) {
            http_response_code(401);
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode(['error' => 'Требуется авторизация.'], JSON_UNESCAPED_UNICODE);

            return;
        }
        $leadController->details();
        return;
    }

    abort(404, 'Страница не найдена', 'Запрошенная страница не существует.');
} catch (Bitrix24Exception $e) {
    abort(
        502,
        'Нет связи с Битрикс24',
        $debug
            ? $e->getMessage()
            : 'Не удалось получить данные из Битрикс24. Попробуйте обновить страницу позже.',
        $debug,
        $e,
    );
} catch (Throwable $e) {
    abort(
        500,
        'Внутренняя ошибка сервера',
        $debug ? $e->getMessage() : 'Что-то пошло не так. Попробуйте позже.',
        $debug,
        $e,
    );
}
