<?php

namespace objects;

use classes\db;
use classes\email;
use classes\object_property;
use classes\pdf_generator;
use Exception;
use MailerSend\Exceptions\MailerSendAssertException;
use MailerSend\Exceptions\MailerSendException;
use Psr\Http\Client\ClientExceptionInterface;
use traits\db_object_t;

class bookings_new_o extends db
{
    use db_object_t;

    public object_property $customer_number;
    public object_property $wash_type;
    public object_property $contact_email;
    public object_property $reference_number;
    public object_property $regNrTraekker;
    public object_property $regNrTrailer;
    public object_property $washCertificateEmail;
    public object_property $date;
    public object_property $department;
    public object_property $pickup_bool;
    public object_property $notes;
    public object_property $washCertificateStatus;
    public object_property $washCertificateUrl;
    public object_property $status;
    public object_property $data;

    private static function isCancelled(int $id): bool
    {
        global $db;
        // Check if the booking has been cancelled
        $sql = "SELECT status FROM bookings WHERE id = $id";
        $result = $db->query($sql);
        $row = $db->fetch_assoc($result);
        return $row['status'] === 'cancelled';
    }

    public function structure(): void
    {
        $this->setTable('bookings_new');
    }

    public function delete(int $id): void
    {
        $this->id = $id;
        $this->getObjectProperties();
        // Set the status to cancelled
        $this->status->set('cancelled');
        // Remove the cache
        redis->clear_department_booking_count($this->department->value());
    }

    public function getObjectProperties(): void
    {
        $this->customer_number = new object_property($this->table, $this->id, 'customer_number', 'int', true);
        $this->wash_type = new object_property($this->table, $this->id, 'wash_type', 'string', true);
        $this->contact_email = new object_property($this->table, $this->id, 'contact_email', 'string', true);
        $this->reference_number = new object_property($this->table, $this->id, 'reference_number', 'string', true);
        $this->regNrTraekker = new object_property($this->table, $this->id, 'regNrTraekker', 'string', true);
        $this->regNrTrailer = new object_property($this->table, $this->id, 'regNrTrailer', 'string', true);
        $this->washCertificateEmail = new object_property($this->table, $this->id, 'washCertificateEmail', 'string', true);
        $this->date = new object_property($this->table, $this->id, 'date', 'string', true);
        $this->department = new object_property($this->table, $this->id, 'department', 'int', true);
        $this->pickup_bool = new object_property($this->table, $this->id, 'pickup_bool', 'int', true);
        $this->notes = new object_property($this->table, $this->id, 'notes', 'string', true);
        $this->washCertificateStatus = new object_property($this->table, $this->id, 'washCertificateStatus', 'string', true);
        $this->washCertificateUrl = new object_property($this->table, $this->id, 'washCertificateUrl', 'string', true);
        $this->status = new object_property($this->table, $this->id, 'status', 'string', true);
        $this->data = new object_property($this->table, $this->id, 'data', 'string', true);
    }

    public function parseBookings(array $listObjectsWithPaginationIfSet): array
    {
        // Parse the customer numbers
        $bookings = $this->parseCustomerNumbers($listObjectsWithPaginationIfSet);
        return $bookings;
    }

    public function parseCustomerNumbers(array $listObjectsWithPaginationIfSet): array
    {
        // Parse the customer numbers
        foreach ( $listObjectsWithPaginationIfSet as $key => $value ) {
            $listObjectsWithPaginationIfSet[$key]['customer_name'] = (new users_o())->getCustomerName($value['customer_number']);
        }
        return $listObjectsWithPaginationIfSet;

    }

    /**
     * @param int $customer_number
     * @param string $wash_type
     * @param string $contact_email
     * @param string $reference_number
     * @param string $regNrTraekker
     * @param string $regNrTrailer
     * @param string $washCertificateEmail
     * @param string $date
     * @param string $department
     * @param int $pickup_bool
     * @param string $notes
     * @param string $washCertificateStatus
     * @param string $washCertificateUrl
     * @param string $status
     * @return void
     */
    public function add(int $customer_number, string $wash_type, string $contact_email, string $reference_number, string $regNrTraekker, string $regNrTrailer, string $washCertificateEmail, string $date, string $department, int $pickup_bool, string $notes, string $washCertificateStatus, string $washCertificateUrl, string $status, array $data = []): void
    {
        global $db;
        // Avoid SQL injection
        $wash_type = $db->escape_string($wash_type);
        $contact_email = $db->escape_string($contact_email);
        $reference_number = $db->escape_string($reference_number);
        $regNrTraekker = $db->escape_string($regNrTraekker);
        $regNrTrailer = $db->escape_string($regNrTrailer);
        $washCertificateEmail = $db->escape_string($washCertificateEmail);
        $date = $db->escape_string($date);
        $department = $db->escape_string($department);
        $notes = $db->escape_string($notes);
        $washCertificateStatus = $db->escape_string($washCertificateStatus);
        $washCertificateUrl = $db->escape_string($washCertificateUrl);
        $status = $db->escape_string($status);
        // Create a new record in the database ( Replace the code, if an entry already exists )
        $sql = "INSERT INTO $this->table (customer_number, wash_type, contact_email, reference_number, regNrTraekker, regNrTrailer, washCertificateEmail, date, department, pickup_bool, notes, washCertificateStatus, washCertificateUrl, status) VALUES ($customer_number, '$wash_type', '$contact_email', '$reference_number', '$regNrTraekker', '$regNrTrailer', '$washCertificateEmail', '$date', '$department', $pickup_bool, '$notes', '$washCertificateStatus', '$washCertificateUrl', '$status')";
        $db->query($sql);
        // Clear the cache
        redis->clear_department_booking_count($department);

        // Get the id of the new record
        $this->id = $db->insert_id();

        // Set the object properties
        self::getObjectProperties();

        // Add the data to the object
        $this->data->set(json_encode($data));

        self::objectChanged();
    }

    public function objectChanged(): void
    {
        // Clear the cache
        redis->clear_department_booking_count($this->department->value());
    }

    /**
     * Generate a wash certificate for the booking
     * @param string|null $safety_seal
     * @param string|null $operator
     * @return void
     * @throws Exception If the booking is cancelled
     * @throws Exception If the booking is completed
     * @throws Exception If the booking status is unknown
     * @throws ClientExceptionInterface
     */
    public function generateWashCertificate(string|null $safety_seal, string|null $operator): void
    {
        self::requireSelected();
        // Prepare the date and time
        $date = date('d-m-Y', strtotime($this->date->value()));
        $time = date('H:i', strtotime($this->date->value()));
        // Get the customer name
        $customer_name = (new users_o())->getCustomerName($this->customer_number->value());
        $pdf_generator = new pdf_generator();
        $pdf_generator->add_html($pdf_generator->templates->getTemplate('wash_certificate')
            ->setCompany([
                'name' => 'Truck Wash',
                'address' => 'Letland Allé 2',
                'zip' => 2630,
                'city' => 'Taastrup',
                'phone_prefix' => 45,
                'phone' => 43717886,
                'email' => 'cph@truckwash.dk',
                'website' => 'www.truckwash.dk',
                'images' => [
                    'logo' => '/truckwash-banner-png.png',
                    'banner' => '/truckwash-banner-png.png',
                    'signature' => '/truckwash-underskrift.png',
                ],
            ])
            ->addData([
                'seal_number' => $safety_seal,
                'reg_1' => $this->regNrTraekker->value(),
                'reg_2' => $this->regNrTrailer->value(),
                'date' => $date,
                'time' => $time,
                'carried_out_by' => $operator,
                'department_id' => $this->department->value(),
                'customer_name' => $customer_name,
                'type' => $this->wash_type->value(),
            ])
            ->getHtml()
        );
        // Generate the pdf
        $pdf_path = $pdf_generator->generate_pdf();
        // Set the wash certificate url
        $this->washCertificateUrl->set($pdf_path);
        // Set the wash certificate status
        $this->washCertificateStatus->set('completed');
        // Set the status to completed
        $this->status->set('completed');
        self::sendWashCertificateEmail();
    }

    /**
     * Send the wash certificate email
     * @throws MailerSendException
     * @throws ClientExceptionInterface
     * @throws MailerSendAssertException
     * @throws \JsonException
     * @throws Exception
     */
    public function sendWashCertificateEmail(): void
    {
        self::requireSelected();
        // Send the wash certificate email
        $email = new email();
        $email->sendWashCertificateEmail(
            $this->id,
            (new users_o())->getCustomerName($this->customer_number->value()),
            $this->contact_email->value(),
            $this->reference_number->value(),
            $this->washCertificateUrl->value(),
            $this->washCertificateEmail->value(),
        );
    }

}