<?php

namespace Planaday\Database\SQLDatabaseControllers\Course;

use ArrayAccess;
use Countable;
use Planaday\Database\SQLDatabaseControllers\Database;
use Planaday\Entities\Course\CourseDatabase;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\Course\DTO\CourseSearch;
use Planaday\Utility\DataGrouping\Collection;
use Traversable;

class SQLCourseDatabase implements CourseDatabase, Database {
	public function __construct(
		protected CourseTable $table,
		protected CourseCompanyLink $courseCompanyLink
	) {}

	public function setCourse( Course $course ):void {
		$this->table->setCourse($course);
		$this->courseCompanyLink->setCompaniesForCourse($course->getId(), $course->getCompanies());
	}

	public function getCourseById( int $id ): ?Course {
		$course = $this->table->getCourseById($id);
		$course?->setCompanies(
			Collection::fromIterable(
				$this->courseCompanyLink->getCompaniesForCourse( $course->getId()
				)
			)
		);
		return $course;
	}

	public function getCoursesBySearch(CourseSearch $search): ArrayAccess&Traversable&Countable {
		$courses = $this->table->getCoursesBySearch($search);

		foreach ($courses as $course) {
			$course->setCompanies(
				Collection::fromIterable(
					$this->courseCompanyLink->getCompaniesForCourse( $course->getId() )
				)
			);
		}

		return $courses;
	}

	public function getUniqueLabelsCourse(): ArrayAccess&Traversable&Countable {
		return $this->table->getUniqueLabelsCourse();
	}

	public function getAll(): ArrayAccess&Traversable&Countable {
		$courses = $this->table->getAll();
		foreach ($courses as $course) {
			$course->setCompanies(
				Collection::fromIterable(
					$this->courseCompanyLink->getCompaniesForCourse( $course->getId()
					)
				)
			);
		}
		return $courses;
	}

	public function setAll( ArrayAccess&Traversable&Countable $courses, bool $wipeDB = false ):void {
		$this->table->setAll($courses, $wipeDB);
		foreach ($courses as $course) {
			$this->courseCompanyLink->setCompaniesForCourse($course->getId(), $course->getCompanies());
		}
	}

	public function getCoursesByTimeSlot(int $startDate, int $endDate): ArrayAccess&Traversable&Countable {
		$courses = $this->table->getCoursesByTimeSlot($startDate, $endDate);
		foreach ($courses as $course) {
			$course->setCompanies(
				Collection::fromIterable(
					$this->courseCompanyLink->getCompaniesForCourse( $course->getId()
					)
				)
			);
		}
		return $courses;
	}

	public function getCreateTableQuery( bool $force = false ): string {
		$outputQuery = '';

		if (!$this->table->isTableValid() || $force ) $outputQuery .= $this->table->getDropTableQuery() . $this->table->getCreateTableQuery();
		if (!$this->courseCompanyLink->isTableValid() || $force ) $outputQuery .= $this->courseCompanyLink->getDropTableQuery() . $this->courseCompanyLink->getCreateTableQuery();

		return $outputQuery;
	}

	public function getDropTableQuery(): string {
		return $this->table->getDropTableQuery() .
		       $this->courseCompanyLink->getDropTableQuery();
	}

	public function isDatabaseValid(): bool {
		return $this->table->isTableValid() &&
		       $this->courseCompanyLink->isTableValid();
	}

	public function getCountAll(): int {
		return $this->table->getCountAll();
	}

	public function getAllRaw(): ArrayAccess&Traversable&Countable {
		return $this->table->getAllRaw();
	}

	public function rebuildTables(): void {
		$this->table->rebuildTable();
		$this->courseCompanyLink->rebuildTable();
	}
}