<?php

namespace vonRotenberg\WeinanlieferungBundle\EventListener;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Contao\CoreBundle\Monolog\ContaoContext;
use Contao\MemberModel;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Filesystem\Filesystem;
use vonRotenberg\WeinanlieferungBundle\Event\CheckInCompletedEvent;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLageModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;

/**
 * Listener for the CheckInCompletedEvent.
 * Generates a CSV export file for each checked-in booking.
 */
class CheckInCompletedListener implements EventSubscriberInterface
{
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var string
     */
    private $projectDir;

    /**
     * Constructor.
     *
     * @param LoggerInterface $logger
     * @param string $projectDir
     */
    public function __construct(LoggerInterface $logger, string $projectDir)
    {
        $this->logger = $logger;
        $this->projectDir = $projectDir;
    }

    /**
     * Returns an array of event names this subscriber wants to listen to.
     *
     * @return array The event names to listen to
     */
    public static function getSubscribedEvents()
    {
        return [
            CheckInCompletedEvent::NAME => 'onCheckInCompleted',
        ];
    }

    /**
     * Handle the check-in completed event.
     *
     * @param CheckInCompletedEvent $event
     */
    public function onCheckInCompleted(CheckInCompletedEvent $event)
    {
        // Get the reservation data from the event
        $reservationData = $event->getReservationData();
        $reservationModel = $event->getReservationModel();

        // Log the event for testing purposes
        $this->logger->log(
            LogLevel::INFO,
            sprintf('Check-in completed for reservation ID: %s', $reservationData['id']),
            ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN')]
        );

        // Generate and save the CSV export
        $this->generateCsvExport($reservationData, $reservationModel);
    }

    /**
     * Generate and save the CSV export file.
     *
     * @param array $reservationData
     * @param object $reservationModel
     */
    private function generateCsvExport(array $reservationData, $reservationModel)
    {
        // Create export directory if it doesn't exist
        $exportDir = $this->projectDir . '/export/check_in';
        $filesystem = new Filesystem();

        if (!$filesystem->exists($exportDir)) {
            $filesystem->mkdir($exportDir, 0755);
        }

        // Get member data
        $memberId = $reservationData['uid'];
        $memberModel = MemberModel::findById($memberId);

        if (null === $memberModel) {
            $this->logger->log(
                LogLevel::ERROR,
                sprintf('Could not find member with ID: %s', $memberId),
                ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN_CSV_EXPORT')]
            );
            return;
        }

        // Get behaelter numbers
        $behaelterNumbers = json_decode($reservationData['behaelter_numbers'], true);
        if (!is_array($behaelterNumbers) || empty($behaelterNumbers)) {
            $this->logger->log(
                LogLevel::ERROR,
                sprintf('No behaelter numbers found for reservation ID: %s', $reservationData['id']),
                ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN_CSV_EXPORT')]
            );
            return;
        }

        // Format check-in date
        $checkInDate = date('d.m.Y', $reservationData['checked_in_on']);

        // Get sorten (grape varieties and harvest types)
        $sortenData = [];
        $sortenLeseartPairs = explode(';', $reservationData['sorten']);
        foreach ($sortenLeseartPairs as $pair) {
            if (empty($pair)) {
                continue;
            }

            list($sorteId, $leseartId) = explode(',', $pair);

            $rebsorteModel = WeinanlieferungRebsorteModel::findById($sorteId);
            $leseartModel = WeinanlieferungLeseartModel::findById($leseartId);

            if (null !== $rebsorteModel && null !== $leseartModel) {
                $sortenData[] = [
                    'rebsorte_id' => $rebsorteModel->ident_string,
                    'rebsorte_title' => $rebsorteModel->title,
                    'leseart_id' => $leseartModel->ident_string,
                    'leseart_title' => $leseartModel->title
                ];
            }
        }

        // Get lagen (locations)
        $lagenData = [];
        $lagenIds = explode(',', $reservationData['lage']);
        foreach ($lagenIds as $lageId) {
            if (empty($lageId)) {
                continue;
            }

            $lageModel = WeinanlieferungLageModel::findById($lageId);

            if (null !== $lageModel) {
                $lagenData[] = [
                    'lage_id' => $lageModel->ident_string,
                    'lage_title' => $lageModel->title
                ];
            }
        }

        // Get ernteart (harvest method)
        $ernteartValues = explode(',', $reservationData['ernteart']);
        $ernteartMapping = [
            'handlese' => 'H',
            'vollernter' => 'V'
        ];

        // Prepare CSV data
        $csvData = [];

        // For each behaelter, create a line in the CSV
        foreach ($behaelterNumbers as $behaelterNumber) {
            // Skip special value 9999 if needed
            if ($behaelterNumber === '9999') {
                continue;
            }

            // Use the first sorte, leseart, and lage if available
            $rebsorteId = !empty($sortenData) ? $sortenData[0]['rebsorte_id'] : '';
            $rebsorteTitle = !empty($sortenData) ? $sortenData[0]['rebsorte_title'] : '';
            $leseartId = !empty($sortenData) ? $sortenData[0]['leseart_id'] : '';
            $leseartTitle = !empty($sortenData) ? $sortenData[0]['leseart_title'] : '';
            $lageId = !empty($lagenData) ? $lagenData[0]['lage_id'] : '';
            $lageTitle = !empty($lagenData) ? $lagenData[0]['lage_title'] : '';

            // Map ernteart values to H/V
            $ernteart = '';
            foreach ($ernteartValues as $value) {
                if (isset($ernteartMapping[$value])) {
                    $ernteart = $ernteartMapping[$value];
                    break;
                }
            }

            // Create CSV line
            $csvData[] = [
                $memberModel->memberno, // member id
                $memberModel->firstname . ' ' . $memberModel->lastname, // member first and lastname
                $rebsorteId, // rebsorte identifikator
                $rebsorteTitle, // rebsorte title
                $lageId, // lage identifikator
                $lageTitle, // lage title
                $leseartId, // leseart identifikator
                $leseartTitle, // leseart title
                $ernteart, // ernteart (H for handlese, V for vollernter)
                $behaelterNumber, // behaelter number
                $checkInDate, // check-in date
                $reservationData['behaelter'] // behaelter amount for the whole checked-in booking
            ];
        }

        // Generate CSV file
        $filename = $reservationData['id'] . '_' . $memberModel->memberno . '.csv';
        $filepath = $exportDir . '/' . $filename;

        $file = fopen($filepath, 'w');

        foreach ($csvData as $line) {
            fputcsv($file, $line, ';');
        }

        fclose($file);

        $this->logger->log(
            LogLevel::INFO,
            sprintf('CSV export created for reservation ID: %s at %s', $reservationData['id'], $filepath),
            ['contao' => new ContaoContext(__METHOD__, 'CHECK_IN_CSV_EXPORT')]
        );
    }
}