<?php

namespace App\Services;

use App\Models\ActivityAssignmentRule;
use App\Models\Company;
use App\Models\User;
use Illuminate\Support\Collection;

class ActivityAssignmentService
{
    /**
     * Check if activity is mandatory for a specific user.
     */
    public function isActivityMandatoryForUser(User $user): bool
    {
        $company = $user->company;

        // Check if activity mandatory is enabled globally
        if (!($company->activity_mandatory_enabled ?? false)) {
            return false;
        }

        // If scope is 'all', everyone must fill activity
        if ($company->activity_mandatory_scope === 'all') {
            return true;
        }

        // If scope is 'rules', check assignment rules
        if ($company->activity_mandatory_scope === 'rules') {
            return $this->userMatchesAnyRule($user);
        }

        return false;
    }

    /**
     * Check if user matches any active assignment rule.
     */
    protected function userMatchesAnyRule(User $user): bool
    {
        $rules = ActivityAssignmentRule::where('company_id', $user->company_id)
            ->where('is_active', true)
            ->get();

        foreach ($rules as $rule) {
            if ($rule->appliesToUser($user)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get all users with mandatory activity for a company.
     */
    public function getUsersWithMandatoryActivity(Company $company): Collection
    {
        if (!($company->activity_mandatory_enabled ?? false)) {
            return collect();
        }

        if ($company->activity_mandatory_scope === 'all') {
            return $company->users()->active()->get();
        }

        // Collect users from all active rules
        $userIds = collect();

        $rules = ActivityAssignmentRule::where('company_id', $company->id)
            ->where('is_active', true)
            ->get();

        foreach ($rules as $rule) {
            $matchingUserIds = $this->getUserIdsMatchingRule($rule, $company);
            $userIds = $userIds->merge($matchingUserIds);
        }

        return User::whereIn('id', $userIds->unique())
            ->where('is_active', true)
            ->get();
    }

    /**
     * Get user IDs that match a specific rule.
     */
    protected function getUserIdsMatchingRule(ActivityAssignmentRule $rule, Company $company): Collection
    {
        $query = User::where('company_id', $company->id)
            ->where('is_active', true);

        return match ($rule->rule_type) {
            'all_users' => $query->pluck('id'),
            'specific_users' => collect($rule->target_values ?? []),
            'departments' => $query->whereIn('department', $rule->target_values ?? [])->pluck('id'),
            'positions' => $query->whereIn('position', $rule->target_values ?? [])->pluck('id'),
            default => collect(),
        };
    }

    /**
     * Get users without mandatory activity for a company.
     */
    public function getUsersWithoutMandatoryActivity(Company $company): Collection
    {
        if (!($company->activity_mandatory_enabled ?? false)) {
            return $company->users()->active()->get();
        }

        if ($company->activity_mandatory_scope === 'all') {
            return collect();
        }

        $mandatoryUserIds = $this->getUsersWithMandatoryActivity($company)->pluck('id');

        return $company->users()
            ->active()
            ->whereNotIn('id', $mandatoryUserIds)
            ->get();
    }

    /**
     * Get all rules for a company.
     */
    public function getRulesForCompany(int $companyId): Collection
    {
        return ActivityAssignmentRule::where('company_id', $companyId)
            ->orderBy('created_at', 'desc')
            ->get();
    }

    /**
     * Create a new assignment rule.
     */
    public function createRule(array $data): ActivityAssignmentRule
    {
        return ActivityAssignmentRule::create($data);
    }

    /**
     * Update an existing rule.
     */
    public function updateRule(ActivityAssignmentRule $rule, array $data): ActivityAssignmentRule
    {
        $rule->update($data);
        return $rule->fresh();
    }

    /**
     * Delete a rule.
     */
    public function deleteRule(ActivityAssignmentRule $rule): bool
    {
        return $rule->delete();
    }

    /**
     * Get statistics about activity assignment for a company.
     */
    public function getAssignmentStatistics(Company $company): array
    {
        $totalUsers = $company->users()->active()->count();
        $mandatoryUsers = $this->getUsersWithMandatoryActivity($company)->count();
        $optionalUsers = $totalUsers - $mandatoryUsers;
        $activeRules = ActivityAssignmentRule::where('company_id', $company->id)
            ->where('is_active', true)
            ->count();

        return [
            'total_users' => $totalUsers,
            'mandatory_users' => $mandatoryUsers,
            'optional_users' => $optionalUsers,
            'active_rules' => $activeRules,
            'mandatory_enabled' => $company->activity_mandatory_enabled ?? false,
            'mandatory_scope' => $company->activity_mandatory_scope ?? 'all',
        ];
    }

    /**
     * Get unique departments from company users.
     */
    public function getAvailableDepartments(Company $company): Collection
    {
        return User::where('company_id', $company->id)
            ->whereNotNull('department')
            ->where('department', '!=', '')
            ->distinct()
            ->pluck('department')
            ->sort()
            ->values();
    }

    /**
     * Get unique positions from company users.
     */
    public function getAvailablePositions(Company $company): Collection
    {
        return User::where('company_id', $company->id)
            ->whereNotNull('position')
            ->where('position', '!=', '')
            ->distinct()
            ->pluck('position')
            ->sort()
            ->values();
    }

    /**
     * Preview which users would be affected by a rule configuration.
     */
    public function previewRuleEffect(Company $company, string $ruleType, array $targetValues = null): Collection
    {
        $query = User::where('company_id', $company->id)
            ->where('is_active', true);

        return match ($ruleType) {
            'all_users' => $query->get(),
            'specific_users' => $query->whereIn('id', $targetValues ?? [])->get(),
            'departments' => $query->whereIn('department', $targetValues ?? [])->get(),
            'positions' => $query->whereIn('position', $targetValues ?? [])->get(),
            default => collect(),
        };
    }
}
