<?php

namespace TPsoft\BugreportBackend;

require_once __DIR__ . '/Init.php';

use TPsoft\APIlite\APIlite;
use TPsoft\BugreportBackend\Models\Reports;
use TPsoft\BugreportBackend\Models\Attachments;
use TPsoft\BugreportBackend\Models\Options;


class API extends APIlite
{
	/**
	 * Add new report
	 *
	 * @param string $title
	 * @param string $description
	 * @param int $status 0 = Uncategorized, 1 = Waiting, 2 = InProgress, 3 = Blocked, 4 = Archived
	 * @param string $group
	 * @param int $priority 0 = Low, 1 = Medium, 2 = High, 3 = Urgent
	 *
	 * @return int
	 */
	public function add(string $title, string $description, int $status = 0, ?string $group = null, int $priority = 0): int
	{
		$status = intval($status);
		$priority = intval($priority);
		$reports = new Reports();
		$report_id = $reports->report(null, [
			'report_title' => $title,
			'report_description' => $description,
			'report_status' => $status,
			'report_group' => $group,
			'report_priority' => $priority,
		]);
		return $report_id;
	}

	/**
	 * Update report
	 *
	 * @param int $report_id
	 * @param array $report_data
	 *
	 * @return bool
	 */
	public function update(int $report_id, array $report_data): bool
	{
		$reports = new Reports();
		$suc = $reports->report($report_id, $report_data);
		return $suc !== false;
	}

	/**
	 * Delete report
	 *
	 * @param int $report_id
	 *
	 * @return bool
	 */
	public function delete(int $report_id): bool
	{
		$reports = new Reports();
		$suc = $reports->report($report_id, null);
		return $suc !== false;
	}

	/**
	 * Get report
	 *
	 * @param int $report_id
	 *
	 * @return array
	 */
	public function get(int $report_id): array
	{
		$reports = new Reports();
		return $reports->report($report_id);
	}

	/**
	 * Get all reports
	 *
	 * @param array $status 0 = Uncategorized, 1 = Waiting, 2 = InProgress, 3 = Blocked, 4 = Archived
	 * @param int $page Pagination from 0
	 *
	 * @return array
	 */
	public function getAll(?array $status = null, int $page = 0): array
	{
		$page = intval($page);
		$reports = new Reports();
		if ($status === null) $status = array(0, 1, 2, 3);
		$ret = $reports->search('reports')
			->where(['report_status' => $status])
			->order(array('report_priority' => 'DESC', 'ordnum' => 'ASC'))
			->limit($page * 10, 10)
			->toArray();
		return $ret;
	}

	/**
	 * Get all reports grouped by status
	 *
	 * @param array $status 0 = Uncategorized, 1 = Waiting, 2 = InProgress, 3 = Blocked, 4 = Archived
	 * @param int $page Pagination from 0
	 *
	 * @return array
	 */
	public function getAllGrouped(?array $status = null, int $page = 0): array
	{
		$page = intval($page);
		$all = $this->getAll($status, $page);
		$groups = [];
		foreach ($all as $report) {
			$groups[$report['report_status']][] = $report;
		}
		return $groups;
	}

	/**
	 * Get archived reports
	 *
	 * @param int $page Pagination from 0
	 *
	 * @return array
	 */
	public function getArchived(int $page = 0): array
	{
		$page = intval($page);
		$reports = new Reports();
		$ret = $reports->search('reports')
			->where(['report_status' => 4])
			->order(array('created_dt' => 'DESC'))
			->limit($page * 10, 10)
			->toArray();
		return $ret;
	}

	/**
	 * Update report order number
	 *
	 * @param array $ordnums report_id => ordnum
	 *
	 * @return bool
	 */
	public function updateOrdNum(array $ordnums): bool
	{
		$reports = new Reports();
		$suc = true;
		foreach ($ordnums as $report_id => $ordnum) {
			$suc &= $reports->report($report_id, ['ordnum' => $ordnum]);
		}
		return $suc;
	}

	/**
	 * Update report status
	 *
	 * @param int $report_id
	 * @param int $status 0 = Uncategorized, 1 = Waiting, 2 = InProgress, 3 = Blocked, 4 = Archived
	 *
	 * @return bool
	 */
	public function updateStatus(int $report_id, int $status): bool
	{
		$reports = new Reports();
		$suc = $reports->report($report_id, ['report_status' => $status]);
		return $suc !== false;
	}

	/**
	 * Add report attachment
	 *
	 * @param int $report_id
	 * @param string $attachment_type "comment" or "file"
	 * @param string $attachment_content
	 *
	 * @return bool
	 */
	public function attachmentAdd(int $report_id, string $attachment_type, string $attachment_content): bool
	{
		if ($attachment_type == 'file') {
			$data = json_decode($attachment_content, true);
			if (!is_array($data)) return false;
			$base64 = preg_replace('/^data:.*?;base64,/', '', $data['base64']);
			$base64_data = base64_decode($base64);
			$filename = 'report_' . $report_id . '_' . time() . '_' . $this->sanitizeFilename($data['filename']);
			file_put_contents(UPLOAD_DIR_ATTACHMENTS . $filename, $base64_data);
			$attachment_content = $filename;
		}
		$attachments = new Attachments();
		$suc = $attachments->attachment(null, [
			'report_id' => $report_id,
			'attachment_type' => $attachment_type,
			'attachment_content' => $attachment_content,
			'created_dt' => date('Y-m-d H:i:s')
		]);
		return $suc !== false;
	}

	private function sanitizeFilename($filename, $allowedExtensions = [])
	{
		// Rozdelenie názvu a prípony
		$pathInfo = pathinfo($filename);
		$name = $pathInfo['filename'] ?? 'file';
		$extension = strtolower($pathInfo['extension'] ?? '');
		// Odstránenie nebezpečných znakov z názvu
		$name = preg_replace('/[^a-zA-Z0-9_-]/', '_', $name);
		$name = substr($name, 0, 100); // voliteľné obmedzenie dĺžky
		// Validácia prípony, ak je zoznam povolený
		if (
			$allowedExtensions
			&& count($allowedExtensions) > 0
			&& !in_array($extension, $allowedExtensions)
		) {
			$extension = 'bin'; // fallback ak prípona nie je povolená
		}
		return $name . '.' . $extension;
	}

	/**
	 * Update report attachment
	 *
	 * @param int $attachment_id
	 * @param string $attachment_content
	 *
	 * @return bool
	 */
	public function attachmentUpdate(int $attachment_id, string $attachment_content): bool
	{
		if (strlen(trim($attachment_content)) <= 0) return $this->attachmentDelete($attachment_id);
		$attachments = new Attachments();
		$suc = $attachments->attachment($attachment_id, [
			'attachment_content' => $attachment_content,
			'updated_dt' => date('Y-m-d H:i:s')
		]);
		return $suc !== false;
	}

	/**
	 * Get all report attachments
	 *
	 * @param int $report_id
	 *
	 * @return array
	 */
	public function attachmentGetAll(int $report_id): array
	{
		$attachments = new Attachments();
		$all = $attachments->search('attachments')
			->where(['report_id' => $report_id])
			->order(array('created_dt' => 'ASC'))
			->toArray();
		if (is_array($all)) foreach ($all as $key => $row) {
			if ($all[$key]['attachment_type'] == 'file') {
				$all[$key]['attachment_content'] = '?action=attachmentDownload&filename=' . $all[$key]['attachment_content'];
			}
		}
		return $all;
	}

	/**
	 * Delete report attachment
	 *
	 * @param int $attachment_id
	 *
	 * @return bool
	 */
	public function attachmentDelete(int $attachment_id): bool {
		$attachments = new Attachments();
		$suc = $attachments->attachment($attachment_id, null);
		return $suc !== false;
	}

	/**
	 * Download report attachment
	 *
	 * @param string $filename
	 *
	 * @return void
	 */
	public function attachmentDownload(string $filename): void {
		$filename = $this->sanitizeFilename($filename);
		$filename = UPLOAD_DIR_ATTACHMENTS . $filename;
		if (file_exists($filename)) {
			header('Content-Description: File Transfer');
			header('Content-Type: application/octet-stream');
			header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
			header('Expires: 0');
			header('Cache-Control: must-revalidate');
			header('Pragma: public');
			header('Content-Length: ' . filesize($filename));
			readfile($filename);
			exit;
		}
	}

}
