<?php

namespace App\Http\Controllers\Company\Masters;

use App\Http\Controllers\Controller;
use App\Models\{Account, AuditLog, Currency, Vendor};
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class VendorsController extends Controller
{
    public function index(Request $request)
    {
        $this->gate('ap', 'view');

        $query = Vendor::with('currency');

        if ($request->filled('search')) {
            $s = $request->search;
            $query->where(fn($q) => $q->where('name','like',"%{$s}%")
                ->orWhere('code','like',"%{$s}%")
                ->orWhere('email','like',"%{$s}%")
                ->orWhere('phone','like',"%{$s}%"));
        }

        if ($request->filled('status')) {
            $query->where('is_active', $request->status === 'active');
        }

        $vendors = $query->orderBy('name')->paginate(25)->withQueryString();

        $stats = [
            'total'    => Vendor::count(),
            'active'   => Vendor::where('is_active', true)->count(),
            'inactive' => Vendor::where('is_active', false)->count(),
        ];

        return view('masters.vendors.index', compact('vendors', 'stats'));
    }

    public function create()
    {
        $this->gate('ap', 'create');
        return view('masters.vendors.create', $this->formData());
    }

    public function store(Request $request)
    {
        $this->gate('ap', 'create');

        $companyId = auth()->user()->company_id;
        $validated = $this->validateVendor($request, $companyId);

        $vendor = Vendor::withoutGlobalScopes()->create(array_merge(
            $validated,
            ['company_id' => $companyId, 'is_active' => true]
        ));

        AuditLog::record('create', 'vendors', (string) $vendor->id, null,
            ['name' => $vendor->name], "Vendor created: {$vendor->name}");

        return redirect()->route('masters.vendors.index')
            ->with('success', "Vendor '{$vendor->name}' created successfully.");
    }

    public function edit(Vendor $vendor)
    {
        $this->gate('ap', 'edit');
        $this->sameCompany($vendor);
        return view('masters.vendors.edit', array_merge($this->formData(), compact('vendor')));
    }

    public function update(Request $request, Vendor $vendor)
    {
        $this->gate('ap', 'edit');
        $this->sameCompany($vendor);

        $companyId = auth()->user()->company_id;
        $validated = $this->validateVendor($request, $companyId, $vendor->id);
        $old       = $vendor->only(['name','email','phone','is_active']);

        $vendor->update($validated);

        AuditLog::record('update', 'vendors', (string) $vendor->id, $old,
            $vendor->only(['name','email','phone','is_active']),
            "Vendor updated: {$vendor->name}");

        return redirect()->route('masters.vendors.index')
            ->with('success', "Vendor '{$vendor->name}' updated successfully.");
    }

    public function toggleActive(Vendor $vendor)
    {
        $this->gate('ap', 'edit');
        $this->sameCompany($vendor);
        $old = $vendor->is_active;
        $vendor->update(['is_active' => !$old]);
        return back()->with('success', "Vendor " . (!$old ? 'activated' : 'deactivated') . " successfully.");
    }

    public function destroy(Vendor $vendor)
    {
        $this->gate('ap', 'edit');
        $this->sameCompany($vendor);

        $guard = app(\App\Services\MasterDeletionGuard::class);
        if ($message = $guard->blockingMessage($vendor)) {
            return back()->withErrors(['error' => $message]);
        }

        $name = $vendor->name;
        $id = $vendor->id;
        $guard->hardDelete($vendor);
        AuditLog::record('hard_delete', 'vendors', (string) $id, null, null, "Vendor permanently deleted: {$name}");
        return redirect()->route('masters.vendors.index')->with('success', "Vendor '{$name}' permanently deleted.");
    }

    public function search(Request $request)
    {
        $q       = $request->input('q', '');
        $vendors = Vendor::where('is_active', true)
            ->when($q, fn($query) => $query->where(fn($qq) =>
                $qq->where('name','like',"%{$q}%")->orWhere('code','like',"%{$q}%")
            ))
            ->orderBy('name')->limit(50)->get(['id','code','name','currency_id']);

        return response()->json([
            'results' => $vendors->map(fn($v) => [
                'id'          => $v->id,
                'text'        => ($v->code ? "[{$v->code}] " : '') . $v->name,
                'currency_id' => $v->currency_id,
            ])
        ]);
    }

    private function validateVendor(Request $request, int $companyId, ?int $ignoreId = null): array
    {
        return $request->validate([
            'code'               => ['nullable','string','max:30',
                Rule::unique('vendors')->where(fn($q) => $q->where('company_id',$companyId)->whereNull('deleted_at'))->ignore($ignoreId)],
            'name'               => 'required|string|max:150',
            'contact_person'     => 'nullable|string|max:100',
            'email'              => 'nullable|email|max:150',
            'phone'              => 'nullable|string|max:30',
            'address'            => 'nullable|string|max:500',
            'tax_id'             => 'nullable|string|max:50',
            'currency_id'        => 'nullable|integer|exists:currencies,id',
            'payment_terms_days' => 'nullable|integer|min:0|max:365',
            'bank_name'          => 'nullable|string|max:100',
            'bank_account'       => 'nullable|string|max:50',
            'bank_routing'       => 'nullable|string|max:50',
            'account_payable_id' => 'nullable|integer|exists:accounts,id',
            'notes'              => 'nullable|string|max:1000',
            'is_active'          => 'boolean',
        ]);
    }

    private function formData(): array
    {
        $companyId = auth()->user()->company_id;
        return [
            'currencies' => Currency::withoutGlobalScopes()->where('company_id',$companyId)->where('is_active',true)->orderBy('code')->get(),
            'apAccounts' => Account::withoutGlobalScopes()->where('company_id',$companyId)->where('is_group',false)->where('is_active',true)->whereNull('deleted_at')->orderBy('code')->get(['id','code','name']),
        ];
    }

    private function gate(string $module, string $action): void
    {
        if (!auth()->user()->hasPermission($module, $action)) abort(403);
    }

    private function sameCompany(Vendor $vendor): void
    {
        if ($vendor->company_id !== auth()->user()->company_id) abort(403);
    }
}
