<?php

namespace App\Workflows\Traits;

use App\Workflows\Models\StepInstance;
use App\Workflows\Models\WorkflowInstance;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Support\Facades\Auth;

trait HasWorkflow
{
    /**
     * Get the workflow instance for this model.
     */
    public function workflowInstance(): MorphOne
    {
        return $this->morphOne(WorkflowInstance::class, 'subject');
    }

    /**
     * Get the current workflow step.
     */
    public function currentStep(): ?StepInstance
    {
        // Don't return steps if workflow is not in running state
        if (! $this->workflowInstance || ! $this->workflowInstance->isRunning()) {
            return null;
        }

        return $this->workflowInstance->currentStep();
    }

    /**
     * Check if this model has an active workflow.
     */
    public function hasWorkflow(): bool
    {
        return $this->workflowInstance !== null;
    }

    /**
     * Check if this model has an active running workflow.
     */
    public function hasActiveWorkflow(): bool
    {
        return $this->workflowInstance && $this->workflowInstance->isRunning();
    }

    /**
     * Check if the workflow has a current pending step.
     */
    public function hasPendingStep(): bool
    {
        // First check if we have an active workflow
        if (! $this->hasActiveWorkflow()) {
            return false;
        }

        $currentStep = $this->currentStep();

        return $currentStep && $currentStep->isPending();
    }

    /**
     * Get the workflow status label.
     */
    public function getWorkflowStatusLabel(): string
    {
        if (! $this->hasWorkflow()) {
            return __('workflow.status.no_workflow');
        }

        $workflowInstance = $this->workflowInstance;

        // Check workflow instance state first
        if ($workflowInstance->isRejected()) {
            return __('workflow.states.rejected');
        }

        if ($workflowInstance->isCanceled()) {
            return __('workflow.states.canceled');
        }

        if ($workflowInstance->isCompleted()) {
            return __('workflow.states.completed');
        }

        // If running, check current step
        $currentStep = $this->currentStep();
        if (! $currentStep) {
            // This shouldn't happen in running state, but handle gracefully
            return __('workflow.status.in_progress');
        }

        $stepStatus = __('workflow.step_states.'.$currentStep->status);

        return __('workflow.status.step_with_status', [
            'step' => $currentStep->getLabel(),
            'status' => $stepStatus,
        ]);
    }

    /**
     * Log workflow activity when workflow is started.
     */
    public function logWorkflowStarted(?string $notes = null): void
    {
        $currentStep = $this->currentStep();

        $logName = method_exists($this, 'getActivitylogOptions')
            ? $this->getActivitylogOptions()->logName
            : 'default';

        activity($logName)
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('workflow_started')
            ->withProperties([
                'action' => 'started',
                'current_step' => $currentStep?->getLabel(),
                'current_step_id' => $currentStep?->id,
                'notes' => $notes,
                'workflow_id' => $this->workflowInstance?->id,
            ])
            ->log(__('workflow.activity.workflow_started'));
    }

    /**
     * Log workflow activity when a step is approved/completed.
     */
    public function logWorkflowStepApproved(
        StepInstance $fromStep,
        ?StepInstance $toStep = null,
        array $stepData = [],
        ?string $notes = null
    ): void {
        $logName = method_exists($this, 'getActivitylogOptions')
            ? $this->getActivitylogOptions()->logName
            : 'default';

        activity($logName)
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('workflow_step_approved')
            ->withProperties([
                'action' => 'approved',
                'from_step' => $fromStep->getLabel(),
                'from_step_id' => $fromStep->id,
                'to_step' => $toStep?->getLabel(),
                'to_step_id' => $toStep?->id,
                'step_data' => $stepData,
                'notes' => $notes,
                'workflow_id' => $this->workflowInstance?->id,
            ])
            ->log($toStep
                ? __('workflow.activity.step_approved_with_next', [
                    'from_step' => $fromStep->getLabel(),
                    'to_step' => $toStep->getLabel(),
                ])
                : __('workflow.activity.step_approved_completed', [
                    'from_step' => $fromStep->getLabel(),
                ])
            );
    }

    /**
     * Log workflow activity when a step is rejected.
     */
    public function logWorkflowStepRejected(
        StepInstance $step,
        string $reason,
        ?string $notes = null
    ): void {
        $logName = method_exists($this, 'getActivitylogOptions')
            ? $this->getActivitylogOptions()->logName
            : 'default';

        activity($logName)
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('workflow_step_rejected')
            ->withProperties([
                'action' => 'rejected',
                'step' => $step->getLabel(),
                'step_id' => $step->id,
                'reason' => $reason,
                'notes' => $notes,
                'workflow_id' => $this->workflowInstance?->id,
            ])
            ->log(__('workflow.activity.step_rejected', [
                'step' => $step->getLabel(),
                'reason' => $reason,
            ]));
    }

    /**
     * Log workflow activity when workflow is completed.
     */
    public function logWorkflowCompleted(?string $notes = null): void
    {
        $logName = method_exists($this, 'getActivitylogOptions')
            ? $this->getActivitylogOptions()->logName
            : 'default';

        activity($logName)
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('workflow_completed')
            ->withProperties([
                'action' => 'completed',
                'notes' => $notes,
                'workflow_id' => $this->workflowInstance?->id,
            ])
            ->log(__('workflow.activity.workflow_completed'));
    }

    /**
     * Log custom workflow activity.
     */
    public function logWorkflowActivity(
        string $event,
        string $description,
        array $properties = [],
        ?string $notes = null
    ): void {
        $currentStep = $this->currentStep();

        $logName = method_exists($this, 'getActivitylogOptions')
            ? $this->getActivitylogOptions()->logName
            : 'default';

        activity($logName)
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event($event)
            ->withProperties(array_merge([
                'current_step' => $currentStep?->getLabel(),
                'current_step_id' => $currentStep?->id,
                'notes' => $notes,
                'workflow_id' => $this->workflowInstance?->id,
            ], $properties))
            ->log($description);
    }
}
