<?php
namespace PortalPeople\ShippingFields\Model\Checkout;

use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Checkout\Model\Session as CheckoutSession;
use Magento\Cms\Model\BlockFactory as CmsBlockFactory;
use Magento\Cms\Model\Template\FilterProvider;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
use PortalPeople\DisabledDates\Model\ResourceModel\DisabledDate\CollectionFactory;
use PortalPeople\ShippingFields\Model\ShippingDateFormatter;

class DeliveryDateConfigProvider implements ConfigProviderInterface
{
    private const XML_PATH_DISABLE_MON = 'portalpeople_disableddates/weekly_block/disable_mon';
    private const XML_PATH_DISABLE_TUE = 'portalpeople_disableddates/weekly_block/disable_tue';
    private const XML_PATH_DISABLE_WED = 'portalpeople_disableddates/weekly_block/disable_wed';
    private const XML_PATH_DISABLE_THU = 'portalpeople_disableddates/weekly_block/disable_thu';
    private const XML_PATH_DISABLE_FRI = 'portalpeople_disableddates/weekly_block/disable_fri';
    private const XML_PATH_DISABLE_SAT = 'portalpeople_disableddates/weekly_block/disable_sat';
    private const XML_PATH_DISABLE_SUN = 'portalpeople_disableddates/weekly_block/disable_sun';

    private ScopeConfigInterface $scopeConfig;
    private CollectionFactory $collectionFactory;
    private CheckoutSession $checkoutSession;
    private ShippingDateFormatter $shippingDateFormatter;
    private CmsBlockFactory $cmsBlockFactory;
    private FilterProvider $filterProvider;

    public function __construct(
        ScopeConfigInterface $scopeConfig,
        CollectionFactory $collectionFactory,
        CheckoutSession $checkoutSession,
        ShippingDateFormatter $shippingDateFormatter,
        CmsBlockFactory $cmsBlockFactory,
        FilterProvider $filterProvider
    ) {
        $this->scopeConfig = $scopeConfig;
        $this->collectionFactory = $collectionFactory;
        $this->checkoutSession = $checkoutSession;
        $this->shippingDateFormatter = $shippingDateFormatter;
        $this->cmsBlockFactory = $cmsBlockFactory;
        $this->filterProvider = $filterProvider;
    }

    public function getConfig(): array
    {
        $map = [
            0 => self::XML_PATH_DISABLE_SUN,
            1 => self::XML_PATH_DISABLE_MON,
            2 => self::XML_PATH_DISABLE_TUE,
            3 => self::XML_PATH_DISABLE_WED,
            4 => self::XML_PATH_DISABLE_THU,
            5 => self::XML_PATH_DISABLE_FRI,
            6 => self::XML_PATH_DISABLE_SAT,
        ];

        $disabledWeekdays = [];
        foreach ($map as $dayIndex => $path) {
            if ($this->scopeConfig->isSetFlag($path, ScopeInterface::SCOPE_STORE)) {
                $disabledWeekdays[] = $dayIndex;
            }
        }

        // Fetch disabled dates from database and format as YYYY-MM-DD strings
        $disabledDates = [];
        try {
            $collection = $this->collectionFactory->create();
            $dates = $collection->getColumnValues('disabled_date');
            foreach ($dates as $date) {
                if ($date) {
                    $disabledDates[] = $this->formatDate($date);
                }
            }
        } catch (\Exception $e) {
            // Log error but don't break checkout if database query fails
            error_log('Error fetching disabled dates: ' . $e->getMessage());
        }

        // Disable today and the next 2 working days (Mon–Fri) as lead time
        $today = new \DateTime('today');
        $leadTimeDates = $this->getNextWorkingDays(2);
        if ((int)$today->format('N') <= 5) {
            array_unshift($leadTimeDates, $today->format('Y-m-d'));
        }
        $disabledDates = array_values(array_unique(array_merge($disabledDates, $leadTimeDates)));

        // Read saved values from current quote to restore on page refresh
        $savedDate = '';
        $savedMessage = '';
        $savedW3w = '';
        $deliveryInformationHtml = '';
        try {
            $quote = $this->checkoutSession->getQuote();
            if ($quote && $quote->getId()) {
                $rawDate = $quote->getData('shipping_date');
                $savedDate = $this->shippingDateFormatter->formatForDisplay($rawDate);
                $savedMessage = (string)($quote->getData('shipping_message') ?? '');
                $savedW3w = (string)($quote->getData('shipping_w3w') ?? '');
            }
        } catch (\Exception $e) {
            // Don't break checkout if we can't read quote
        }

        try {
            $block = $this->cmsBlockFactory->create()->load('delivery-access', 'identifier');
            if ($block->getId() && $block->getIsActive()) {
                $deliveryInformationHtml = $this->filterProvider->getBlockFilter()->filter(
                    (string)$block->getContent()
                );
            }
        } catch (\Exception $e) {
            // Don't break checkout if CMS block render fails
        }

        return [
            'portalpeopleShippingFields' => [
                'disabledWeekdays' => $disabledWeekdays,
                'disabledDates' => $disabledDates,
                'savedDate' => $savedDate,
                'savedMessage' => $savedMessage,
                'savedW3w' => $savedW3w,
                'deliveryInformationHtml' => $deliveryInformationHtml,
            ],
        ];
    }

    /**
     * Format date to YYYY-MM-DD string
     */
    private function formatDate($date): string
    {
        if ($date instanceof \DateTime) {
            return $date->format('Y-m-d');
        }
        return (string)$date;
    }

    /**
     * Return the next $count working days (Mon–Fri) as YYYY-MM-DD strings,
     * starting from tomorrow.
     */
    private function getNextWorkingDays(int $count): array
    {
        $dates = [];
        $current = new \DateTime('today');
        while (count($dates) < $count) {
            $current->modify('+1 day');
            $dayOfWeek = (int)$current->format('N'); // 1 = Mon, 7 = Sun
            if ($dayOfWeek <= 5) {
                $dates[] = $current->format('Y-m-d');
            }
        }
        return $dates;
    }
}
