<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use App\Models\BaseModel;
use Illuminate\Support\Facades\DB;

class AdditionalCharge extends BaseModel
{
    protected $table = 'additional_charges';

    // CI useTimestamps = false
    public $timestamps = true;

    protected $fillable = [
        'parent_id',
        'invoice_id',
        'school_year',
        'semester',
        'charge_type',
        'title',
        'description',
        'amount',
        'due_date',
        'status',
        'created_by',
        'created_at',
        'updated_at',
    ];

    protected $casts = [
        'parent_id'  => 'integer',
        'invoice_id' => 'integer',
        'amount'     => 'decimal:2', // adjust if you store more precision
        'due_date'   => 'date',      // if due_date is DATE/DATETIME
        'created_by' => 'integer',
    ];

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

    public function parentUser()
    {
        return $this->belongsTo(User::class, 'parent_id');
    }

    public function invoice()
    {
        return $this->belongsTo(Invoice::class, 'invoice_id');
    }

    /* =========================
     * Query scopes (optional)
     * ========================= */

    public function scopeForTerm(Builder $q, string $schoolYear, ?string $semester = null): Builder
    {
        $q->where('school_year', $schoolYear);

        if ($semester !== null && $semester !== '') {
            $q->where('semester', $semester);
        }

        return $q;
    }

    public function scopeStatus(Builder $q, ?string $status): Builder
    {
        return ($status !== null && $status !== '')
            ? $q->where('status', $status)
            : $q;
    }

    public function scopeByParentTerm(
        Builder $q,
        int $parentId,
        string $year,
        string $sem,
        ?string $status = null
    ): Builder {
        $q->where('parent_id', $parentId)
            ->where('school_year', $year)
            ->where('semester', $sem);

        if ($status !== null && $status !== '') {
            $q->where('status', $status);
        }

        return $q->orderByDesc('id');
    }

    /* =========================
     * CI methods equivalents
     * ========================= */

    public static function byParentTerm(int $parentId, string $year, string $sem, ?string $status = null)
    {
        return static::query()
            ->where('parent_id', $parentId)
            ->where('school_year', $year)
            ->where('semester', $sem)
            ->when($status !== null, fn ($q) => $q->where('status', $status))
            ->orderByDesc('id')
            ->get();
    }

    /**
     * Set status=applied and invoice_id for given IDs.
     * Returns true if nothing to update (empty ids) or update succeeded.
     */
    public static function markApplied($ids, int $invoiceId): bool
    {
        $ids = is_array($ids) ? $ids : [$ids];
        $ids = array_values(array_filter(array_map('intval', $ids)));

        if (count($ids) === 0) {
            return true;
        }

        $affected = static::query()
            ->whereIn('id', $ids)
            ->update([
                'status'     => 'applied',
                'invoice_id' => $invoiceId,
            ]);

        return $affected >= 0; // update returns affected rows; 0 is still "ok"
    }

    /**
     * listAllForTerm (Laravel version)
     * - joins users + invoices
     * - supports status + q search
     * - paginates
     * - fallback: if no rows for semester and allowed, retry year-only
     */
    public static function listAllForTerm(
        string $schoolYear,
        string $semester,
        ?string $status = null,
        ?string $q = null,
        int $perPage = 50,
        bool $fallbackToYear = true
    ) {
        $build = function (?string $semFilter) use ($schoolYear, $status, $q) {
            $query = static::query()
                ->select([
                    'additional_charges.*',
                    DB::raw("CONCAT(COALESCE(users.lastname, ''), ', ', COALESCE(users.firstname, '')) AS parent_name"),
                    'invoices.invoice_number',
                ])
                ->leftJoin('users', 'users.id', '=', 'additional_charges.parent_id')
                ->leftJoin('invoices', 'invoices.id', '=', 'additional_charges.invoice_id')
                ->where('additional_charges.school_year', $schoolYear);

            if ($semFilter !== null && $semFilter !== '') {
                $query->where('additional_charges.semester', $semFilter);
            }

            if (!empty($status)) {
                $query->where('additional_charges.status', $status);
            }

            if (!empty($q)) {
                $term = trim($q);
                $query->where(function ($w) use ($term) {
                    $w->where('additional_charges.title', 'like', "%{$term}%")
                      ->orWhere('additional_charges.description', 'like', "%{$term}%")
                      ->orWhere('users.firstname', 'like', "%{$term}%")
                      ->orWhere('users.lastname', 'like', "%{$term}%")
                      ->orWhere('invoices.invoice_number', 'like', "%{$term}%");
                });
            }

            return $query->orderByDesc('additional_charges.id');
        };

        // First attempt: year + semester
        $result = $build($semester)->paginate($perPage);

        // Fallback: if no rows and allowed, retry year-only
        if ($fallbackToYear && $result->total() === 0 && $semester !== '') {
            $result = $build(null)->paginate($perPage);
        }

        return $result;
    }
}
