<?php

namespace App\Services\Member;

use App\Models\CvProfile;
use App\Models\Hub;
use App\Models\User;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

// ══════════════════════════════════════════════════════════════════
//  InPractice — CvService
//  Location: app/Services/Member/CvService.php
//
//  All business logic for the CV Pool feature.
//
//  Methods:
//    myProfile()      → load current user's CV profile (or null)
//    saveProfile()    → create or update CV profile in DB transaction
//    toggleVisibility() → flip is_visible flag
//    index()          → browse anonymous CV pool with filters + pagination
//
//  N+1 rules:
//    - Pool index: one paginated query with no per-row joins
//    - Hub names loaded via cache — not per-profile
//    - Personal info (name, email, phone) NEVER returned in index()
//    - Personal info only returned when notification status = connected
// ══════════════════════════════════════════════════════════════════

class CvService
{
    // ── My Profile ────────────────────────────────────────────
    // Returns current user's CV profile or null (first visit).

    public function myProfile(User $user): array
    {
        $profile = CvProfile::where('user_id', $user->id)->first();

        $hubs = $this->getHubs();

        return [
            'profile'  => $profile ? $this->formatProfile($profile, showPersonal: false) : null,
            'allHubs'  => $hubs,
            'hasProfile' => $profile !== null,
        ];
    }

    // ── Save Profile ──────────────────────────────────────────
    // Creates or updates. Wrapped in DB transaction.

    public function saveProfile(User $user, array $data): CvProfile
    {
        return DB::transaction(function () use ($user, $data) {
            return CvProfile::updateOrCreate(
                ['user_id' => $user->id],
                $data
            );
        });
    }

    // ── Toggle Visibility ─────────────────────────────────────
    // Flips is_visible. Returns new state.

    public function toggleVisibility(User $user): bool
    {
        $profile = CvProfile::where('user_id', $user->id)->firstOrFail();

        $newState = ! $profile->is_visible;
        $profile->update(['is_visible' => $newState]);

        return $newState;
    }

    // ── CV Pool Index ─────────────────────────────────────────
    // Browsing the anonymous pool.
    // NEVER exposes name, email, or phone.
    // Filters: hub_id, experience_level, job_type_preference, years_experience_min
    // 12 per page.

    public function index(User $viewer, array $filters = []): array
    {
        $query = CvProfile::visible()
            ->select([
                'id',
                'job_title',
                'current_industry',
                'years_experience',
                'experience_level',
                'skills',
                'hub_ids',
                'education_level',
                'education_field',
                'location_country',
                'location_city',
                'summary',
                'preferred_sectors',
                'job_type_preference',
                'open_to_relocation',
                'user_id',      // needed to hide the viewer's own CV
                'updated_at',
            ]);

        // Never show the viewer their own CV in the pool
        $query->where('user_id', '!=', $viewer->id);

        // ── Filters ────────────────────────────────────────────
        if (! empty($filters['hub_id'])) {
            $query->whereJsonContains('hub_ids', (int) $filters['hub_id']);
        }

        if (! empty($filters['experience_level'])) {
            $query->where('experience_level', $filters['experience_level']);
        }

        if (! empty($filters['job_type_preference'])) {
            $query->where('job_type_preference', $filters['job_type_preference']);
        }

        if (isset($filters['years_experience_min']) && $filters['years_experience_min'] !== '') {
            $query->where('years_experience', '>=', (int) $filters['years_experience_min']);
        }

        // Most recently updated profiles first
        $profiles = $query->latest('updated_at')->paginate(12)->withQueryString();

        // Format — strip user_id from output, never expose personal info
        $profiles->getCollection()->transform(function ($profile) {
            return $this->formatProfileAnonymous($profile);
        });

        return [
            'profiles'   => $profiles,
            'allHubs'    => $this->getHubs(),
            'filters'    => $filters,
        ];
    }

    // ── Private helpers ───────────────────────────────────────

    /**
     * Format a profile for the owner's My Profile page.
     * showPersonal is always false — personal info lives on the User model
     * and is only shared through the job notification consent flow.
     */
    private function formatProfile(CvProfile $profile, bool $showPersonal = false): array
    {
        return [
            'id'                   => $profile->id,
            'job_title'            => $profile->job_title,
            'current_industry'     => $profile->current_industry,
            'years_experience'     => $profile->years_experience,
            'experience_level'     => $profile->experience_level,
            'skills'               => $profile->skills,
            'hub_ids'              => $profile->hub_ids,
            'education_level'      => $profile->education_level,
            'education_field'      => $profile->education_field,
            'location_country'     => $profile->location_country,
            'location_city'        => $profile->location_city,
            'summary'              => $profile->summary,
            'preferred_sectors'    => $profile->preferred_sectors,
            'job_type_preference'  => $profile->job_type_preference,
            'open_to_relocation'   => $profile->open_to_relocation,
            'is_visible'           => $profile->is_visible,
            'updated_at'           => $profile->updated_at?->diffForHumans(),
        ];
    }

    /**
     * Format a profile for the anonymous pool.
     * No user_id. No name. No email. No phone.
     */
    private function formatProfileAnonymous(CvProfile $profile): array
    {
        return [
            'id'                   => $profile->id,
            'job_title'            => $profile->job_title,
            'current_industry'     => $profile->current_industry,
            'years_experience'     => $profile->years_experience,
            'experience_level'     => $profile->experience_level,
            'skills'               => $profile->skills,
            'hub_ids'              => $profile->hub_ids,
            'education_level'      => $profile->education_level,
            'education_field'      => $profile->education_field,
            'location_country'     => $profile->location_country,
            'location_city'        => $profile->location_city,
            'summary'              => $profile->summary,
            'preferred_sectors'    => $profile->preferred_sectors,
            'job_type_preference'  => $profile->job_type_preference,
            'open_to_relocation'   => $profile->open_to_relocation,
            'updated_at'           => $profile->updated_at?->diffForHumans(),
        ];
    }

    private function getHubs(): \Illuminate\Database\Eloquent\Collection
    {
        return Cache::remember('hubs.active', 3600, function () {
            return Hub::where('is_active', true)
                ->select('id', 'name_en', 'name_ar', 'color', 'icon')
                ->orderBy('sort_order')
                ->get();
        });
    }
}
