<?php

namespace Modules\Offer\Models;

use App\Libraries\EgyptTime;
use CodeIgniter\Model;

class OfferModel extends Model
{
	/** Egypt admin display: day/month/year (e.g. 26/06/2026). */
	public const EGYPT_DISPLAY_DATE_FORMAT = 'd/m/Y';
	protected $DBGroup              = 'default';
	protected $table                = 'offers';
	protected $primaryKey           = 'id';
	protected $useAutoIncrement     = true;
	protected $insertID             = 0;
	protected $returnType           = 'object';
	protected $useSoftDeletes       = true;
	protected $protectFields        = true;
	protected $allowedFields        = ['id','code','offer_title','offer_description','start_date','end_date','booking_start_date','booking_end_date','travel_start_date','travel_end_date','min_passengers','discount','discount_type','discount_cap','min_discount','max_discount','condition','offer_for','offer_image','seat_class','trip_category'];

	// Dates
	protected $useTimestamps        = true;
	protected $dateFormat           = 'datetime';
	protected $createdField         = 'created_at';
	protected $updatedField         = 'updated_at';
	protected $deletedField         = 'deleted_at';

	// Validation
	protected $validationRules      = [];
	protected $validationMessages   = [];
	protected $skipValidation       = true;
	protected $cleanValidationRules = true;

	// Callbacks
	protected $allowCallbacks       = true;
	protected $beforeInsert         = [];
	protected $afterInsert          = [];
	protected $beforeUpdate         = [];
	protected $afterUpdate          = [];
	protected $beforeFind           = [];
	protected $afterFind            = [];
	protected $beforeDelete         = [];
	protected $afterDelete          = [];


	public function getOffersWithDetails()
	{

		$roleId     = session()->get("role_id");
        $companyId  = session()->get("company_id");
        $user_id    = session()->get("user_id");

        if($roleId == 1){
			return $this->select('
					offers.*,
					GROUP_CONCAT(DISTINCT companies.name SEPARATOR ", ") AS company_names
				')
				->join('offer_details', 'offer_details.offer_id = offers.id', 'left')
				->join('companies', 'FIND_IN_SET(companies.id, offer_details.company_id)', 'left')
				->where('offers.deleted_at IS NULL')
				->groupBy('offers.id')
				->asObject()
				->findAll();
		}else{
			return $this->select('
					offers.*,
					GROUP_CONCAT(DISTINCT companies.name SEPARATOR ", ") AS company_names
				')
				->join('offer_details', 'offer_details.offer_id = offers.id', 'left')
				->join('companies', 'FIND_IN_SET(companies.id, offer_details.company_id)', 'left')
				->where('offers.deleted_at IS NULL')
				->where('companies.id',$companyId)
				->groupBy('offers.id')
				->asObject()
				->findAll();
		}
	}

	/**
	 * Display calendar date in Egypt format (dd/mm/yyyy, Africa/Cairo).
	 */
	public static function formatDisplayDate(?string $date): string
	{
		$date = trim((string) $date);
		if ($date === '') {
			return '';
		}

		$normalized = self::normalizeStoredDate($date);
		if ($normalized === null || $normalized === '') {
			return '';
		}

		try {
			// Noon Cairo avoids DST/midnight edge cases on calendar-only dates.
			return EgyptTime::parse($normalized . ' 12:00:00')->format(self::EGYPT_DISPLAY_DATE_FORMAT);
		} catch (\Exception $e) {
			return $date;
		}
	}

	/**
	 * Parse Egypt admin input (dd/mm/yyyy, dd-mm-yyyy, yyyy-mm-dd) to yyyy-mm-dd for storage.
	 */
	public static function normalizeStoredDate(?string $date): ?string
	{
		$date = trim((string) $date);
		if ($date === '') {
			return null;
		}

		if (preg_match('/^\d{4}-\d{2}-\d{2}/', $date)) {
			return substr($date, 0, 10);
		}

		$tz = EgyptTime::timezone();
		$datePart = substr($date, 0, 10);

		foreach (['d/m/Y', 'd-m-Y'] as $format) {
			$parsed = \DateTime::createFromFormat('!' . $format, $datePart, $tz);
			if ($parsed instanceof \DateTime) {
				$errors = \DateTime::getLastErrors();
				if (($errors['warning_count'] ?? 0) === 0 && ($errors['error_count'] ?? 0) === 0) {
					return $parsed->format('Y-m-d');
				}
			}
		}

		try {
			return EgyptTime::toDateString($date);
		} catch (\Exception $e) {
			return $date;
		}
	}

	/**
	 * @param array<string, mixed> $data
	 * @return array<string, mixed>
	 */
	public static function normalizeOfferDates(array $data): array
	{
		foreach ([
			'start_date',
			'end_date',
			'booking_start_date',
			'booking_end_date',
			'travel_start_date',
			'travel_end_date',
		] as $field) {
			if (array_key_exists($field, $data)) {
				$data[$field] = self::normalizeStoredDate($data[$field] ?? null);
			}
		}

		return $data;
	}

	/**
	 * Offer is active when today falls between start_date and end_date (inclusive).
	 */
	public static function isOfferActive(?string $startDate, ?string $endDate, ?string $today = null): bool
	{
		$start = substr(trim((string) $startDate), 0, 10);
		$end = substr(trim((string) $endDate), 0, 10);
		if ($start === '' || $end === '') {
			return false;
		}

		$today = $today ?? egypt_today();

		return $today >= $start && $today <= $end;
	}

	/**
	 * @return array{total: int, active: int, inactive: int}
	 */
	public function getOfferStatistics(int $roleId, ?int $companyId): array
	{
		$offers = $this->getOffersWithDetails();
		$today = egypt_today();
		$active = 0;

		foreach ($offers as $offer) {
			if (self::isOfferActive($offer->start_date ?? null, $offer->end_date ?? null, $today)) {
				$active++;
			}
		}

		$total = count($offers);

		return [
			'total' => $total,
			'active' => $active,
			'inactive' => $total - $active,
		];
	}

	public static function formatDiscountDisplay(object $offer): string
	{
		$amount = number_format((float) ($offer->discount ?? 0), 2);
		if (isset($offer->discount_type) && (int) $offer->discount_type === 1) {
			return lang('Localize.key_currency_egp') . ' ' . $amount;
		}

		return $amount . '%';
	}

	public static function statusBadgeHtml(bool $isActive): string
	{
		if ($isActive) {
			return '<span class="badge bg-success">Active</span>';
		}

		return '<span class="badge bg-secondary">Inactive</span>';
	}

	/**
	 * @param \CodeIgniter\Database\BaseBuilder $builder
	 */
	public static function applyStatusFilter($builder, string $statusFilter, ?string $today = null): void
	{
		$statusFilter = strtolower(trim($statusFilter));
		if ($statusFilter === '' || $statusFilter === 'all') {
			return;
		}

		$today = $today ?? egypt_today();

		if ($statusFilter === 'active') {
			$builder->where('DATE(offers.start_date) <=', $today)
				->where('DATE(offers.end_date) >=', $today);

			return;
		}

		if ($statusFilter === 'inactive') {
			$builder->groupStart()
				->where('DATE(offers.start_date) >', $today)
				->orWhere('DATE(offers.end_date) <', $today)
				->orWhere('offers.start_date IS NULL', null, false)
				->orWhere('offers.end_date IS NULL', null, false)
				->orWhere('offers.start_date', '')
				->orWhere('offers.end_date', '')
				->groupEnd();
		}
	}
}
