<?php

namespace App\Http\Controllers;

use App\Models\Lead;
use App\Services\DuplicateCheckService;
use App\Services\LeadImportService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class LeadController extends Controller
{
    protected $duplicateCheck;
    protected $leadImport;

    public function __construct(DuplicateCheckService $duplicateCheck, LeadImportService $leadImport)
    {
        $this->duplicateCheck = $duplicateCheck;
        $this->leadImport = $leadImport;
    }

    public function index(Request $request)
    {
        $user = $request->user();
        $query = Lead::with(['assignedTo', 'creator']);

        if ($user->isAdmin()) {
            // Admin sees all leads - no filter needed
        } elseif ($user->isHead()) {
            // Head sees leads assigned to them/team OR created by them/team
            $teamMemberIds = $user->members->pluck('id')->toArray();
            $teamMemberIds[] = $user->id; // Include self
            
            $query->where(function($q) use ($teamMemberIds) {
                $q->whereIn('created_by', $teamMemberIds)
                  ->orWhereHas('assignedTo', function ($sq) use ($teamMemberIds) {
                      $sq->whereIn('users.id', $teamMemberIds);
                  });
            });
        } elseif ($user->isTeamMember()) {
            // Team Member sees leads assigned to them OR created by them
            $query->where(function($q) use ($user) {
                $q->where('created_by', $user->id)
                  ->orWhereHas('assignedTo', function ($sq) use ($user) {
                      $sq->where('users.id', $user->id);
                  });
            });
        }

        // Filters
        if ($request->has('status')) {
            $query->where('status', $request->status);
        }

        if ($request->has('quality')) {
            $query->where('lead_quality', $request->quality);
        }

        if ($request->has('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('person_name', 'like', "%{$search}%")
                    ->orWhere('company_name', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%")
                    ->orWhere('mobile', 'like', "%{$search}%");
            });
        }

        $leads = $query->latest()->paginate(20);

        $leads->getCollection()->transform(function ($lead) use ($user) {
            $hasAccess = $user->isAdmin() || 
                $user->isHead() || 
                $lead->created_by == $user->id ||
                $lead->assignedTo->contains($user->id);

            if (!$hasAccess) {
                $lead->email = '********';
                $lead->mobile = '********';
            }
            $lead->can_view_details = $hasAccess;

            return $lead;
        });

        return response()->json($leads);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'person_name' => 'required|string|max:255',
            'company_name' => 'required|string|max:255',
            'email' => 'nullable|email|max:255|required_without:mobile',
            'mobile' => 'nullable|string|max:15|required_without:email',
            'size' => 'nullable|string',
            'notes' => 'nullable|string',
            'lead_quality' => 'required|in:general,priority',
            'linkedin_url' => 'nullable|string|url',
            'purpose' => 'nullable|string',
            'status' => 'required|in:new,follow-up,lost,open',
            'next_followup_date' => 'nullable|date',
            'user_ids' => 'nullable|array', // Assign to Heads
            'user_ids.*' => 'exists:users,id',
        ]);

        // Validate assignments
        if (!empty($validated['user_ids'])) {
            $assignedUsers = \App\Models\User::whereIn('id', $validated['user_ids'])->with('role')->get();
            $currentUser = $request->user();

            foreach ($assignedUsers as $assignedUser) {
                // 1. Prevent assigning to Admins
                if ($assignedUser->isAdmin()) {
                    return response()->json(['message' => "Cannot assign leads to Admin users ({$assignedUser->name})"], 422);
                }

                // 2. Head can only assign to their team members
                if ($currentUser->isHead()) {
                    // Check if assigned user is in head's team or is the head themselves
                    $isMyTeam = $assignedUser->head->contains($currentUser->id) || $assignedUser->id === $currentUser->id;
                    if (!$isMyTeam) {
                        return response()->json(['message' => "You can only assign leads to your team members ({$assignedUser->name})"], 403);
                    }
                }

                // 3. Team Member can assign to their Head or Peers (Same Head)
                if ($currentUser->isTeamMember()) {
                    $myHead = $currentUser->head()->first();
                    if (!$myHead) {
                         if ($assignedUser->id !== $currentUser->id) {
                            return response()->json(['message' => "You don't have a Head assigned, so you cannot assign others."], 403);
                         }
                    } else {
                        $isHead = $assignedUser->id === $myHead->id;
                        $isPeer = $assignedUser->head->contains($myHead->id);
                        $isSelf = $assignedUser->id === $currentUser->id;

                        if (!$isHead && !$isPeer && !$isSelf) {
                            return response()->json(['message' => "You can only assign leads to your Head or Team members ({$assignedUser->name})"], 403);
                        }
                    }
                }
            }
        }

        $duplicates = $this->duplicateCheck->checkDuplicate(
            $validated['email'],
            $validated['mobile'],
            null,
            'lead'
        );

        if (!empty($duplicates)) {
            return response()->json(['errors' => $duplicates], 422);
        }

        DB::beginTransaction();
        try {
            $lead = Lead::create([
                'person_name' => $validated['person_name'],
                'company_name' => $validated['company_name'],
                'email' => $validated['email'],
                'mobile' => $validated['mobile'],
                'size' => $validated['size'] ?? null,
                'notes' => $validated['notes'] ?? null,
                'lead_quality' => $validated['lead_quality'] ?? 'general',
                'purpose' => $validated['purpose'] ?? null,
                'status' => $validated['status'] ?? 'new',
                'linkedin_url' => $validated['linkedin_url'] ?? null,
                'next_followup_date' => isset($validated['next_followup_date']) ? date('Y-m-d', strtotime($validated['next_followup_date'])) : null,
                'lead_type' => 'investor', // Assuming a default lead_type for manually created leads
                'is_imported' => false,
                'is_accepted' => $request->user()->isTeamMember() ? true : null,
                'created_by' => $request->user()->id,
            ]);

            if (!empty($validated['user_ids'])) {
                $lead->assignedTo()->attach($validated['user_ids']);
            }
            $lead->load(['assignedTo', 'creator']);

            DB::commit();

            return response()->json([
                'message' => 'Lead created successfully',
                'lead' => $lead,
            ], 201);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Failed to create lead: ' . $e->getMessage()], 500);
        }
    }

    public function show($id, Request $request)
    {
        $user = $request->user();
        $lead = Lead::with(['assignedTo', 'creator'])->findOrFail($id);

        // Check access
        if ($user->isTeamMember()) {
            $headId = $user->head()->first()->id ?? null;
            
            // Team member can view if:
            // 1. They created it
            // 2. It's assigned to them
            // 3. It's assigned to their head
            $canView = ($lead->created_by === $user->id) ||
                       $lead->assignedTo->contains($user->id) ||
                       ($headId && $lead->assignedTo->contains($headId));
            
            if (!$canView) {
                return response()->json(['message' => 'Unauthorized'], 403);
            }
        } elseif ($user->isHead()) {
            $isAssigned = $lead->assignedTo->contains($user->id);
            $isCreator = $lead->created_by === $user->id;

            // Check if created by ANY of their team members
            $teamMemberIds = $user->members->pluck('id')->toArray();
            $isTeamCreator = in_array($lead->created_by, $teamMemberIds);

             if (!$isAssigned && !$isCreator && !$isTeamCreator) {
                return response()->json(['message' => 'Unauthorized'], 403);
            }
        }

        return response()->json($lead);
    }

    public function update(Request $request, $id)
    {
        $lead = Lead::findOrFail($id);
        $user = $request->user();

        // Check access
        if ($user->isTeamMember()) {
            $headId = $user->head()->first()->id ?? null;
            $isAssigned = $lead->assignedTo->contains($headId);
            //  if (!$isAssigned) {
            //     return response()->json(['message' => 'Unauthorized'], 403);
            // }
        } elseif ($user->isHead()) {
            // Head can update if:
            // 1. Assigned to them
            // 2. Created by them
            // 3. Created by their team member
             $isAssigned = $lead->assignedTo->contains($user->id);
             $isCreator = $lead->created_by === $user->id;
             
             $teamMemberIds = $user->members->pluck('id')->toArray();
             $isTeamCreator = in_array($lead->created_by, $teamMemberIds);

             if (!$isAssigned && !$isCreator && !$isTeamCreator) {
                return response()->json(['message' => 'Unauthorized'], 403);
            }
        }

        $validated = $request->validate([
            'person_name' => 'sometimes|required|string|max:255',
            'company_name' => 'sometimes|required|string|max:255',
            'email' => 'sometimes|required|email|max:255',
            'mobile' => 'sometimes|required|string|max:15',
            'size' => 'nullable|string',
            'notes' => 'nullable|string',
            'lead_quality' => 'sometimes|in:general,priority',
            'lead_quality' => 'sometimes|in:general,priority',
            'linkedin_url' => 'nullable|string|url',
            'purpose' => 'nullable|string',
            'status' => 'sometimes|in:new,follow-up,lost,open',
            'next_followup_date' => 'nullable|date',
            'user_ids' => 'sometimes|array',
            'user_ids.*' => 'exists:users,id',
        ]);

        if (isset($validated['user_ids'])) {
            // Validate assignments
            $assignedUsers = \App\Models\User::whereIn('id', $validated['user_ids'])->with('role')->get();
            $currentUser = $request->user();

            foreach ($assignedUsers as $assignedUser) {
                // 1. Prevent assigning to Admins
                if ($assignedUser->isAdmin()) {
                    return response()->json(['message' => "Cannot assign leads to Admin users ({$assignedUser->name})"], 422);
                }

                // 2. Head can only assign to their team members
                if ($currentUser->isHead()) {
                    // Check if assigned user is in head's team or is the head themselves
                    $isMyTeam = $assignedUser->head->contains($currentUser->id) || $assignedUser->id === $currentUser->id;
                    if (!$isMyTeam) {
                        return response()->json(['message' => "You can only assign leads to your team members ({$assignedUser->name})"], 403);
                    }
                }
            }
        }

        if (isset($validated['email']) || isset($validated['mobile'])) {
            $duplicates = $this->duplicateCheck->checkDuplicate(
                $validated['email'] ?? $lead->email,
                $validated['mobile'] ?? $lead->mobile,
                $id,
                'lead'
            );

            if (!empty($duplicates)) {
                return response()->json(['errors' => $duplicates], 422);
            }
        }

        DB::beginTransaction();
        try {
            $lead->update($validated);

            if (isset($validated['user_ids'])) {
                $lead->assignedTo()->sync($validated['user_ids']);
            }

            $lead->load(['assignedTo', 'creator']);

            DB::commit();

            return response()->json([
                'message' => 'Lead updated successfully',
                'lead' => $lead,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Failed to update lead'], 500);
        }
    }

    public function destroy($id, Request $request)
    {
        $lead = Lead::findOrFail($id);
        $user = $request->user();

        if ($user->isTeamMember()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $lead->delete();

        return response()->json(['message' => 'Lead deleted successfully']);
    }

    public function import(Request $request)
    {
        $user = $request->user();

        if ($user->isTeamMember()) {
            return response()->json(['message' => 'Unauthorized. Only Admin and Head can import leads.'], 403);
        }

        $request->validate([
            'file' => 'required|file|mimetypes:text/csv,text/plain,application/csv,text/comma-separated-values,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/octet-stream',
            'user_ids' => 'nullable|array',
            'user_ids.*' => 'exists:users,id',
        ]);

        // Validate assignments only if provided
        if ($request->has('user_ids') && !empty($request->user_ids)) {
            $assignedUsers = \App\Models\User::whereIn('id', $request->user_ids)->with('role')->get();
            
            foreach ($assignedUsers as $assignedUser) {
                // 1. Prevent assigning to Admins
                if ($assignedUser->isAdmin()) {
                    return response()->json(['message' => "Cannot assign leads to Admin users ({$assignedUser->name})"], 422);
                }

                // 2. Head can only assign to their team members
                if ($user->isHead()) {
                    // Check if assigned user is in head's team or is the head themselves
                    $isMyTeam = $assignedUser->head->contains($user->id) || $assignedUser->id === $user->id;
                    if (!$isMyTeam) {
                        return response()->json(['message' => "You can only assign leads to your team members ({$assignedUser->name})"], 403);
                    }
                }
            }
        }

        $file = $request->file('file');
        $filePath = $file->getRealPath();

        $result = $this->leadImport->importFromExcel(
            $filePath,
            $request->user_ids ?? [],
            $user->id
        );

        return response()->json([
            'message' => "Import completed. {$result['imported']} leads imported.",
            'imported' => $result['imported'],
            'errors' => $result['errors'],
        ]);
    }

    public function accept($id, Request $request)
    {
        $user = $request->user();
        $lead = Lead::findOrFail($id);

        if (!$user->isTeamMember() && !$user->isHead()) {
             return response()->json(['message' => 'Unauthorized'], 403);
        }

        $assignment = null;

        if ($user->isHead()) {
             // Head can accept if assigned to them OR any of their team members
             $teamMemberIds = $user->members->pluck('id')->toArray();
             $teamMemberIds[] = $user->id;
             
             $assignment = DB::table('lead_assignments')
                ->where('lead_id', $id)
                ->whereIn('user_id', $teamMemberIds)
                ->first();
        } else {
            // Team Member
            $headId = $user->head()->first()->id ?? null;
            
            $assignment = DB::table('lead_assignments')
                ->where('lead_id', $id)
                ->where(function ($q) use ($user, $headId) {
                    $q->where('user_id', $user->id); // Direct assignment
                    if ($headId) {
                        $q->orWhere('user_id', $headId); // Head assignment
                    }
                })
                ->first();
        }

        if (!$assignment) {
            return response()->json(['message' => 'Lead not assigned to you or your team'], 403);
        }

        DB::table('lead_assignments')
            ->where('id', $assignment->id)
            ->update([
                'accepted_at' => now(),
                'rejected_at' => null,
            ]);

        $lead->update(['is_accepted' => true]);

        return response()->json(['message' => 'Lead accepted successfully']);
    }

    public function reject($id, Request $request)
    {
        $user = $request->user();
        $lead = Lead::findOrFail($id);

        if (!$user->isTeamMember() && !$user->isHead()) {
             return response()->json(['message' => 'Unauthorized'], 403);
        }

        $assignment = null;

        if ($user->isHead()) {
             // Head can reject if assigned to them OR any of their team members
             $teamMemberIds = $user->members->pluck('id')->toArray();
             $teamMemberIds[] = $user->id;
             
             $assignment = DB::table('lead_assignments')
                ->where('lead_id', $id)
                ->whereIn('user_id', $teamMemberIds)
                ->first();
        } else {
            // Team Member
            $headId = $user->head()->first()->id ?? null;
            
            $assignment = DB::table('lead_assignments')
                ->where('lead_id', $id)
                ->where(function ($q) use ($user, $headId) {
                    $q->where('user_id', $user->id); // Direct assignment
                    if ($headId) {
                        $q->orWhere('user_id', $headId); // Head assignment
                    }
                })
                ->first();
        }

        if (!$assignment) {
            return response()->json(['message' => 'Lead not assigned to you or your team'], 403);
        }

        DB::table('lead_assignments')
            ->where('id', $assignment->id)
            ->update([
                'rejected_at' => now(),
                'accepted_at' => null,
            ]);

        $lead->update(['is_accepted' => false]);

        return response()->json(['message' => 'Lead rejected successfully']);
    }

    public function priorityLeads(Request $request)
    {
        $user = $request->user();
        $query = Lead::priority()->with(['assignedTo', 'creator']);

        if ($user->isTeamMember()) {
            $headId = $user->head()->first()->id ?? null;
            if ($headId) {
                $query->whereHas('assignedTo', function ($q) use ($headId) {
                    $q->where('users.id', $headId);
                });
            }
        } elseif ($user->isHead()) {
            $query->whereHas('assignedTo', function ($q) use ($user) {
                $q->where('users.id', $user->id);
            });
        }

        $leads = $query->latest()->paginate(20);

        return response()->json($leads);
    }

    public function rejectedLeads(Request $request)
    {
        $user = $request->user();

        if ($user->isTeamMember()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        // Head sees rejected leads assigned to them
        $leads = Lead::with(['assignedTo', 'creator'])
            ->whereHas('assignedTo', function ($q) use ($user) {
                $q->where('users.id', $user->id)
                    ->whereNotNull('lead_assignments.rejected_at');
            })
            ->latest()
            ->paginate(20);

        return response()->json($leads);
    }
    public function newlyAssigned(Request $request)
    {
        $user = $request->user();

        if (!$user->isTeamMember()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $headId = $user->head()->first()->id ?? null;

        $leads = Lead::with(['assignedTo', 'creator'])
            ->whereHas('assignedTo', function ($q) use ($user, $headId) {
                $q->where(function ($subQ) use ($user, $headId) {
                    // Leads assigned directly to this team member (not accepted/rejected)
                    $subQ->where('users.id', $user->id)
                         ->whereNull('lead_assignments.accepted_at')
                         ->whereNull('lead_assignments.rejected_at');
                    
                    // OR leads assigned to their head (not accepted/rejected)
                    if ($headId) {
                        $subQ->orWhere(function ($headQ) use ($headId) {
                            $headQ->where('users.id', $headId)
                                  ->whereNull('lead_assignments.accepted_at')
                                  ->whereNull('lead_assignments.rejected_at');
                        });
                    }
                });
            })
            ->latest()
            ->paginate(20);

        return response()->json($leads);
    }

    // convertToProject removed
}
