<?php

namespace App\Jobs;

use App\Enum\ResourceEnum\ReviewStatusEnum;
use App\Models\Automation\SmartApproval;
use App\Models\SmartApprovalActivity;
use App\Traits\ModelFinder;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class TriggerProcessFlowJob implements ShouldQueue
{
    use ModelFinder;
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $service;

    /**
     * Create a new job instance.
     */
    public function __construct($service)
    {
        $this->service = $service;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        tenancy()->tenant->run(function () {

            $service = $this->service;
            $service_type = get_class((object) $service);
            $service_id = $service?->id;

            $check_exist = SmartApprovalActivity::query()->where([['service_type', '=', $service_type], ['service_id', '=', $service_id]])->first();

            if ($service && !$check_exist) {
                $smart_approvals = SmartApproval::query()->whereRelation('smartForm', 'model_type', '=', $service_type)->get();

                $smart_approval = null;
                foreach ($smart_approvals as $key => $approval) {
                    $criteria_flow = $approval->criteriaFlow;

                    if (!empty($criteria_flow)) {
                        $expression_result = false;
                        foreach ($criteria_flow as $criterion) {
                            $logic_operator = $criterion->logical_operator ?? null;
                            $model_type = $criterion->model_type;

                            if (class_exists($model_type)) {
                                $model = app($model_type);

                                $values = $criterion->value;
                                $query = $this->getModelQuery($criterion);

                                $criterion_result = (bool)$model->whereRaw($query, $values)->first();

                                if ($logic_operator == 'AND') {
                                    $expression_result = $expression_result && $criterion_result;
                                } elseif ($logic_operator == 'OR') {
                                    $expression_result = $expression_result || $criterion_result;
                                }
                            } else {
                                throw new \InvalidArgumentException("Class $model_type does not exist.");
                            }
                        }

                        // Met Criteria
                        if ($expression_result) {
                            $smart_approval = $approval;
                            break;
                        }
                    }
                }


                // Trigger Approval Flow
                if ($smart_approval) {
                    $process_flow = $smart_approval->approvalProcessFlow()->orderBy('level')->first();
                    SmartApprovalActivity::query()->create([
                        'smart_approval_id' => $smart_approval->id,
                        'process_flow_id' => $process_flow?->id,
                        'status' => ReviewStatusEnum::PENDING->value,
                        'service_type' => $service_type,
                        'service_id' => $service_id,
                    ]);
                }
            }
        });
    }
}
