<?php

namespace Planaday\Database\SQLDatabaseControllers\Booking;

use Planaday\Database\Abstraction\SQLQuery\ColumnTypeMap;
use Planaday\Database\Abstraction\SQLQuery\SQLFactory;
use Planaday\Database\SQLDatabaseControllers\Table;
use Planaday\Platform\PlatformAbstraction\DatabaseInterface;

class BookingMaterialTable extends Table {
	public const BOOKING_MATERIAL_TABLE = 'booking_material';

	public const ID_COLUMN = 'id';
	public const BOOKING_ID_COLUMN = 'booking_id';
	public const MATERIAL_ID_COLUMN = 'material_id';

	public function __construct( DatabaseInterface $querySender, SQLFactory $sql, ColumnTypeMap $columnTypeMap ) {
		$columns = [];

		$columns[self::BOOKING_ID_COLUMN] =implode(" ", [
			$columnTypeMap->UUID(),
			$columnTypeMap->NOT_NULL()
		]);

		$columns[self::MATERIAL_ID_COLUMN] =
		$columns[self::ID_COLUMN] = implode(" ", [
			$columnTypeMap->ID(),
			$columnTypeMap->NOT_NULL()
		]);

		$columns[self::ID_COLUMN] .= ' ' . $columnTypeMap->AUTO_INCREMENT() . ' ' . $columnTypeMap->PRIMARY_KEY();

		parent::__construct( $querySender, $sql, self::BOOKING_MATERIAL_TABLE, $columns, [] );
	}

	/**
	 * @param string $bookingId
	 * @param int $materialId
	 * @param int|null $id
	 *
	 * @return int id of created booking attribute if new, otherwise id of existing
	 */
	public function set(string $bookingId, int $materialId, ?int $id = null):int {
		$table = $this->getSqlTable();
		$array = $this->valuesToArray($bookingId, $materialId);

		if ($id !== null && $this->querySender->idExists($this, $id)) {
			$where = $this->sql->compare($table->getColumn(self::ID_COLUMN), $id, true);
			$query = $this->sql->update($table, $where, $array);

			$this->querySender->sendQuery($query->toQuery());

			return $id;
		}

		$query = $this->sql->insert($table, $array);
		$this->querySender->sendQuery($query->toQuery());

		return $this->querySender->getLastGeneratedInsertId();
	}

	public function remove(int $id):void {
		$table = $this->getSqlTable();
		$where = $this->sql->compare( $table->getColumn( self::ID_COLUMN ), $id, true );
		$query = $this->sql->delete( $table, $where );

		$this->querySender->sendQuery( $query->toQuery() );
	}

	public function removeByBookingId(string $bookingId):void {
		$table = $this->getSqlTable();
		$where = $this->sql->compare( $table->getColumn( self::BOOKING_ID_COLUMN ), $bookingId, true );
		$query = $this->sql->delete( $table, $where );

		$this->querySender->sendQuery( $query->toQuery() );
	}

	public function get(int $id): ?array {
		$table = $this->getSqlTable();
		$where = $this->sql->compare($table->getColumn(self::ID_COLUMN), $id, true);
		$query = $this->sql->query($table, $table);
		$query->setWhere($where);
		$query->setLimit(1);

		$result = $this->querySender->sendQuery($query->toQuery());
		if (!is_array($result) || count($result) < 1) {
			$this->logWarning("No material found with id $id", $result);
			return null;
		}

		return $result[0];
	}

	public function getByBookingId(string $bookingId): array {
		$table = $this->getSqlTable();
		$where = $this->sql->compare( $table->getColumn( self::BOOKING_ID_COLUMN ), $bookingId, true );
		$query = $this->sql->query( $table, $table );
		$query->setWhere( $where );

		$result = $this->querySender->sendQuery( $query->toQuery() );
		if ( ! is_array( $result ) || count( $result ) < 1 ) {
			$this->logWarning( "No material found with booking id $bookingId", $result );

			return [];
		}

		return $result;
	}

	/**
	 * @param string $bookingId
	 * @param int $materialId
	 *
	 * @return array
	 */
	public function valuesToArray(string $bookingId, int $materialId): array {
		$returnArray = [];

		$returnArray[ self::BOOKING_ID_COLUMN ] = $bookingId;
		$returnArray[ self::MATERIAL_ID_COLUMN ] = $materialId;

		return $returnArray;
	}
}