<?php

namespace Yuvayana\Acadlix\Common\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;

defined('ABSPATH') || exit();

if (!class_exists('Order')) {
  class Order extends Model
  {
    const STATUS_PENDING = 'pending';
    const STATUS_SUCCESS = 'success';
    const STATUS_FAILED = 'failed';
    protected $table;

    protected $fillable = [
      'user_id',
      'subscription_id',
      'parent_id',
      'status', // pending, success, failed
      'coupon_id',
      'coupon_code',
      'coupon_amount',
      'discount_type',
      'extra_charges',
      'total_amount'
    ];

    protected $casts = [
      'user_id' => 'integer',
    ];

    public function __construct(array $attributes = [])
    {
      parent::__construct($attributes);

      $this->table = acadlix()->helper()->acadlix_table_prefix('orders');
    }

    public function setExtraChargesAttribute($value)
    {
      $this->attributes['extra_charges'] = acadlix()->helper()->acadlix_format_price_for_storage($value);
    }

    public function getExtraChargesAttribute($value)
    {
      return acadlix()->helper()->acadlix_format_price_for_display($value);
    }

    public function setTotalAmountAttribute($value)
    {
      $this->attributes['total_amount'] = acadlix()->helper()->acadlix_format_price_for_storage($value);
    }

    public function getTotalAmountAttribute($value)
    {
      return acadlix()->helper()->acadlix_format_price_for_display($value);
    }

    public function scopeOfSuccess($query)
    {
      return $query->where('status', self::STATUS_SUCCESS);
    }

    public function order_items()
    {
      return $this->hasMany(acadlix()->model()->orderItem(), 'order_id', 'id');
    }

    public function getCourseNames()
    {
      return $this
        ->order_items
        ->map(fn($item) => $item->item->post_title ?? $item->item_title ?? '')
        ->filter()
        ->implode(', ');
    }

    public function order_metas()
    {
      return $this->hasMany(acadlix()->model()->orderMeta(), 'order_id', 'id');
    }

    public function activity_logs()
    {
      return $this
        ->hasMany(acadlix()->model()->userActivityMeta(), 'type_id', 'id')
        ->where('type', 'order')
        ->where('meta_key', 'activity_log')
        ->orderBy('id', 'desc');
    }

    public function getMetaValue($key)
    {
      $meta = $this->order_metas()->where('meta_key', $key)->first();

      // Check if the meta exists and return its value or null
      return $meta?->meta_value ?? null;
    }

    public function updateStatus($status = self::STATUS_PENDING)
    {
      return $this->update(['status' => $status]);
    }

    public function updateOrCreateMeta($metaKey, $metaValue)
    {
      return $this->order_metas()->updateOrCreate(
        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Its custom order meta table
        ['meta_key' => $metaKey],  // Condition to check for existing meta_key
        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Its custom order meta table
        ['meta_value' => $metaValue]  // Values to update or create
      );
    }

    public function createActivityLog($message = '')
    {
      return acadlix()->model()->userActivityMeta()->create([
        'user_id' => $this->user_id ?? 0,
        'type' => 'order',
        'type_id' => $this->id,
        'meta_key' => 'activity_log',  // phpcs:ignore
        'meta_value' => $message  // phpcs:ignore
      ]);
    }

    public function user()
    {
      return $this->belongsTo(acadlix()->model()->wpUsers(), 'user_id', 'ID');
    }

    public function delete()
    {
      // Delete associated order items and their metas
      acadlix()
        ->model()
        ->enrollmentSource()
        ->revokeAccess('order', $this->id);

      acadlix()
        ->model()
        ->userActivityMeta()
        ->where('type', 'order')
        ->where('type_id', $this->id)
        ->delete();
      // check if payment if offline to delete uploaded files
      $payment_method = $this->getMetaValue('payment_method');
      if ($payment_method === 'offline') {
        // Add logic to delete uploaded files related to offline payment
        $uploaded_files = $this->getMetaValue('offline_upload_file');
        if ($uploaded_files) {
          if (file_exists($uploaded_files['file_path'])) {
            wp_delete_file($uploaded_files['file_path']);
          }
        }
      }
      return parent::delete();
    }

    public function pending_order()
    {
      if ($this->status === self::STATUS_PENDING) {
        return $this;
      }
      $this->updateStatus(self::STATUS_PENDING);
      // unenroll user from purchased courses
      acadlix()
        ->model()
        ->enrollmentSource()
        ->revokeAccess('order', $this->id);

      return $this;
    }

    protected function enrollItem($item, $order, $via = 'user', $viaId = 0)
    {
      if ($item->type === 'course') {
        $course = acadlix()->model()->course()->find($item->item_id);
        if (!$course) {
          throw new \Exception('Course not found for Order Item ID ' . $item->id . ' with Course ID ' . $item->item_id);
        }

        $courseSectionContentId = $course->getCurrentCourseContentId($order->user_id);

        acadlix()
          ->model()
          ->courseEnrollment()
          ->enroll(
            $order->user_id,
            $item->item_id,
            [
              'source_type' => 'order',
              'source_id' => $item->order_id,
              'type' => $item->type,
              'item_id' => $item->item_id,
              'via' => $via ?? 'user',
              'via_id' => $viaId > 0 ? $viaId : $order->user_id,
              'course_section_content_id' => $courseSectionContentId,
            ]
          );
      }
    }

    public function success_order($via = 'user', $viaId = 0)
    {
      if ($this->status === self::STATUS_SUCCESS) {
        return $this;
      }
      $this->updateStatus(self::STATUS_SUCCESS);
      // enroll user to purchased courses
      $this->order_items->each(function ($item) use ($via, $viaId) {
        // 1. If it's a native course, handle it directly in Free
        $this->enrollItem($item, $this, $via, $viaId);
        /**
         * 2. Extensibility Hook for Anything Else (Pro Features)
         * If the item is NOT a course (e.g., 'bundle', 'membership', 'download'),
         * we pass it to this hook so Pro addons can process it.
         */
        do_action('acadlix_order_success_order_item', $item, $this, $via, $viaId);

      });

      // Universal hook after order processing finishes
      do_action('acadlix_order_success_order_complete', $this, $via, $viaId);

      // send mail on success
      acadlix()->notifications()->email()->handleCoursePurchaseEmail($this->id);

      return $this;
    }

    public function failed_order()
    {
      if ($this->status === self::STATUS_FAILED) {
        return $this;
      }
      $this->updateStatus(self::STATUS_FAILED);

      // unenroll user from purchased courses
      acadlix()
        ->model()
        ->enrollmentSource()
        ->revokeAccess('order', $this->id);

      // send mail on failed
      acadlix()->notifications()->email()->handleFailedTransationEmail($this->id);
      return $this;
    }

    public function getTodaySalesTotal()
    {
      return $this
        ->whereDate('created_at', Carbon::today())
        ->ofSuccess()
        ->sum('total_amount');
    }

    public function getTotalSales()
    {
      return $this
        ->ofSuccess()
        ->sum('total_amount');
    }
  }
}
