<?php

namespace App\Services\Refunds;

use App\Models\Refund;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

class RefundQueryService
{
    public function list(array $filters): array
    {
        $perPage = (int) ($filters['per_page'] ?? 25);
        $page = (int) ($filters['page'] ?? 1);
        $sortBy = (string) ($filters['sort_by'] ?? 'created_at');
        $sortDir = strtolower((string) ($filters['sort_dir'] ?? 'desc')) === 'asc' ? 'asc' : 'desc';

        $allowedSorts = ['created_at', 'updated_at', 'refund_amount', 'status', 'parent_id', 'invoice_id'];
        if (!in_array($sortBy, $allowedSorts, true)) {
            $sortBy = 'created_at';
        }

        $query = Refund::query()
            ->select([
                'refunds.*',
                DB::raw("CONCAT(COALESCE(parents.lastname, ''), ', ', COALESCE(parents.firstname, '')) AS parent_name"),
                DB::raw("CONCAT(COALESCE(approvers.lastname, ''), ', ', COALESCE(approvers.firstname, '')) AS approved_by_name"),
            ])
            ->leftJoin('users as parents', 'parents.id', '=', 'refunds.parent_id')
            ->leftJoin('users as approvers', 'approvers.id', '=', 'refunds.approved_by');

        if (!empty($filters['status'])) {
            $query->where('refunds.status', $filters['status']);
        }
        if (!empty($filters['request'])) {
            $query->where('refunds.request', $filters['request']);
        }
        if (!empty($filters['parent_id'])) {
            $query->where('refunds.parent_id', (int) $filters['parent_id']);
        }
        if (!empty($filters['invoice_id'])) {
            $query->where('refunds.invoice_id', (int) $filters['invoice_id']);
        }
        if (!empty($filters['school_year'])) {
            $query->where('refunds.school_year', (string) $filters['school_year']);
        }
        if (!empty($filters['semester'])) {
            $query->where('refunds.semester', (string) $filters['semester']);
        }
        if (!empty($filters['q'])) {
            $term = trim((string) $filters['q']);
            $query->where(function ($where) use ($term) {
                $where->where('refunds.reason', 'like', "%{$term}%")
                    ->orWhere('refunds.note', 'like', "%{$term}%")
                    ->orWhere('parents.firstname', 'like', "%{$term}%")
                    ->orWhere('parents.lastname', 'like', "%{$term}%");
            });
        }

        $paginator = $query->orderBy('refunds.' . $sortBy, $sortDir)
            ->paginate($perPage, ['*'], 'page', $page);

        return [
            'refunds' => $paginator,
            'pagination' => $this->paginationPayload($paginator),
        ];
    }

    public function find(int $refundId): ?Refund
    {
        return Refund::query()->find($refundId);
    }

    private function paginationPayload(LengthAwarePaginator $paginator): array
    {
        return [
            'current_page' => $paginator->currentPage(),
            'per_page' => $paginator->perPage(),
            'total' => $paginator->total(),
            'total_pages' => $paginator->lastPage(),
        ];
    }
}
