<?php

namespace App\Services;

use App\Models\JobPackage;
use App\Models\Contractor;
use App\Models\ContractorExperience;
use App\Models\ContractorSBU;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class MatchingService
{
    /**
     * Find candidates for a package with location-based priority
     */
    public function findCandidates(int $packageId, int $limit = 5): array
    {
        $package = JobPackage::find($packageId);
        if (!$package) {
            return [];
        }

        // Ambil semua kontraktor yang aktif, terverifikasi, dan tidak blacklist
        $contractors = Contractor::where('is_active', true)
            ->where('oap_status', 'verified')
            ->where('is_blacklisted', false)
            ->get();

        if ($contractors->isEmpty()) {
            return [];
        }

        $candidates = [];
        foreach ($contractors as $contractor) {
            $score = $this->calculateScore($package, $contractor);
            
            if ($score > 0) {
                $candidates[] = [
                    'contractor_id' => $contractor->id,
                    'business_name' => $contractor->business_name,
                    'location' => [
                        'province' => $contractor->province,
                        'regency' => $contractor->regency,
                        'district' => $contractor->district,
                        'village' => $contractor->village,
                    ],
                    'score' => $score,
                    'match_reason' => $this->getMatchReason($package, $contractor),
                    'distance_label' => $this->getDistanceLabel($package, $contractor),
                    'rating' => $contractor->rating_avg,
                    'skp_remaining' => $contractor->skp_remaining,
                    'experience_count' => ContractorExperience::where('contractor_id', $contractor->id)->count(),
                ];
            }
        }

        // Urutkan berdasarkan skor (tertinggi ke terendah)
        usort($candidates, function ($a, $b) {
            return $b['score'] - $a['score'];
        });

        return array_slice($candidates, 0, $limit);
    }

    /**
     * Calculate matching score dengan prioritas lokasi
     */
    public function calculateScore(JobPackage $package, Contractor $contractor): int
    {
        $score = 0;

        // ============================================================
        // 1. LOKASI (40%) - PRIORITAS UTAMA!
        // Desa (40%) > Kecamatan (30%) > Kabupaten (20%) > Provinsi (10%)
        // ============================================================
        $locationScore = 0;
        if ($package->village && $contractor->village && $package->village === $contractor->village) {
            $locationScore = 40;  // Desa sama = 40 poin
        } elseif ($package->district && $contractor->district && $package->district === $contractor->district) {
            $locationScore = 30;  // Kecamatan sama = 30 poin
        } elseif ($package->regency && $contractor->regency && $package->regency === $contractor->regency) {
            $locationScore = 20;  // Kabupaten sama = 20 poin
        } elseif ($package->province && $contractor->province && $package->province === $contractor->province) {
            $locationScore = 10;  // Provinsi sama = 10 poin
        }
        $score += $locationScore;

        // ============================================================
        // 2. PENGALAMAN (25%)
        // ============================================================
        $experienceCount = ContractorExperience::where('contractor_id', $contractor->id)->count();
        if ($experienceCount > 0) {
            $experienceScore = min(25, $experienceCount * 3);
            $score += $experienceScore;
        }

        // ============================================================
        // 3. SERTIFIKASI/SBU (15%)
        // ============================================================
        $sbuCount = ContractorSBU::where('contractor_id', $contractor->id)->count();
        if ($sbuCount > 0) {
            $sbuScore = min(15, $sbuCount * 3);
            $score += $sbuScore;
        }

        // ============================================================
        // 4. RATING (10%)
        // ============================================================
        if ($contractor->rating_avg >= 4.5) {
            $score += 10;
        } elseif ($contractor->rating_avg >= 4.0) {
            $score += 7;
        } elseif ($contractor->rating_avg >= 3.5) {
            $score += 4;
        } elseif ($contractor->rating_avg >= 3.0) {
            $score += 2;
        }

        // ============================================================
        // 5. SKP (10%)
        // ============================================================
        if ($contractor->skp_remaining > 0) {
            $score += min(10, $contractor->skp_remaining * 2);
        }

        return min(100, $score);
    }

    /**
     * Get match reasons
     */
    public function getMatchReason(JobPackage $package, Contractor $contractor): array
    {
        $reasons = [];

        // 1. Lokasi (prioritas utama)
        if ($package->village && $contractor->village && $package->village === $contractor->village) {
            $reasons[] = '📍 Satu Desa: ' . $contractor->village;
        } elseif ($package->district && $contractor->district && $package->district === $contractor->district) {
            $reasons[] = '📍 Satu Kecamatan: ' . $contractor->district;
        } elseif ($package->regency && $contractor->regency && $package->regency === $contractor->regency) {
            $reasons[] = '📍 Satu Kabupaten: ' . $contractor->regency;
        } elseif ($package->province && $contractor->province && $package->province === $contractor->province) {
            $reasons[] = '📍 Satu Provinsi: ' . $contractor->province;
        }

        // 2. Pengalaman
        $experienceCount = ContractorExperience::where('contractor_id', $contractor->id)->count();
        if ($experienceCount > 0) {
            $reasons[] = '📋 Pengalaman ' . $experienceCount . ' proyek';
        }

        // 3. Sertifikasi/SBU
        $sbuCount = ContractorSBU::where('contractor_id', $contractor->id)->count();
        if ($sbuCount > 0) {
            $reasons[] = '📜 Memiliki ' . $sbuCount . ' sertifikasi/SBU';
        }

        // 4. Rating
        if ($contractor->rating_avg >= 4.5) {
            $reasons[] = '⭐ Rating sangat baik (' . number_format($contractor->rating_avg, 1) . ')';
        } elseif ($contractor->rating_avg >= 4.0) {
            $reasons[] = '⭐ Rating baik (' . number_format($contractor->rating_avg, 1) . ')';
        } elseif ($contractor->rating_avg >= 3.5) {
            $reasons[] = '⭐ Rating cukup (' . number_format($contractor->rating_avg, 1) . ')';
        }

        // 5. SKP
        if ($contractor->skp_remaining > 0) {
            $reasons[] = '📊 SKP tersisa ' . $contractor->skp_remaining;
        }

        return $reasons;
    }

    /**
     * Get distance label
     */
    public function getDistanceLabel(JobPackage $package, Contractor $contractor): string
    {
        if ($package->village && $contractor->village && $package->village === $contractor->village) {
            return '📍 Satu Desa (' . $contractor->village . ')';
        } elseif ($package->district && $contractor->district && $package->district === $contractor->district) {
            return '📍 Satu Kecamatan (' . $contractor->district . ')';
        } elseif ($package->regency && $contractor->regency && $package->regency === $contractor->regency) {
            return '📍 Satu Kabupaten (' . $contractor->regency . ')';
        } elseif ($package->province && $contractor->province && $package->province === $contractor->province) {
            return '📍 Satu Provinsi (' . $contractor->province . ')';
        } else {
            return '📍 Luar Provinsi';
        }
    }

    /**
     * Get queue of packages waiting for matching
     */
    public function getQueue(int $limit = 10): array
    {
        $packages = JobPackage::where('status', 'submitted')
            ->orderBy('created_at', 'asc')
            ->limit($limit)
            ->get();

        $queue = [];
        foreach ($packages as $package) {
            $candidates = $this->findCandidates($package->id);
            $queue[] = [
                'id' => $package->id,
                'name' => $package->name,
                'budget' => $package->budget,
                'status' => $package->status,
                'created_at' => $package->created_at,
                'candidates_count' => count($candidates),
            ];
        }

        return $queue;
    }

    /**
     * Get top candidates for a package (untuk display)
     */
    public function getTopCandidates(int $packageId, int $limit = 5): array
    {
        return $this->findCandidates($packageId, $limit);
    }

    /**
     * Get all candidates with full details
     */
    public function getAllCandidates(int $packageId): array
    {
        return $this->findCandidates($packageId, 999);
    }
}