<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\UserMatch;
use App\Models\UserPreference; // Assuming you have a UserPreference model
use Illuminate\Support\Facades\DB;

class MatchMakingProcess extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'matchmaking:process {--userId=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Process matchmaking for a given user ID';

    protected $relegionsRange = [
        [
            'from' => 0,
            'to' => 33,
            'label' => 'Not Practicing'
        ],
        [
            'from' => 34,
            'to' => 66,
            'label' => 'Moderate Practicing'
        ],
        [
            'from' => 67,
            'to' => 100,
            'label' => 'Very Practicing'
        ],
    ];

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $userId = $this->option('userId');

        // Fetch the user// Fetch user preferences
        $preferences = UserPreference::where('user_id', $userId)->first();

        if (!$preferences) {
            $this->error("Preferences not found for user ID {$userId}.");
            return;
        }

        $gender = $preferences->user->gender;


        // Fetch potential matches based on preferences
        $potentialMatches = UserPreference::where('user_id', '!=', $userId)
            ->whereHas('user', function ($query) use ($gender) {
                $query->where('gender', '!=', $gender);
            })
            ->get()
            ->filter(function ($match) use ($preferences, $userId) {
            $matchScore = 0;

            $userSects = $preferences->user->sects->pluck('sect_id')->toArray();
            $matchSects = $match->user->sects->pluck('sect_id')->toArray();

            if (empty($userSects) || !empty(array_intersect($userSects, $matchSects))) {
                $matchScore++;
            }

            $userEducations = $preferences->user->educations->pluck('education_id')->toArray();
            $matchEductions = $match->user->educations->pluck('education_id')->toArray();

            if (empty($userEducations) || !empty(array_intersect($userEducations, $matchEductions))) {
                $matchScore++;
            }

            $userProfesssions = $preferences->user->professions->pluck('profession_id')->toArray();
            $matchProfessions = $match->user->professions->pluck('profession_id')->toArray();

            if (empty($userProfesssions) || !empty(array_intersect($userProfesssions, $matchProfessions))) {
                $matchScore++;
            }

            if (
                $preferences->height_all == 1 || 
                (
                    $match->from_height_cm <= $preferences->to_height_cm && 
                    $match->to_height_cm >= $preferences->from_height_cm
                )
            ) {
                $matchScore++;
            }
            if (
                $preferences->weight_all == 1 || 
                (
                    $match->from_weight_kg <= $preferences->to_weight_kg && 
                    $match->to_weight_kg >= $preferences->from_weight_kg
                )
            ) {
                $matchScore++;
            }

            $userMaritalStatuses = $preferences->user->maritalStatuses->pluck('marital_status_id')->toArray();
            $matchMaritalStatuses = $match->user->maritalStatuses->pluck('marital_status_id')->toArray();

            if (empty($userMaritalStatuses) || !empty(array_intersect($userMaritalStatuses, $matchMaritalStatuses))) {
                $matchScore++;
            }

            
            if (empty($preferences->religion_practice) || $this->checkReligous($preferences->religion_practice, $match->religion_practice)) {
                $matchScore++;
            }

            $userDressCodes = $preferences->user->dressCodes->pluck('dress_code_id')->toArray();
            $matchDressCodes = $match->user->dressCodes->pluck('dress_code_id')->toArray();

            if (empty($userDressCodes) || !empty(array_intersect($userDressCodes, $matchDressCodes))) {
                $matchScore++;
            }

            if (empty($preferences->smoking) || $match->smoking == $preferences->smoking) {
                $matchScore++;
            }

            // Calculate match percentage
            $matchPercentage = ($matchScore / 9) * 100;
            $match->matchPercentage = $matchPercentage;

            // Check inverse match
            $inversePreferences = $match;
            $inverseMatchScore = 0;

            if ($inversePreferences) {
                $inverseSects = $inversePreferences->user->sects->pluck('sect_id')->toArray();
                if (empty($inverseSects) || !empty(array_intersect($userSects, $inverseSects))) {
                    $inverseMatchScore++;
                }
                $inverseEducation = $inversePreferences->user->educations->pluck('education_id')->toArray();
                if (empty($inversePreferences->education_id) || !empty(array_intersect($userEducations, $inverseEducation))) {
                    $inverseMatchScore++;
                }
                $inverseProfessions = $inversePreferences->user->professions->pluck('profession_id')->toArray();
                if (empty($inversePreferences->profession_id) || !empty(array_intersect($userProfesssions, $inverseProfessions))) {
                    $inverseMatchScore++;
                }
                if (
                    $inversePreferences->height_all == 1 || 
                    (
                        $preferences->user->from_height_cm <= $inversePreferences->to_height_cm && 
                        $preferences->user->to_height_cm >= $inversePreferences->from_height_cm
                    )
                ) {
                    $inverseMatchScore++;
                }
                if (
                    $inversePreferences->weight_all == 1 || 
                    (
                        $preferences->user->from_weight_kg <= $inversePreferences->to_weight_kg && 
                        $preferences->user->to_weight_kg >= $inversePreferences->from_weight_kg
                    )
                ) {
                    $inverseMatchScore++;
                }
                $inverseMaritalStatuses = $inversePreferences->user->maritalStatuses->pluck('marital_status_id')->toArray();

                if (empty($inverseMaritalStatuses) || !empty(array_intersect($userMaritalStatuses, $inverseMaritalStatuses))) {
                    $inverseMatchScore++;
                }
                if (empty($inversePreferences->religion_practice) || $preferences->user->religion_practice >= $inversePreferences->religion_practice) {
                    $inverseMatchScore++;
                }
                $inverseDressCodes = $inversePreferences->user->dressCodes->pluck('dress_code_id')->toArray();
                if (empty($inverseDressCodes) || !empty(array_intersect($userDressCodes, $inverseDressCodes))) {
                    $inverseMatchScore++;
                }
                if (empty($inversePreferences->smoking) || $preferences->user->smoking == $inversePreferences->smoking) {
                    $inverseMatchScore++;
                }

                $inverseMatchPercentage = ($inverseMatchScore / 9) * 100;
                $match->inverseMatchPercentage = $inverseMatchPercentage;
                $match->isInverseMatch = $inverseMatchPercentage >= 40 ? true : false;
            } else {
                $match->inverseMatchPercentage = 0;
                $match->isInverseMatch = false;
            }

            // Return true if either match percentage or inverse match percentage is 40% or higher
            return $matchPercentage >= 40 || $match->isInverseMatch;
            });


        foreach ($potentialMatches as $pMatch) {
            if($pMatch->matchPercentage >=40){
                UserMatch::updateOrCreate(
                    [
                        'user_id' => $userId,
                        'matched_user_id' => $pMatch->user_id,
                    ],
                    [
                        'match_percentage' => (int)$pMatch->matchPercentage,
                    ]
                );
            }
            if($pMatch->isInverseMatch){
                UserMatch::updateOrCreate(
                    [
                        'user_id' => $pMatch->user_id,
                        'matched_user_id' => $userId,
                    ],
                    [
                        'match_percentage' => (int)$pMatch->inverseMatchPercentage,
                    ]
                );
            }

        }

        $this->info("Matchmaking process completed for user ID {$userId}.");

    }

    private function checkReligous($first, $second)
    {
        if (!is_null($first) && !is_null($second)) {
            $first = (int)$first;
            $second = (int)$second;

            $firstLabel = null;
            $secondLabel = null;

            foreach ($this->relegionsRange as $range) {
                if ($first >= $range['from'] && $first <= $range['to']) {
                    $firstLabel = $range['label'];
                }
                if ($second >= $range['from'] && $second <= $range['to']) {
                    $secondLabel = $range['label'];
                }
            }

            return $firstLabel === $secondLabel;
        }

        return false;
    }
}
