<?php

declare(strict_types=1);

namespace App\Models;

use App\Support\Concerns\DerivesWorkspaceIdFromTenant;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class SupportRequest extends Model
{
    use DerivesWorkspaceIdFromTenant;

    /** @use HasFactory<\Database\Factories\SupportRequestFactory> */
    use HasFactory;

    public const string PRIMARY_CONTEXT_TENANT = 'tenant';

    public const string PRIMARY_CONTEXT_OPERATION_RUN = 'operation_run';

    public const string ATTACHMENT_MODE_DIAGNOSTIC_SNAPSHOT_ATTACHED = 'diagnostic_snapshot_attached';

    public const string ATTACHMENT_MODE_CANONICAL_CONTEXT_ONLY = 'canonical_context_only';

    public const string SEVERITY_LOW = 'low';

    public const string SEVERITY_NORMAL = 'normal';

    public const string SEVERITY_HIGH = 'high';

    public const string SEVERITY_BLOCKING = 'blocking';

    public const string EXTERNAL_HANDOFF_MODE_INTERNAL_ONLY = 'internal_only';

    public const string EXTERNAL_HANDOFF_MODE_CREATE_EXTERNAL_TICKET = 'create_external_ticket';

    public const string EXTERNAL_HANDOFF_MODE_LINK_EXISTING_TICKET = 'link_existing_ticket';

    public const string HANDOFF_OUTCOME_INTERNAL_ONLY = 'internal_only';

    public const string HANDOFF_OUTCOME_EXTERNAL_TICKET_CREATED = 'external_ticket_created';

    public const string HANDOFF_OUTCOME_EXTERNAL_TICKET_LINKED = 'external_ticket_linked';

    public const string HANDOFF_OUTCOME_EXTERNAL_HANDOFF_FAILED = 'external_handoff_failed';

    protected $guarded = [];

    /**
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'context_envelope' => 'array',
        ];
    }

    /**
     * @return array<string, string>
     */
    public static function severityOptions(): array
    {
        return [
            self::SEVERITY_LOW => 'Low',
            self::SEVERITY_NORMAL => 'Normal',
            self::SEVERITY_HIGH => 'High',
            self::SEVERITY_BLOCKING => 'Blocking',
        ];
    }

    /**
     * @return list<string>
     */
    public static function severityValues(): array
    {
        return array_keys(self::severityOptions());
    }

    /**
     * @return array<string, string>
     */
    public static function externalHandoffModeOptions(): array
    {
        return [
            self::EXTERNAL_HANDOFF_MODE_INTERNAL_ONLY => 'TenantPilot only',
            self::EXTERNAL_HANDOFF_MODE_CREATE_EXTERNAL_TICKET => 'Create external ticket',
            self::EXTERNAL_HANDOFF_MODE_LINK_EXISTING_TICKET => 'Link existing ticket',
        ];
    }

    /**
     * @return list<string>
     */
    public static function externalHandoffModeValues(): array
    {
        return array_keys(self::externalHandoffModeOptions());
    }

    public function hasExternalTicket(): bool
    {
        return is_string($this->external_ticket_reference) && trim($this->external_ticket_reference) !== '';
    }

    public function hasExternalHandoffFailure(): bool
    {
        return is_string($this->external_handoff_failure_summary) && trim($this->external_handoff_failure_summary) !== '';
    }

    public function externalHandoffOutcome(): string
    {
        if ($this->hasExternalHandoffFailure()) {
            return self::HANDOFF_OUTCOME_EXTERNAL_HANDOFF_FAILED;
        }

        if (! $this->hasExternalTicket()) {
            return self::HANDOFF_OUTCOME_INTERNAL_ONLY;
        }

        return match ($this->external_handoff_mode) {
            self::EXTERNAL_HANDOFF_MODE_CREATE_EXTERNAL_TICKET => self::HANDOFF_OUTCOME_EXTERNAL_TICKET_CREATED,
            self::EXTERNAL_HANDOFF_MODE_LINK_EXISTING_TICKET => self::HANDOFF_OUTCOME_EXTERNAL_TICKET_LINKED,
            default => self::HANDOFF_OUTCOME_INTERNAL_ONLY,
        };
    }

    /**
     * @return list<string>
     */
    public static function primaryContextTypes(): array
    {
        return [
            self::PRIMARY_CONTEXT_TENANT,
            self::PRIMARY_CONTEXT_OPERATION_RUN,
        ];
    }

    /**
     * @return list<string>
     */
    public static function attachmentModes(): array
    {
        return [
            self::ATTACHMENT_MODE_DIAGNOSTIC_SNAPSHOT_ATTACHED,
            self::ATTACHMENT_MODE_CANONICAL_CONTEXT_ONLY,
        ];
    }

    /**
     * @return BelongsTo<Workspace, $this>
     */
    public function workspace(): BelongsTo
    {
        return $this->belongsTo(Workspace::class);
    }

    /**
     * @return BelongsTo<ManagedEnvironment, $this>
     */
    public function tenant(): BelongsTo
    {
        return $this->belongsTo(ManagedEnvironment::class, 'managed_environment_id');
    }

    /**
     * @return BelongsTo<OperationRun, $this>
     */
    public function operationRun(): BelongsTo
    {
        return $this->belongsTo(OperationRun::class);
    }

    /**
     * @return BelongsTo<User, $this>
     */
    public function initiator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'initiated_by_user_id');
    }
}
