<?php

namespace App\Http\Controllers;

use App\Models\AuditLog;
use App\Models\Lead;
use App\Models\User;
use App\Services\ActivityLogger;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class LeadController extends Controller
{
    public function index(Request $request)
    {
        $currentUser = auth()->user();

        // 1. Data-Level Permission Scoping (own, team, department, all)
        $query = Lead::forUser($currentUser, 'leads')->with('assignee');

        // Search Filter
        if ($request->filled('search')) {
            $search = $request->input('search');
            $query->where(function($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('email', 'like', "%{$search}%")
                  ->orWhere('phone', 'like', "%{$search}%")
                  ->orWhere('company', 'like', "%{$search}%")
                  ->orWhere('lead_code', 'like', "%{$search}%");
            });
        }

        // Status Filter
        if ($request->filled('status')) {
            $query->where('status', $request->input('status'));
        }

        // Source Filter
        if ($request->filled('source')) {
            $query->where('source', $request->input('source'));
        }

        // Assigned To Filter (Scope-guarded)
        if ($request->filled('assigned_to')) {
            $query->where('assigned_to', $request->input('assigned_to'));
        }

        // Sort By Column
        $sortBy = $request->input('sort', 'latest');
        switch ($sortBy) {
            case 'oldest':
                $query->orderBy('created_at', 'asc');
                break;
            case 'name_asc':
                $query->orderBy('name', 'asc');
                break;
            case 'name_desc':
                $query->orderBy('name', 'desc');
                break;
            case 'source_asc':
                $query->orderBy('source', 'asc');
                break;
            case 'source_desc':
                $query->orderBy('source', 'desc');
                break;
            case 'value_desc':
                $query->orderBy('expected_value', 'desc');
                break;
            case 'value_asc':
                $query->orderBy('expected_value', 'asc');
                break;
            case 'status_asc':
            case 'status':
                $query->orderBy('status', 'asc');
                break;
            case 'status_desc':
                $query->orderBy('status', 'desc');
                break;
            case 'assignee_asc':
                $query->orderBy('assigned_to', 'asc');
                break;
            case 'assignee_desc':
                $query->orderBy('assigned_to', 'desc');
                break;
            case 'latest':
            default:
                $query->orderBy('created_at', 'desc');
                break;
        }

        // Per Page Option: 10, 20, 50, 100, all
        $perPageInput = $request->input('per_page', '20');
        if ($perPageInput === 'all') {
            $perPage = 999999;
        } else {
            $perPage = (int) $perPageInput;
            if (!in_array($perPage, [10, 20, 50, 100])) {
                $perPage = 20;
            }
        }

        $leads = $query->paginate($perPage)->withQueryString();

        // Assignable Users Dropdown (Filtered by user's authority)
        $users = $this->getAssignableUsers($currentUser);

        return view('leads.index', compact('leads', 'users', 'sortBy', 'perPageInput'));
    }

    public function create()
    {
        $currentUser = auth()->user();
        $users = $this->getAssignableUsers($currentUser);

        return view('leads.create', compact('users'));
    }

    public function store(Request $request)
    {
        $currentUser = auth()->user();

        $data = $request->validate([
            'name'           => 'required|string|max:160',
            'phone'          => 'nullable|string|max:40',
            'email'          => 'nullable|email|max:160',
            'source'         => 'required|string|max:50',
            'status'         => 'required|string|max:50',
            'assigned_to'    => 'nullable|exists:users,id',
            'expected_value' => 'nullable|numeric|min:0',
            'company'        => 'nullable|string|max:255',
            'notes'          => 'nullable|string',
        ]);

        // Default assigned user to creator if unassigned or if user lacks assign authority
        if (empty($data['assigned_to']) || (!$currentUser->isAdmin() && !$currentUser->hasPermission('leads.assign'))) {
            $data['assigned_to'] = $currentUser->id;
        }

        $data['lead_code'] = 'LD-' . strtoupper(Str::random(8));
        $lead = Lead::create($data);

        ActivityLogger::log('lead_created', 'Lead created.', [], $lead->id);
        AuditLog::log('lead_created', 'Leads', "Created lead '{$lead->name}' ({$lead->lead_code})", $lead, null, $lead->toArray());

        return redirect()->route('leads.index')->with('success', 'Lead created successfully.');
    }

    public function show(Lead $lead)
    {
        $currentUser = auth()->user();
        if (!$currentUser->canAccessLead($lead)) {
            return response()->view('errors.403', [
                'permission' => 'leads.view',
                'message'    => 'Access Denied: You are not authorized to view this lead record.'
            ], 403);
        }

        $lead->load(['assignee', 'followUps.user', 'customer']);
        return view('leads.show', compact('lead'));
    }

    public function edit(Lead $lead)
    {
        $currentUser = auth()->user();
        if (!$currentUser->canAccessLead($lead)) {
            return response()->view('errors.403', [
                'permission' => 'leads.edit',
                'message'    => 'Access Denied: You are not authorized to edit this lead record.'
            ], 403);
        }

        $users = $this->getAssignableUsers($currentUser);
        return view('leads.edit', compact('lead', 'users'));
    }

    public function update(Request $request, Lead $lead)
    {
        $currentUser = auth()->user();
        if (!$currentUser->canAccessLead($lead)) {
            return response()->view('errors.403', [
                'permission' => 'leads.edit',
                'message'    => 'Access Denied: You are not authorized to update this lead record.'
            ], 403);
        }

        $before = $lead->status;
        $oldValues = $lead->toArray();

        $data = $request->validate([
            'name'           => 'required|string|max:160',
            'phone'          => 'nullable|string|max:40',
            'email'          => 'nullable|email|max:160',
            'source'         => 'required|string|max:50',
            'status'         => 'required|string|max:50',
            'assigned_to'    => 'nullable|exists:users,id',
            'expected_value' => 'nullable|numeric|min:0',
            'company'        => 'nullable|string|max:255',
            'notes'          => 'nullable|string',
        ]);

        // Prevent unauthorized re-assignment
        if (!$currentUser->isAdmin() && !$currentUser->hasPermission('leads.assign')) {
            unset($data['assigned_to']);
        }

        $lead->update($data);

        if ($before !== $lead->status) {
            ActivityLogger::log('lead_status_changed', "Status changed from {$before} to {$lead->status}.", [
                'before' => $before,
                'after'  => $lead->status
            ], $lead->id);
        }

        AuditLog::log('lead_updated', 'Leads', "Updated lead '{$lead->name}' ({$lead->lead_code})", $lead, $oldValues, $lead->toArray());

        return redirect()->route('leads.show', $lead)->with('success', 'Lead updated successfully.');
    }

    public function destroy(Lead $lead)
    {
        $currentUser = auth()->user();
        if (!$currentUser->canAccessLead($lead)) {
            return response()->view('errors.403', [
                'permission' => 'leads.delete',
                'message'    => 'Access Denied: You are not authorized to delete this lead record.'
            ], 403);
        }

        $leadName = $lead->name;
        $lead->delete();

        ActivityLogger::log('lead_deleted', 'Lead deleted.', [], $lead->id);
        AuditLog::log('lead_deleted', 'Leads', "Deleted lead '{$leadName}'", $lead);

        return redirect()->route('leads.index')->with('success', "Lead '{$leadName}' deleted successfully.");
    }

    private function getAssignableUsers(User $user)
    {
        if ($user->isAdmin() || $user->isSuperAdmin() || $user->hasPermission('leads.assign')) {
            return User::where('active', true)->orderBy('name')->get();
        }

        if ($user->role === 'manager' || $user->role === 'team-leader') {
            $teamIds = array_merge([$user->id], $user->directReports()->pluck('id')->toArray());
            return User::whereIn('id', $teamIds)->where('active', true)->orderBy('name')->get();
        }

        return User::where('id', $user->id)->get();
    }
}
