<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use App\Models\BaseModel;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Staff extends BaseModel
{
    protected $table = 'staff';

    /**
     * CI: timestamps managed manually (created_at/updated_at set by caller/controller)
     */
    public $timestamps = true;

    protected $fillable = [
        'firstname',
        'lastname',
        'email',
        'phone',
        'role_name',
        'school_year',
        'active_role',
        'created_at',
        'updated_at',
        'user_id',
    ];

    protected $casts = [
        'user_id'     => 'integer',
        'created_at'  => 'datetime',
        'updated_at'  => 'datetime',
    ];

    /* ============================================================
     * Relationships (optional)
     * ============================================================
     */

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /* ============================================================
     * Scopes (nice for queries)
     * ============================================================
     */

    public function scopeActive(Builder $q): Builder
    {
        return $q->where('active_role', '!=', 'inactive');
    }

    public function scopeInactive(Builder $q): Builder
    {
        return $q->where('active_role', '=', 'inactive');
    }

    public function scopeForSchoolYear(Builder $q, string $schoolYear): Builder
    {
        return $q->where('school_year', $schoolYear);
    }

    /* ============================================================
     * CI-compatible methods
     * ============================================================
     */

    public static function getActiveStaff(): array
    {
        return static::query()
            ->active()
            ->orderByDesc('created_at')
            ->get()
            ->all();
    }

    public static function getInactiveStaff(): array
    {
        return static::query()
            ->inactive()
            ->orderByDesc('updated_at')
            ->get()
            ->all();
    }

    /**
     * Insert or update a staff row keyed by (user_id, school_year).
     * - If school_year missing: reuse latest existing school_year for that user if available.
     * - created_at is preserved on update (unless explicitly provided).
     * - updated_at can be provided by caller; otherwise we set it.
     *
     * Returns the saved model or null if invalid.
     */
    public static function upsertStaff(array $data): ?self
    {
        if (empty($data['user_id'])) {
            return null;
        }

        $userId = (int) $data['user_id'];

        // Resolve school_year fallback like your CI logic
        $schoolYear = $data['school_year'] ?? null;
        if ($schoolYear === null) {
            $existingAny = static::query()
                ->where('user_id', $userId)
                ->orderByDesc('id')
                ->first();

            if ($existingAny && $existingAny->school_year) {
                $schoolYear = (string) $existingAny->school_year;
                $data['school_year'] = $schoolYear;
            }
        }

        // Find existing by key
        $existing = null;
        if ($schoolYear !== null) {
            $existing = static::query()
                ->where('user_id', $userId)
                ->where('school_year', (string) $schoolYear)
                ->first();
        } else {
            // If no school_year, treat (user_id) as key
            $existing = static::query()
                ->where('user_id', $userId)
                ->first();
        }

        $now = now(); // use UTC if app.timezone=UTC (recommended)

        // Only allow fillable keys
        $payload = array_intersect_key($data, array_flip((new static)->getFillable()));

        if ($existing) {
            // Preserve original created_at unless explicitly provided
            if (!array_key_exists('created_at', $payload) && $existing->created_at) {
                $payload['created_at'] = $existing->created_at;
            }
            // Ensure updated_at exists
            if (!array_key_exists('updated_at', $payload)) {
                $payload['updated_at'] = $now;
            }

            $existing->fill($payload);
            $existing->save();

            return $existing;
        }

        // Insert new row — set created_at/updated_at if not provided
        if (!array_key_exists('created_at', $payload)) {
            $payload['created_at'] = $now;
        }
        if (!array_key_exists('updated_at', $payload)) {
            $payload['updated_at'] = $now;
        }

        return static::query()->create($payload);
    }

    /**
     * CI-compatible boolean wrapper if you want the same signature.
     */
    public static function upsertBool(array $data): bool
    {
        return (bool) static::upsertStaff($data);
    }

    /* ============================================================
     * Optional validation helper (FormRequest/controller)
     * ============================================================
     */

    public static function rules(bool $updating = false): array
    {
        $req = $updating ? 'sometimes' : 'required';

        return [
            'user_id'      => [$req, 'integer', 'min:1', 'exists:users,id'],
            'firstname'    => ['nullable', 'string', 'max:120'],
            'lastname'     => ['nullable', 'string', 'max:120'],
            'email'        => ['nullable', 'email', 'max:255'],
            'phone'        => ['nullable', 'string', 'max:40'],
            'role_name'    => ['nullable', 'string', 'max:80'],
            'active_role'  => ['nullable', 'string', 'max:80'], // includes 'inactive'
            'status'       => ['nullable', 'string', 'max:40'],
            'school_year'  => ['nullable', 'string', 'max:20'],
            'created_at'   => ['nullable', 'date'],
            'updated_at'   => ['nullable', 'date'],
        ];
    }
}