<?php

namespace Modules\ProductCompat\Http\Controllers;

use App\Product;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Modules\ProductCompat\Entities\PcPartNumber;
use Modules\ProductCompat\Entities\PcDeviceCompat;
use Modules\ProductCompat\Entities\PcCompatible;
use Modules\ProductCompat\Entities\PcDataCandidate;
use Modules\ProductCompat\Entities\PcProductStatus;
use Modules\ProductCompat\Entities\Services\ProductCompatService;

class ReviewController extends Controller
{
    protected ProductCompatService $service;

    public function __construct(ProductCompatService $service)
    {
        $this->service = $service;
    }

    /**
     * Queue of products that have parsed data still needing review.
     */
    public function index(Request $request)
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $business_id = $request->session()->get('user.business_id');

        // Product ids with at least one needs_review part number, device compat,
        // or cross-product compatibility link.
        $partIds = PcPartNumber::where('business_id', $business_id)->where('needs_review', true)->pluck('product_id');
        $devIds  = PcDeviceCompat::where('business_id', $business_id)->where('needs_review', true)->pluck('product_id');
        $linkIds = PcCompatible::where('business_id', $business_id)->where('needs_review', true)->pluck('product_id');
        $productIds = $partIds->merge($devIds)->merge($linkIds);

        // Also surface products that only have pending AI data candidates (guarded
        // so review still works before the pc_data_candidates migration has run).
        $hasCandidates = Schema::hasTable('pc_data_candidates');
        if ($hasCandidates) {
            $candIds = PcDataCandidate::where('business_id', $business_id)
                ->where('status', 'pending')->pluck('product_id');
            $productIds = $productIds->merge($candIds);
        }
        $productIds = $productIds->unique()->values();

        $products = Product::whereIn('id', $productIds)
            ->select('id', 'name', 'sku')
            ->orderBy('sku')
            ->paginate(25);

        // Inline-load the flagged items only for the products on this page.
        $pageIds = $products->getCollection()->pluck('id');
        $flaggedDevices = PcDeviceCompat::with('deviceModel')
            ->whereIn('product_id', $pageIds)->where('needs_review', true)
            ->orderByDesc('confidence')->get()->groupBy('product_id');
        $flaggedParts = PcPartNumber::whereIn('product_id', $pageIds)->where('needs_review', true)
            ->orderByDesc('confidence')->get()->groupBy('product_id');
        $flaggedCompat = PcCompatible::with('compatibleProduct')
            ->whereIn('product_id', $pageIds)->where('needs_review', true)
            ->get()->groupBy('product_id');

        // Pending AI data candidates for the products on this page.
        $pendingCandidates = collect();
        if ($hasCandidates) {
            $pendingCandidates = PcDataCandidate::whereIn('product_id', $pageIds)
                ->where('status', 'pending')
                ->orderByDesc('confidence')->get()->groupBy('product_id');
        }

        // How many device suggestions could be cleared in one bulk action.
        $bulkCount = PcDeviceCompat::where('business_id', $business_id)->where('needs_review', true)->count();

        return view('productcompat::review.index', compact('products', 'flaggedDevices', 'flaggedParts', 'flaggedCompat', 'bulkCount', 'pendingCandidates'));
    }

    /**
     * Approve selected suggestions (verify them, clear needs_review).
     */
    public function approve(Request $request)
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $business_id = $request->session()->get('user.business_id');
        $now = now();
        $uid = (int) auth()->id();

        $compatIds = array_filter(array_map('intval', (array) $request->input('compat_ids', [])));
        $partIds   = array_filter(array_map('intval', (array) $request->input('part_ids', [])));
        $linkIds   = array_filter(array_map('intval', (array) $request->input('link_ids', [])));
        $count = 0;

        if ($compatIds) {
            $count += PcDeviceCompat::where('business_id', $business_id)->whereIn('id', $compatIds)
                ->update(['needs_review' => false, 'verified_at' => $now, 'verified_by' => $uid]);
        }
        if ($partIds) {
            $count += PcPartNumber::where('business_id', $business_id)->whereIn('id', $partIds)
                ->update(['needs_review' => false, 'verified_at' => $now, 'verified_by' => $uid]);
        }
        if ($linkIds) {
            $count += PcCompatible::where('business_id', $business_id)->whereIn('id', $linkIds)
                ->update(['needs_review' => false, 'verified_at' => $now, 'verified_by' => $uid]);
        }

        return redirect()->back()->with('status', ['success' => 1, 'msg' => "Approved {$count} suggestion(s)."]);
    }

    /**
     * Reject (delete) selected suggestions — wrong classifications.
     */
    public function reject(Request $request)
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $business_id = $request->session()->get('user.business_id');
        $compatIds = array_filter(array_map('intval', (array) $request->input('compat_ids', [])));
        $partIds   = array_filter(array_map('intval', (array) $request->input('part_ids', [])));
        $linkIds   = array_filter(array_map('intval', (array) $request->input('link_ids', [])));
        $count = 0;

        if ($compatIds) {
            $count += PcDeviceCompat::where('business_id', $business_id)->whereIn('id', $compatIds)->delete();
        }
        if ($partIds) {
            $count += PcPartNumber::where('business_id', $business_id)->whereIn('id', $partIds)->delete();
        }
        if ($linkIds) {
            $count += PcCompatible::where('business_id', $business_id)->whereIn('id', $linkIds)->delete();
        }

        return redirect()->back()->with('status', ['success' => 1, 'msg' => "Rejected {$count} suggestion(s)."]);
    }

    /**
     * Bulk-approve every device suggestion at/above a confidence threshold —
     * fast path to clear the easy backlog.
     */
    public function bulkApprove(Request $request)
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $business_id = $request->session()->get('user.business_id');
        $min = (int) $request->input('min_confidence', 50);
        $now = now();
        $uid = (int) auth()->id();

        $devices = PcDeviceCompat::where('business_id', $business_id)->where('needs_review', true)
            ->where('confidence', '>=', $min)
            ->update(['needs_review' => false, 'verified_at' => $now, 'verified_by' => $uid]);
        $parts = PcPartNumber::where('business_id', $business_id)->where('needs_review', true)
            ->where('confidence', '>=', $min)
            ->update(['needs_review' => false, 'verified_at' => $now, 'verified_by' => $uid]);

        return redirect()->back()->with('status', ['success' => 1, 'msg' => "Bulk-approved {$devices} device + {$parts} part suggestion(s) at ≥ {$min}% confidence."]);
    }

    /**
     * Mark a product checked and verify its parsed rows.
     */
    public function markChecked(Request $request)
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate(['product_id' => 'required|exists:products,id']);
        $product = Product::findOrFail($request->input('product_id'));

        $this->service->markChecked((int) $product->business_id, (int) $product->id, (int) auth()->id());

        return redirect()->back()->with('status', ['success' => 1, 'msg' => __('productcompat::lang.marked_checked')]);
    }

    /**
     * Clear the legacy product_custom_field* data — only permitted once the
     * product has been marked checked.
     */
    public function removeCustomFields(Request $request)
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate(['product_id' => 'required|exists:products,id']);
        $product = Product::findOrFail($request->input('product_id'));

        $status = PcProductStatus::where('product_id', $product->id)->first();
        if (! $status || empty($status->checked_at)) {
            return redirect()->back()->with('status', ['success' => 0, 'msg' => __('productcompat::lang.cf_not_checked')]);
        }

        // Snapshot then clear the 20 custom field columns.
        $columns = [];
        for ($i = 1; $i <= 20; $i++) {
            $columns['product_custom_field' . $i] = null;
        }

        $before = DB::table('products')->where('id', $product->id)->first(array_keys($columns));
        DB::table('products')->where('id', $product->id)->update($columns);

        $status->update(['custom_fields_cleared_at' => now()]);

        Log::info('[ProductCompat] custom fields cleared', [
            'product_id' => $product->id,
            'by'         => auth()->id(),
            'before'     => $before,
        ]);

        return redirect()->back()->with('status', ['success' => 1, 'msg' => __('productcompat::lang.cf_removed')]);
    }
}
