<?php

namespace App\Repositories\Package;

use App\Models\JobPackage;
use App\Repositories\BaseRepository;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;

/**
 * Repository untuk Package
 */
class PackageRepository extends BaseRepository
{
    public function __construct(JobPackage $model)
    {
        parent::__construct($model);
    }

    /**
     * Get all packages with filters
     */
    public function getAll(array $filters = []): LengthAwarePaginator
    {
        $query = $this->model->with([
            'ppk',
            'selectedContractor',
            'documents'
        ]);

        // Apply filters
        $this->_applyFilters($query, $filters);

        // Sorting
        $sortBy = $filters['sort_by'] ?? 'created_at';
        $sortDir = $filters['sort_dir'] ?? 'desc';
        $query->orderBy($sortBy, $sortDir);

        // Pagination
        $perPage = $filters['per_page'] ?? 15;
        return $query->paginate($perPage);
    }

    /**
     * Get packages by PPK
     */
    public function getByPpk(int $ppkId, array $filters = []): LengthAwarePaginator
    {
        $query = $this->model->where('ppk_id', $ppkId)
            ->with(['selectedContractor']);

        if (isset($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        $sortBy = $filters['sort_by'] ?? 'created_at';
        $sortDir = $filters['sort_dir'] ?? 'desc';
        $query->orderBy($sortBy, $sortDir);

        $perPage = $filters['per_page'] ?? 15;
        return $query->paginate($perPage);
    }

    /**
     * Get matching queue (max 50 packages)
     */
    public function getMatchingQueue(): Collection
    {
        return $this->model->where('status', JobPackage::STATUS_ACTIVE)
            ->orderBy('created_at', 'asc')
            ->limit(50)
            ->get();
    }

    /**
     * Get open packages
     */
    public function getOpenPackages(array $filters = []): Collection
    {
        $query = $this->model->whereIn('status', [
            JobPackage::STATUS_ACTIVE,
            JobPackage::STATUS_MATCHING
        ])->with(['ppk']);

        $this->_applyFilters($query, $filters);

        $sortBy = $filters['sort_by'] ?? 'created_at';
        $sortDir = $filters['sort_dir'] ?? 'desc';
        $query->orderBy($sortBy, $sortDir);

        $limit = $filters['limit'] ?? 50;
        return $query->limit($limit)->get();
    }

    /**
     * Get package statistics
     */
    public function getStatistics(?int $ppkId = null): array
    {
        $query = $this->model->query();

        if ($ppkId) {
            $query->where('ppk_id', $ppkId);
        }

        return [
            'total' => (clone $query)->count(),
            'draft' => (clone $query)->where('status', JobPackage::STATUS_DRAFT)->count(),
            'active' => (clone $query)->where('status', JobPackage::STATUS_ACTIVE)->count(),
            'matching' => (clone $query)->where('status', JobPackage::STATUS_MATCHING)->count(),
            'selected' => (clone $query)->where('status', JobPackage::STATUS_SELECTED)->count(),
            'contracting' => (clone $query)->where('status', JobPackage::STATUS_CONTRACTING)->count(),
            'execution' => (clone $query)->where('status', JobPackage::STATUS_EXECUTION)->count(),
            'completed' => (clone $query)->where('status', JobPackage::STATUS_COMPLETED)->count(),
            'cancelled' => (clone $query)->where('status', JobPackage::STATUS_CANCELLED)->count(),
            'total_budget' => (clone $query)->sum('budget'),
        ];
    }

    /**
     * Update package status
     */
    public function updateStatus(int $id, string $status): JobPackage
    {
        $package = $this->find($id);
        $package->update(['status' => $status]);
        return $package->fresh();
    }

    /**
     * Apply filters to query
     */
    private function _applyFilters($query, array $filters): void
    {
        if (isset($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        if (isset($filters['job_type'])) {
            $query->where('job_type', $filters['job_type']);
        }

        if (isset($filters['province'])) {
            $query->where('province', $filters['province']);
        }

        if (isset($filters['regency'])) {
            $query->where('regency', $filters['regency']);
        }

        if (isset($filters['district'])) {
            $query->where('district', $filters['district']);
        }

        if (isset($filters['min_budget'])) {
            $query->where('budget', '>=', $filters['min_budget']);
        }

        if (isset($filters['max_budget'])) {
            $query->where('budget', '<=', $filters['max_budget']);
        }

        if (isset($filters['search'])) {
            $search = '%' . $filters['search'] . '%';
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', $search)
                    ->orWhere('description', 'like', $search)
                    ->orWhere('village', 'like', $search)
                    ->orWhere('regency', 'like', $search);
            });
        }

        if (isset($filters['date_from'])) {
            $query->whereDate('created_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->whereDate('created_at', '<=', $filters['date_to']);
        }
    }
}