<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Application extends Model
{
    protected $fillable = [
        'applicant_id', 'job_listing_id', 'cv_path', 'status',
        'current_stage', 'applied_at', 'final_decision_at', 'admin_notes',
    ];

    protected function casts(): array
    {
        return [
            'applied_at' => 'datetime',
            'final_decision_at' => 'datetime',
            'current_stage' => 'integer',
        ];
    }

    public function applicant(): BelongsTo
    {
        return $this->belongsTo(Applicant::class);
    }

    public function jobListing(): BelongsTo
    {
        return $this->belongsTo(JobListing::class);
    }

    public function stageResponses(): HasMany
    {
        return $this->hasMany(StageResponse::class);
    }

    public function notificationLogs(): HasMany
    {
        return $this->hasMany(NotificationLog::class);
    }

    /**
     * Get response for a specific stage
     */
    public function getResponseForStage(int $stageId): ?StageResponse
    {
        return $this->stageResponses()->where('job_stage_id', $stageId)->first();
    }

    /**
     * Check if form for a specific stage has been filled
     */
    public function hasFilledStage(int $stageId): bool
    {
        // Use loaded relation to avoid N+1 queries
        if ($this->relationLoaded('stageResponses')) {
            return $this->stageResponses->contains('job_stage_id', $stageId);
        }
        return $this->stageResponses()->where('job_stage_id', $stageId)->exists();
    }

    /**
     * Check if documents have been uploaded
     */
    public function hasDocuments(): bool
    {
        return count($this->document_paths) > 0;
    }

    /**
     * Alias for backward compatibility
     */
    public function hasCv(): bool
    {
        return $this->hasDocuments();
    }

    /**
     * Get document paths as array
     */
    public function getDocumentPathsAttribute(): array
    {
        if (empty($this->attributes['cv_path'])) {
            return [];
        }

        $value = $this->attributes['cv_path'];
        $decoded = json_decode($value, true);

        // If JSON array, return as-is; if plain string (legacy), wrap in array
        if (is_array($decoded)) {
            return $decoded;
        }

        return [$value];
    }

    /**
     * Get the effective CV path (first document) — backward compat
     */
    public function getEffectiveCvPathAttribute(): ?string
    {
        $docs = $this->document_paths;
        return $docs[0] ?? null;
    }

    /**
     * Get the next stage the applicant needs to fill
     * Returns null if all stages are filled or waiting for admin approval
     */
    public function getNextFormStage(): ?JobStage
    {
        $job = $this->jobListing;
        if (!$job) return null;

        // Use loaded 'stages' relation filtered in-memory to avoid N+1
        $stages = $this->relationLoaded('jobListing') && $job->relationLoaded('stages')
            ? $job->stages->where('is_active', true)->sortBy('stage_number')
            : $job->activeStages;

        foreach ($stages as $stage) {
            // Check if status indicates this stage is passed (awaiting form fill)
            $passedStatus = 'stage' . $stage->stage_number . '_passed';
            if ($this->status === $passedStatus && !$this->hasFilledStage($stage->id)) {
                return $stage;
            }
        }
        return null;
    }

    /**
     * Dynamic status label based on job stages
     */
    public function getStatusLabelAttribute(): string
    {
        if ($this->status === 'applied') return 'Lamaran Dikirim';
        if ($this->status === 'accepted') return 'Diterima';
        if ($this->status === 'rejected') return 'Ditolak';

        // Dynamic stage statuses — use loaded relation to avoid N+1
        if (preg_match('/^stage(\d+)_passed$/', $this->status, $m)) {
            $stageNum = (int) $m[1];
            $stages = $this->relationLoaded('jobListing') && $this->jobListing?->relationLoaded('stages')
                ? $this->jobListing->stages
                : $this->jobListing?->stages;
            $stage = $stages?->firstWhere('stage_number', $stageNum);
            return 'Lolos: ' . ($stage->name ?? "Tahap {$stageNum}");
        }

        if (preg_match('/^stage(\d+)_form_filled$/', $this->status, $m)) {
            $stageNum = (int) $m[1];
            $stages = $this->relationLoaded('jobListing') && $this->jobListing?->relationLoaded('stages')
                ? $this->jobListing->stages
                : $this->jobListing?->stages;
            $stage = $stages?->firstWhere('stage_number', $stageNum);
            return 'Form Terisi: ' . ($stage->name ?? "Tahap {$stageNum}");
        }

        return ucfirst(str_replace('_', ' ', $this->status));
    }

    /**
     * Dynamic status color
     */
    public function getStatusColorAttribute(): string
    {
        if ($this->status === 'applied') return 'blue';
        if ($this->status === 'accepted') return 'green';
        if ($this->status === 'rejected') return 'red';

        if (str_contains($this->status, '_passed')) return 'yellow';
        if (str_contains($this->status, '_form_filled')) return 'indigo';

        return 'gray';
    }

    /**
     * Get full Tailwind CSS classes for status badge (avoids dynamic class interpolation)
     */
    public function getStatusBadgeClassAttribute(): string
    {
        $map = [
            'blue'   => 'bg-blue-100 text-blue-700',
            'green'  => 'bg-green-100 text-green-700',
            'red'    => 'bg-red-100 text-red-700',
            'yellow' => 'bg-yellow-100 text-yellow-700',
            'indigo' => 'bg-indigo-100 text-indigo-700',
            'gray'   => 'bg-gray-100 text-gray-700',
        ];

        return $map[$this->status_color] ?? 'bg-gray-100 text-gray-700';
    }

    /**
     * Get progress info: how far along the applicant is
     */
    public function getProgressAttribute(): array
    {
        $stages = $this->relationLoaded('jobListing') && $this->jobListing?->relationLoaded('stages')
            ? $this->jobListing->stages->where('is_active', true)
            : ($this->jobListing?->stages?->where('is_active', true) ?? collect());
        $totalStages = $stages->count();
        // Total steps = apply(1) + active stages + final decision(1)
        $totalSteps = $totalStages + 2;

        if ($this->status === 'applied') {
            $current = 1;
        } elseif ($this->status === 'accepted' || $this->status === 'rejected') {
            $current = $totalSteps;
        } elseif (preg_match('/^stage(\d+)/', $this->status, $m)) {
            $current = 1 + (int) $m[1];
            if (str_contains($this->status, '_form_filled')) {
                // Form filled but not yet passed, same step
            }
        } else {
            $current = 1;
        }

        return [
            'current' => $current,
            'total' => $totalSteps,
            'percentage' => $totalSteps > 0 ? round(($current / $totalSteps) * 100) : 0,
        ];
    }
}
