<?php
declare(strict_types=1);

namespace App\Modules\Cron;

use App\Core\I18n\Translator;
use App\Core\Support\Logger;
use App\Core\View\Template;
use App\Modules\Accounting\ReceiptRepository;
use App\Modules\Accounting\ReceiptService;
use App\Modules\Automation\AutomationRepository;
use App\Modules\Automation\AutomationService;
use App\Modules\Automation\AutomationExecutionLogRepository;
use App\Modules\Automation\OrderStatusAgedService;
use App\Modules\Email\AttachmentGenerator;
use App\Modules\Email\EmailSendingService;
use App\Modules\Email\VariableResolver;
use App\Modules\Orders\OrderImportRepository;
use App\Modules\Orders\OrdersRepository;
use App\Modules\Settings\AllegroApiClient;
use App\Modules\Settings\AllegroIntegrationRepository;
use App\Modules\Settings\AllegroOAuthClient;
use App\Modules\Settings\AllegroOrderImportService;
use App\Modules\Settings\AllegroOrdersSyncService;
use App\Modules\Settings\AllegroOrderSyncStateRepository;
use App\Modules\Settings\AllegroStatusMappingRepository;
use App\Modules\Settings\AllegroStatusSyncService;
use App\Modules\Settings\AllegroTokenManager;
use App\Modules\Settings\ApaczkaApiClient;
use App\Modules\Settings\ApaczkaIntegrationRepository;
use App\Modules\Settings\CompanySettingsRepository;
use App\Modules\Settings\EmailMailboxRepository;
use App\Modules\Settings\EmailTemplateRepository;
use App\Modules\Settings\InpostIntegrationRepository;
use App\Modules\Settings\IntegrationSecretCipher;
use App\Modules\Settings\ReceiptConfigRepository;
use App\Modules\Settings\ShopproApiClient;
use App\Modules\Settings\ShopproIntegrationsRepository;
use App\Modules\Settings\ShopproOrderMapper;
use App\Modules\Settings\ShopproOrdersSyncService;
use App\Modules\Settings\ShopproOrderSyncStateRepository;
use App\Modules\Settings\ShopproPaymentStatusSyncService;
use App\Modules\Settings\ShopproProductImageResolver;
use App\Modules\Settings\ShopproStatusMappingRepository;
use App\Modules\Settings\ShopproStatusSyncService;
use App\Modules\Shipments\AllegroTrackingService;
use App\Modules\Shipments\ApaczkaTrackingService;
use App\Modules\Shipments\InpostTrackingService;
use App\Modules\Shipments\ShipmentPackageRepository;
use App\Modules\Shipments\ShipmentTrackingRegistry;
use PDO;

final class CronHandlerFactory
{
    public function __construct(
        private readonly PDO $db,
        private readonly string $integrationSecret,
        private readonly string $basePath
    ) {
    }

    public function build(CronRepository $cronRepository, Logger $logger): CronRunner
    {
        $integrationRepository = new AllegroIntegrationRepository($this->db, $this->integrationSecret);
        $oauthClient = new AllegroOAuthClient();
        $tokenManager = new AllegroTokenManager($integrationRepository, $oauthClient);
        $apiClient = new AllegroApiClient();
        $statusMappingRepository = new AllegroStatusMappingRepository($this->db);
        $ordersRepository = new OrdersRepository($this->db);
        $allegroSyncStateRepository = new AllegroOrderSyncStateRepository($this->db);

        $orderImportService = new AllegroOrderImportService(
            $integrationRepository,
            $tokenManager,
            $apiClient,
            new OrderImportRepository($this->db),
            $statusMappingRepository,
            $ordersRepository
        );

        $ordersSyncService = new AllegroOrdersSyncService(
            $integrationRepository,
            $allegroSyncStateRepository,
            $tokenManager,
            $apiClient,
            $orderImportService
        );

        $shopproIntegrationsRepo = new ShopproIntegrationsRepository($this->db, $this->integrationSecret);
        $shopproApiClient = new ShopproApiClient();
        $shopproSyncStateRepo = new ShopproOrderSyncStateRepository($this->db);
        $shopproStatusMappingRepo = new ShopproStatusMappingRepository($this->db);
        $shopproSyncService = new ShopproOrdersSyncService(
            $shopproIntegrationsRepo,
            $shopproSyncStateRepo,
            $shopproApiClient,
            new OrderImportRepository($this->db),
            $shopproStatusMappingRepo,
            $ordersRepository,
            new ShopproOrderMapper(),
            new ShopproProductImageResolver($shopproApiClient)
        );
        $shopproStatusSyncService = new ShopproStatusSyncService(
            $shopproIntegrationsRepo,
            $shopproSyncService,
            $shopproApiClient,
            $shopproSyncStateRepo,
            $shopproStatusMappingRepo,
            $this->db
        );
        $automationService = $this->buildAutomationService($ordersRepository);

        $shopproPaymentSyncService = new ShopproPaymentStatusSyncService(
            $shopproIntegrationsRepo,
            new ShopproApiClient(),
            $ordersRepository,
            $this->db,
            $automationService
        );

        return new CronRunner(
            $cronRepository,
            $logger,
            [
                'allegro_token_refresh' => new AllegroTokenRefreshHandler(
                    $integrationRepository,
                    $oauthClient
                ),
                'allegro_orders_import' => new AllegroOrdersImportHandler(
                    $ordersSyncService
                ),
                'allegro_status_sync' => new AllegroStatusSyncHandler(
                    new AllegroStatusSyncService(
                        $cronRepository,
                        $orderImportService,
                        $apiClient,
                        $tokenManager,
                        $statusMappingRepository,
                        $allegroSyncStateRepository,
                        $integrationRepository,
                        $this->db
                    )
                ),
                'shoppro_orders_import' => new ShopproOrdersImportHandler(
                    $shopproSyncService
                ),
                'shoppro_order_status_sync' => new ShopproStatusSyncHandler(
                    $shopproStatusSyncService
                ),
                'shoppro_payment_status_sync' => new ShopproPaymentStatusSyncHandler(
                    $shopproPaymentSyncService
                ),
                'shipment_tracking_sync' => new ShipmentTrackingHandler(
                    new ShipmentTrackingRegistry([
                        new InpostTrackingService(
                            new InpostIntegrationRepository($this->db, $this->integrationSecret)
                        ),
                        new ApaczkaTrackingService(
                            new ApaczkaApiClient(),
                            new ApaczkaIntegrationRepository($this->db, $this->integrationSecret)
                        ),
                        new AllegroTrackingService(
                            new InpostIntegrationRepository($this->db, $this->integrationSecret)
                        ),
                    ]),
                    new ShipmentPackageRepository($this->db),
                    $automationService
                ),
                'automation_history_cleanup' => new AutomationHistoryCleanupHandler(
                    new AutomationExecutionLogRepository($this->db)
                ),
                'order_status_aged' => new OrderStatusAgedHandler(
                    new OrderStatusAgedService(
                        new AutomationRepository($this->db),
                        $automationService,
                        $this->db
                    )
                ),
            ]
        );
    }

    private function buildAutomationService(OrdersRepository $ordersRepository): AutomationService
    {
        $automationRepository = new AutomationRepository($this->db);
        $executionLogRepository = new AutomationExecutionLogRepository($this->db);
        $companySettingsRepository = new CompanySettingsRepository($this->db);
        $emailTemplateRepository = new EmailTemplateRepository($this->db);
        $emailMailboxRepository = new EmailMailboxRepository(
            $this->db,
            new IntegrationSecretCipher($this->integrationSecret)
        );
        $template = new Template(
            $this->basePath . '/resources/views',
            new Translator($this->basePath . '/resources/lang', 'pl')
        );

        $emailService = new EmailSendingService(
            $this->db,
            $ordersRepository,
            $emailTemplateRepository,
            $emailMailboxRepository,
            new VariableResolver(new ShipmentPackageRepository($this->db)),
            new AttachmentGenerator(
                new ReceiptRepository($this->db),
                new ReceiptConfigRepository($this->db),
                $template
            )
        );

        $receiptRepository = new ReceiptRepository($this->db);
        $receiptConfigRepository = new ReceiptConfigRepository($this->db);

        $receiptService = new ReceiptService(
            $receiptRepository,
            $receiptConfigRepository,
            $companySettingsRepository,
            $ordersRepository
        );

        return new AutomationService(
            $automationRepository,
            $executionLogRepository,
            $emailService,
            $ordersRepository,
            $companySettingsRepository,
            $receiptRepository,
            $receiptConfigRepository,
            new ShipmentPackageRepository($this->db),
            $receiptService
        );
    }
}
