<?php

namespace App\Providers;

use App\Enumerations\CronTaskType;
use App\Models\Tenant;
use App\Scopes\CommonController;
use Illuminate\Http\Request;
use Carbon\Carbon;
use App\Models\CronTask;
use Psr\Log\LoggerInterface;

class CronTaskHandleProvider extends CommonController
{
    public function run(Request $request)
    {
        $now = Carbon::now();

        $tenants = Tenant::where('has_active_instance', true)->get();
        foreach ($tenants as $tenant) {
            app()->instance('tenant', $tenant);
            $this->runTenantTasks($tenant, $now);
        }

        return response()->json([
            'status' => 'ok',
            'time' => $now->toDateTimeString(),
        ]);
    }

    private function runTenantTasks(Tenant $tenant, Carbon $now) {
        $tasks = CronTask::all();
        foreach ($tasks as $task) {

            // --- Every-Time Tasks ---
            if ($task->execution_type === CronTaskType::CRON_TASK_TYPE_REALTIME) {
                $this->runTask($task);
            }

            // --- Daily Tasks ---
            if ($task->execution_type === CronTaskType::CRON_TASK_TYPE_DAILY) {
                $tenantLastRun = $task->last_run;

                if ($tenantLastRun !== null) {
                    $tenantLastRun = Carbon::parse($tenantLastRun[$tenant->slug]) ?? null;
                } else {
                    $tenantLastRun = null;
                }

                $scheduledTime = \DateTime::createFromFormat('Y-m-d H:i:s', date('Y-m-d ') . $task->schedule_time);
                $now = Carbon::now();

                $alreadyRunToday = $tenantLastRun == null ? false : $tenantLastRun->isToday() ?? false;

                if (!$alreadyRunToday && $now  >= $scheduledTime) {
                    $this->runTask($task);
                }
            }
        }
    }

    private function runTask(CronTask $task)
    {
        $logger = $this->taskLogger($task->name, app('tenant'));
        app()->instance('taskLogger', $logger);

        $taskClass = "\\App\\Tasks\\" . $task->name;
        if (class_exists($taskClass)) {
            $instance = new $taskClass();
            $instance->handle();
            $lastRun = $task->last_run;
            if ($lastRun === null) {
                $lastRun = [];
            }

            $lastRun[app('tenant')->slug] = now();
            // Update last_run
            $task->last_run = $lastRun;
            $task->save();
        }
    }

    private function taskLogger(string $taskName, $tenant = null) : LoggerInterface
    {
        $tenantSlug = $tenant->slug;
        $logDir = storage_path("logs/{$tenantSlug}");

        if (!file_exists($logDir)) {
            mkdir($logDir, 0755, true);
        }

        $logPath = "{$logDir}/{$taskName}.log";

        return \Illuminate\Support\Facades\Log::build([
            'driver' => 'single',
            'path' => $logPath,
            'level' => 'debug',
        ]);
    }
}
