<?php

namespace Modules\VetClinic\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\VetClinic\Entities\VcBlockSetting;
use Modules\VetClinic\Entities\VcEvaluation;
use Modules\VetClinic\Entities\VcPetOwnerDetail;
use Modules\VetClinic\Services\OwnerBlockService;
use App\Contact;

/**
 * Item 3.1 / 3.2 / 2.2 — Owner-blocking management.
 *
 *  GET    /vet-clinic/owner-blocking            - list of blocked owners
 *                                                 (3.2 page); also serves
 *                                                 as the "checklist for
 *                                                 administration" referenced
 *                                                 in 3.1.
 *  GET    /vet-clinic/owner-blocking/settings   - policy editor (3.1)
 *  POST   /vet-clinic/owner-blocking/settings   - save policy
 *  POST   /vet-clinic/owner-blocking/{id}/block - manual block (2.2)
 *  POST   /vet-clinic/owner-blocking/{id}/unblock - unblock with
 *           restore-or-keep credit-limit choice (3.2 prompt)
 */
class VcOwnerBlockingController extends Controller
{
    private function bizId(): int
    {
        return (int) request()->session()->get('user.business_id');
    }

    private function guardManage(): void
    {
        if (!auth()->user()->can('vet_clinic.manage_owner_blocking')) {
            abort(403, 'Not authorised to manage owner blocking.');
        }
    }

    private function guardView(): void
    {
        if (!auth()->user()->can('vet_clinic.view_owner_blocking')
            && !auth()->user()->can('vet_clinic.manage_owner_blocking')) {
            abort(403, 'Not authorised to view blocked owners.');
        }
    }

    /** GET /owner-blocking - blocked list + low-rated-not-yet-blocked queue. */
    public function index()
    {
        $this->guardView();
        $businessId = $this->bizId();
        $settings   = VcBlockSetting::forBusiness($businessId);

        $blocked = VcPetOwnerDetail::where('business_id', $businessId)
            ->where('is_blocked', true)
            ->with(['contact:id,name,supplier_business_name,mobile,credit_limit'])
            ->orderByDesc('blocked_at')
            ->get();

        // Item 3.1 - "review checklist" of owners who are NOT blocked yet
        // but are at or below the threshold (so admins can decide whether
        // to manually intervene). Only meaningful when auto-block is OFF,
        // or when an owner has enough ratings to evaluate but hasn't been
        // re-scored since policy was tightened.
        $threshold = $settings->block_rating_threshold;
        $minCount  = $settings->min_ratings_to_evaluate;
        $candidates = collect();
        $aggregated = \DB::table('vc_evaluations')
            ->where('business_id', $businessId)
            ->where('category', 'pet_owner')
            ->whereNotNull('avg_rating')
            ->whereNotNull('contact_id')
            ->selectRaw('contact_id, COUNT(*) as cnt, AVG(avg_rating) as avg_r')
            ->groupBy('contact_id')
            ->havingRaw('COUNT(*) >= ?', [$minCount])
            ->havingRaw('AVG(avg_rating) < ?', [$threshold / 100 * 5])
            ->get();

        if ($aggregated->isNotEmpty()) {
            $blockedIds = $blocked->pluck('contact_id')->all();
            $contactIds = $aggregated->pluck('contact_id')->reject(fn($id) => in_array($id, $blockedIds, true));
            $details = VcPetOwnerDetail::where('business_id', $businessId)
                ->whereIn('contact_id', $contactIds)
                ->with(['contact:id,name,supplier_business_name,mobile,credit_limit'])
                ->get()
                ->keyBy('contact_id');
            $candidates = $aggregated
                ->filter(fn($a) => $details->has($a->contact_id))
                ->map(function ($a) use ($details) {
                    $d = $details->get($a->contact_id);
                    $d->candidate_avg_rating = round($a->avg_r, 2);
                    $d->candidate_rating_count = (int) $a->cnt;
                    $d->candidate_percent = round(($a->avg_r / 5) * 100);
                    return $d;
                })
                ->values();
        }

        return view('vetClinic::owner-blocking.index', compact(
            'blocked', 'candidates', 'settings'
        ));
    }

    /** GET /owner-blocking/settings - shows the policy form. */
    public function settings()
    {
        $this->guardManage();
        $settings = VcBlockSetting::forBusiness($this->bizId());
        return view('vetClinic::owner-blocking.settings', compact('settings'));
    }

    /** POST /owner-blocking/settings - persists the policy. */
    public function saveSettings(Request $request)
    {
        $this->guardManage();
        $request->validate([
            'enable_auto_block'        => 'nullable|boolean',
            'block_rating_threshold'   => 'required|integer|min:0|max:100',
            'min_ratings_to_evaluate'  => 'required|integer|min:1|max:50',
            'block_zero_credit_limit'  => 'nullable|boolean',
        ]);
        $settings = VcBlockSetting::forBusiness($this->bizId());
        $settings->update([
            'enable_auto_block'        => $request->boolean('enable_auto_block'),
            'block_rating_threshold'   => (int) $request->block_rating_threshold,
            'min_ratings_to_evaluate'  => (int) $request->min_ratings_to_evaluate,
            'block_zero_credit_limit'  => $request->boolean('block_zero_credit_limit'),
        ]);
        return redirect()->route('vc.owner-blocking.settings')
            ->with('status', ['success' => 1, 'msg' => 'Auto-block policy saved.']);
    }

    /** POST /owner-blocking/{id}/block - manual block triggered from the
     *  owner profile (item 2.2). Captures a free-text reason. */
    public function block(Request $request, $detailId)
    {
        $this->guardManage();
        $detail = VcPetOwnerDetail::where('business_id', $this->bizId())->findOrFail($detailId);
        $request->validate(['reason' => 'required|string|max:500']);

        $settings = VcBlockSetting::forBusiness($this->bizId());
        app(OwnerBlockService::class)->block(
            $detail,
            'Manual block: ' . $request->input('reason'),
            (int) auth()->id(),
            $settings->block_zero_credit_limit
        );
        return back()->with('status', ['success' => 1, 'msg' => 'Owner blocked.']);
    }

    /** POST /owner-blocking/{id}/unblock - asks whether to restore the
     *  prior credit limit or keep it at zero (item 3.2 prompt). */
    public function unblock(Request $request, $detailId)
    {
        $this->guardManage();
        $detail = VcPetOwnerDetail::where('business_id', $this->bizId())->findOrFail($detailId);
        $request->validate(['restore_credit_limit' => 'nullable|boolean']);

        app(OwnerBlockService::class)->unblock(
            $detail,
            $request->boolean('restore_credit_limit'),
            (int) auth()->id()
        );
        return back()->with('status', ['success' => 1, 'msg' => 'Owner unblocked.']);
    }
}
