<?php

namespace App\Http\Controllers;

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

class BusinessController extends Controller
{
    protected $duplicateCheck;
    protected $businessImport;

    public function __construct(DuplicateCheckService $duplicateCheck, \App\Services\BusinessImportService $businessImport)
    {
        $this->duplicateCheck = $duplicateCheck;
        $this->businessImport = $businessImport;
    }

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

        // Role-based filtering
        if ($user->isAdmin()) {
            // Admin sees all businesses - no filter needed
        } elseif ($user->isHead()) {
            // Head sees businesses assigned to them OR their team members 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 ONLY businesses 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);
                  });
            });
        }

        // Search
        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}%");
            });
        }

        // Filter by overdue followups
        if ($request->has('overdue') && $request->overdue) {
            $query->overdueFollowups();
        }

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

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

            if (!$hasAccess) {
                $business->email = '********';
                $business->mobile = '********';
            }
            // Add flag for frontend UI to disable view button if needed
            $business->can_view_details = $hasAccess;

            return $business;
        });

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

    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',
            'purpose' => 'nullable|string',
            'size' => 'nullable|string',
            'notes' => 'nullable|string',
            'next_followup_date' => 'nullable|date',
            'linkedin_url' => 'nullable|string|url',
            'user_ids' => 'nullable|array', // Assign to Heads
            'user_ids.*' => 'exists:users,id',
        ]);

        // Validate assignments
        $assignedUsers = [];
        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 businesses 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 businesses 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 no head, maybe allow self only?
                         if ($assignedUser->id !== $currentUser->id) {
                            return response()->json(['message' => "You don't have a Head assigned, so you cannot assign others."], 403);
                         }
                    } else {
                        // Allowed: The Head, or any member of that Head (Peer), or Self
                        $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 businesses to your Head or Team members ({$assignedUser->name})"], 403);
                        }
                    }
                }
        }

        // Check for duplicates
        $duplicates = $this->duplicateCheck->checkDuplicate(
            $validated['email'],
            $validated['mobile'],
            null,
            'business'
        );

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

        DB::beginTransaction();
        try {
            $business = Business::create([
                ...$validated,
                'created_by' => $request->user()->id,
            ]);

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

            DB::commit();

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

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

        // Check access
        // Check access
        if ($user->isTeamMember()) {
            $headId = $user->head()->first()->id ?? null;
            $isAssigned = $business->assignedTo->contains($headId) || 
                          $business->assignedTo->contains($user->id);
            
            // Allow if assigned OR if created by user
            if (!$isAssigned && $business->created_by !== $user->id) {
                return response()->json(['message' => 'Unauthorized'], 403);
            }
        } elseif ($user->isHead()) {
            $isAssigned = $business->assignedTo->contains($user->id);
            $isCreator = $business->created_by === $user->id;
            
            // Check if created by ANY of their team members
            $teamMemberIds = $user->members->pluck('id')->toArray();
            $isTeamCreator = in_array($business->created_by, $teamMemberIds);

            // Allow if assigned OR if created by user OR created by team member
            if (!$isAssigned && !$isCreator && !$isTeamCreator) {
                return response()->json(['message' => 'Unauthorized'], 403);
            }
        }

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

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

        // Check access
        if ($user->isTeamMember()) {
            $headId = $user->head()->first()->id ?? null;
            $isAssigned = $business->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 = $business->assignedTo->contains($user->id);
            $isCreator = $business->created_by === $user->id;
            
            // Check if created by ANY of their team members
            $teamMemberIds = $user->members->pluck('id')->toArray();
            $isTeamCreator = in_array($business->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',
            'purpose' => 'nullable|string',
            'size' => 'nullable|string',
            'notes' => 'nullable|string',
            'next_followup_date' => 'nullable|date',
            'linkedin_url' => 'nullable|string|url',
            '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 businesses 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 businesses 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 businesses to your Head or Team members ({$assignedUser->name})"], 403);
                        }
                    }
                }
            }
        }

        // Check for duplicates if email or mobile changed
        if (isset($validated['email']) || isset($validated['mobile'])) {
            $duplicates = $this->duplicateCheck->checkDuplicate(
                $validated['email'] ?? $business->email,
                $validated['mobile'] ?? $business->mobile,
                $id,
                'business'
            );

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

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

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

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

            DB::commit();

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

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

        // Only admin and head can delete
        if ($user->isTeamMember()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $business->delete();

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

    public function convertToProject($id, Request $request)
    {
        $business = Business::findOrFail($id);
        $user = $request->user();

        // Only Admin and Head can convert (Mark Deal Done)
        if ($user->isTeamMember()) {
            return response()->json(['message' => 'Unauthorized. Only Admin and Head can mark deal as done.'], 403);
        }

        // Logic to convert: Create Project from Business data
        $project = \App\Models\Project::create([
            'company_name' => $business->company_name,
            'contact_person' => $business->person_name,
            'mobile' => $business->mobile,
            'purpose' => $business->purpose,
            'status' => 'ongoing',
            'email' => $business->email,
            'size' => $business->size,
            'notes' => $business->notes,
            'linkedin_url' => $business->linkedin_url,
            'next_followup_date' => $business->next_followup_date,
            'created_by' => $user->id,
        ]);

        // Assign same users to project
        $userIds = $business->assignedTo->pluck('id')->toArray();
        if (!empty($userIds)) {
            $project->assignedTo()->attach($userIds);
        }

        // Soft delete business after conversion
        $business->delete();

        return response()->json([
            'message' => 'Business converted to Project successfully',
            'project_id' => $project->id, 
        ]);
    }

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

        if ($user->isTeamMember()) {
            return response()->json(['message' => 'Unauthorized. Only Admin and Head can import businesses.'], 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 businesses to Admin users ({$assignedUser->name})"], 422);
                }

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

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

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

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