<?php

declare(strict_types=1);

namespace MauticPlugin\DealFlowBundle\Controller;

use Mautic\CoreBundle\Controller\CommonController;
use MauticPlugin\DealFlowBundle\Service\DealAuthorization;
use MauticPlugin\DealFlowBundle\Service\UpdateService;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

final class UpdateController extends CommonController
{
    public function indexAction(
        Request $request,
        DealAuthorization $authorization,
        UpdateService $updateService,
    ): Response {
        if (!$authorization->canViewSettings()) {
            return $this->accessDenied();
        }

        $forceRefresh = $request->query->getBoolean('refresh', false);
        $updateCheck = $updateService->checkForUpdates($forceRefresh);

        // Check for backup directories and write permissions
        $pluginDir = \dirname(__DIR__);
        $pluginsDir = \dirname($pluginDir);
        $backups = glob($pluginsDir.'/DealFlowBundle.bak.*');
        $hasBackup = \is_array($backups) && $backups !== [];
        $isWritable = is_writable($pluginsDir) && is_writable($pluginDir);

        // AJAX request: return JSON instead of full page
        if ($request->isXmlHttpRequest() && $forceRefresh) {
            return new JsonResponse([
                'updateAvailable' => $updateCheck->updateAvailable,
                'latestVersion' => $updateCheck->latestVersion,
                'currentVersion' => $updateCheck->currentVersion,
                'downloadUrl' => $updateCheck->downloadUrl,
                'changelog' => $updateCheck->changelog,
                'sha256' => $updateCheck->sha256,
                'requiresMigration' => $updateCheck->requiresMigration,
                'eligible' => $updateCheck->eligible,
                'updatesUntil' => $updateCheck->updatesUntil,
                'error' => $updateCheck->error,
                'errorMessage' => $updateCheck->errorMessage,
                'hasBackup' => $hasBackup,
                'isWritable' => $isWritable,
                'installUrl' => $this->generateUrl('mautic_dealflow_update_perform'),
                'csrfToken' => $this->container->get('security.csrf.token_manager')
                    ->getToken('dealflow_update_install')->getValue(),
            ]);
        }

        return $this->delegateView([
            'viewParameters' => [
                'updateCheck' => $updateCheck,
                'hasBackup' => $hasBackup,
                'isWritable' => $isWritable,
                'pluginDir' => $pluginDir,
                'pluginsDir' => $pluginsDir,
            ],
            'contentTemplate' => '@DealFlow/Update/index.html.twig',
            'passthroughVars' => [
                'activeLink' => '#mautic_dealflow_updates',
                'route' => $this->generateUrl('mautic_dealflow_update_check'),
                'mauticContent' => 'dealflow',
            ],
        ]);
    }

    public function installAction(
        Request $request,
        DealAuthorization $authorization,
        UpdateService $updateService,
        CsrfTokenManagerInterface $csrfTokenManager,
    ): Response {
        if (!$authorization->canViewSettings()) {
            return $this->accessDenied();
        }

        $token = (string) $request->request->get('_token');
        if (!$csrfTokenManager->isTokenValid(new CsrfToken('dealflow_update_install', $token))) {
            $this->addFlash('error', 'Invalid CSRF token.');

            return $this->postActionRedirect([
                'returnUrl' => $this->generateUrl('mautic_dealflow_update_check'),
            ]);
        }

        $downloadUrl = (string) $request->request->get('download_url', '');
        $sha256 = (string) $request->request->get('sha256', '');

        if ($downloadUrl === '' || $sha256 === '') {
            $this->addFlash('error', 'Missing download URL or checksum.');

            return $this->postActionRedirect([
                'returnUrl' => $this->generateUrl('mautic_dealflow_update_check'),
            ]);
        }

        $result = $updateService->performUpdate($downloadUrl, $sha256);

        if ($result->success) {
            $this->addFlash('notice', 'Successfully updated to v'.($result->newVersion ?? 'unknown').'.');
        } else {
            $this->addFlash('error', 'Update failed: '.$result->message);
        }

        return $this->postActionRedirect([
            'returnUrl' => $this->generateUrl('mautic_dealflow_update_check'),
        ]);
    }

    public function rollbackAction(
        Request $request,
        DealAuthorization $authorization,
        UpdateService $updateService,
        CsrfTokenManagerInterface $csrfTokenManager,
    ): Response {
        if (!$authorization->canViewSettings()) {
            return $this->accessDenied();
        }

        $token = (string) $request->request->get('_token');
        if (!$csrfTokenManager->isTokenValid(new CsrfToken('dealflow_update_rollback', $token))) {
            $this->addFlash('error', 'Invalid CSRF token.');

            return $this->postActionRedirect([
                'returnUrl' => $this->generateUrl('mautic_dealflow_update_check'),
            ]);
        }

        $result = $updateService->rollback();

        if ($result->success) {
            $this->addFlash('notice', 'Rolled back successfully.');
        } else {
            $this->addFlash('error', 'Rollback failed: '.$result->message);
        }

        return $this->postActionRedirect([
            'returnUrl' => $this->generateUrl('mautic_dealflow_update_check'),
        ]);
    }
}
