<?php

/**
 * Vvveb
 *
 * Copyright (C) 2022  Ziadin Givan
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

namespace Vvveb\Controller\Order;

use function Vvveb\__;
use function Vvveb\model;
use Vvveb\Controller\Crud;

class Subscription extends Crud {
	protected string $type = 'subscription';

	protected string $controller = 'subscription';

	protected string $module = 'order';

	/** Subscription status IDs matching the seed data. */
	const STATUS_PENDING  = 1;
	const STATUS_ACTIVE   = 2;
	const STATUS_FAILED   = 3;
	const STATUS_CANCELLED = 4;
	const STATUS_DENIED   = 5;
	const STATUS_EXPIRED  = 6;

	/**
	 * Display the subscription edit form with period, trial, status, and log data.
	 *
	 * @return void
	 */
	public function index(): void {
		parent::index();

		$this->view->period       = ['day' => __('Day'), 'week' => __('Week'), 'month' => __('Month'),  'year' => __('Year')];
		$this->view->trial_period = $this->view->period;

		//load subscription statuses
		$statusModel       = model('subscription_status');
		$statuses          = $statusModel->getAll(['language_id' => $this->global['language_id'] ?? 1] + $this->global);
		$statusOptions     = [];

		if (isset($statuses['subscription_status'])) {
			foreach ($statuses['subscription_status'] as $status) {
				$statusOptions[$status['subscription_status_id']] = $status['name'];
			}
		}

		$this->view->subscription_status = $statusOptions;

		//load subscription logs for the current subscription
		$subscriptionId = $this->request->get['subscription_id'] ?? false;

		if ($subscriptionId) {
			$this->loadLogs($subscriptionId);
		}
	}

	/**
	 * Load subscription history logs and pass them to the view.
	 *
	 * @param int|string $subscriptionId
	 *
	 * @return void
	 */
	private function loadLogs(int|string $subscriptionId): void {
		$logModel = model('subscription_log');
		$logs     = $logModel->getAll([
			'subscription_id' => $subscriptionId,
			'language_id'     => $this->global['language_id'] ?? 1,
		] + $this->global);

		$this->view->subscription_logs = $logs['subscription_log'] ?? [];
	}

	/**
	 * Change the subscription status and record a log entry.
	 *
	 * @param int    $statusId  Target subscription_status_id.
	 * @param string $note      Optional note for the log entry.
	 *
	 * @return void
	 */
	protected function changeStatus(int $statusId, string $note = ''): void {
		$this->checkCsrf();

		$subscriptionId = $this->request->get['subscription_id'] ?? false;

		if (! $subscriptionId) {
			$this->view->errors[] = __('Subscription ID is required!');

			return;
		}

		$model    = model($this->type);
		$result   = $model->edit([
			'subscription' => [
				'subscription_status_id' => $statusId,
				'updated_at'              => date('Y-m-d H:i:s'),
			],
			'subscription_id' => $subscriptionId,
		] + $this->global);

		if ($result) {
			//record log entry
			$logModel = model('subscription_log');
			$logModel->add([
				'subscription_log' => [
					'subscription_id'         => $subscriptionId,
					'subscription_status_id'  => $statusId,
					'notify'                  => 1,
					'note'                    => $note,
					'created_at'              => date('Y-m-d H:i:s'),
				],
			] + $this->global);

			$this->view->success[] = __('Subscription status updated!');
		} else {
			$this->view->errors[] = __('Error updating subscription status!');
		}
	}

	/**
	 * Cancel the subscription.
	 *
	 * @return void
	 */
	public function cancel(): void {
		$note = $this->request->post['note'] ?? __('Cancelled by admin');
		$this->changeStatus(self::STATUS_CANCELLED, $note);
		$this->index();
	}

	/**
	 * Pause the subscription (set to pending).
	 *
	 * @return void
	 */
	public function pause(): void {
		$note = $this->request->post['note'] ?? __('Paused by admin');
		$this->changeStatus(self::STATUS_PENDING, $note);
		$this->index();
	}

	/**
	 * Resume/activate the subscription.
	 *
	 * @return void
	 */
	public function resume(): void {
		$note = $this->request->post['note'] ?? __('Resumed by admin');
		$this->changeStatus(self::STATUS_ACTIVE, $note);
		$this->index();
	}

	/**
	 * Mark subscription as expired.
	 *
	 * @return void
	 */
	public function expire(): void {
		$note = $this->request->post['note'] ?? __('Expired by admin');
		$this->changeStatus(self::STATUS_EXPIRED, $note);
		$this->index();
	}

	/**
	 * Add a log/note entry to a subscription without changing status.
	 *
	 * @return void
	 */
	public function addLog(): void {
		$this->checkCsrf();

		$subscriptionId = $this->request->get['subscription_id'] ?? false;
		$note           = $this->request->post['note'] ?? '';
		$statusId       = (int) ($this->request->post['subscription_status_id'] ?? 0);

		if (! $subscriptionId || ! $note) {
			$this->view->errors[] = __('Subscription ID and note are required!');

			return;
		}

		$logModel = model('subscription_log');
		$result   = $logModel->add([
			'subscription_log' => [
				'subscription_id'         => $subscriptionId,
				'subscription_status_id'  => $statusId ?: self::STATUS_ACTIVE,
				'notify'                  => 0,
				'note'                    => $note,
				'created_at'              => date('Y-m-d H:i:s'),
			],
		] + $this->global);

		if ($result) {
			$this->view->success[] = __('Log entry added!');
		} else {
			$this->view->errors[] = __('Error adding log entry!');
		}

		$this->index();
	}
}
