<?php

namespace App\Http\Controllers;

use App\Models\Visit;
use App\Models\User;
use App\Models\Client;
use App\Models\Governorate;
use App\Models\City;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class VisitController extends Controller
{
    public function index()
    {
        $user = auth()->user();
        
        if ($user->hasRole('admin')) {
            $visits = Visit::with(['employee', 'client', 'governorate', 'city'])
                ->latest()
                ->paginate(15);
        } elseif ($user->hasRole('supervisor')) {
            $employeeIds = $user->subordinates()->pluck('id');
            $visits = Visit::with(['employee', 'client', 'governorate', 'city'])
                ->whereIn('employee_id', $employeeIds)
                ->orWhere('employee_id', $user->id)
                ->latest()
                ->paginate(15);
        } else {
            $visits = Visit::with(['client', 'governorate', 'city'])
                ->where('employee_id', $user->id)
                ->latest()
                ->paginate(15);
        }
        
        return view('visits.index', compact('visits'));
    }

    public function create()
    {
        $user = auth()->user();
        
        // Get clients
        $clients = Client::where('status', 'active')->orderBy('name')->get();
        $governorates = Governorate::orderBy('name')->get();
        
        // Get employees based on role
        if ($user->hasRole('admin')) {
            $employees = User::role('employee')->where('status', 'active')->get();
        } elseif ($user->hasRole('supervisor')) {
            $employees = $user->subordinates()->where('status', 'active')->get();
        } else {
            $employees = collect([$user]);
        }
        
        return view('visits.create', compact('clients', 'employees', 'governorates'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'employee_id' => 'required|exists:users,id',
            'client_id' => 'required|exists:clients,id',
            'governorate_id' => 'required|exists:governorates,id',
            'city_id' => 'required|exists:cities,id',
            'area' => 'required|string|max:255',
            'latitude' => 'nullable|numeric|between:-90,90',
            'longitude' => 'nullable|numeric|between:-180,180',
            'scheduled_date' => 'required|date',
            'scheduled_time' => 'required',
            'comments' => 'nullable|string',
        ]);

        try {
            DB::beginTransaction();
            
            // Get client location if coordinates not provided
            if (!$request->latitude || !$request->longitude) {
                $client = Client::find($request->client_id);
                if ($client->latitude && $client->longitude) {
                    $latitude = $client->latitude;
                    $longitude = $client->longitude;
                } else {
                    // Default to Cairo coordinates
                    $latitude = 30.0444;
                    $longitude = 31.2357;
                }
            } else {
                $latitude = $request->latitude;
                $longitude = $request->longitude;
            }
            
            $visit = Visit::create([
                'employee_id' => $request->employee_id,
                'client_id' => $request->client_id,
                'governorate_id' => $request->governorate_id,
                'city_id' => $request->city_id,
                'area' => $request->area,
                'latitude' => $latitude,
                'longitude' => $longitude,
                'scheduled_date' => $request->scheduled_date,
                'scheduled_time' => $request->scheduled_time,
                'comments' => $request->comments,
                'status' => 'scheduled',
            ]);
            
            DB::commit();
            
            return redirect()->route('visits.index')
                ->with('success', 'Visit scheduled successfully.');
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'Failed to schedule visit: ' . $e->getMessage());
        }
    }

    public function show(Visit $visit)
    {
        $this->authorize('view', $visit);
        
        $visit->load(['employee', 'client', 'governorate', 'city']);
        
        return view('visits.show', compact('visit'));
    }

    public function edit(Visit $visit)
    {
        $this->authorize('update', $visit);
        
        $user = auth()->user();
        $clients = Client::where('status', 'active')->orderBy('name')->get();
        $governorates = Governorate::orderBy('name')->get();
        $cities = City::where('governorate_id', $visit->governorate_id)->get();
        
        if ($user->hasRole('admin')) {
            $employees = User::role('employee')->where('status', 'active')->get();
        } elseif ($user->hasRole('supervisor')) {
            $employees = $user->subordinates()->where('status', 'active')->get();
        } else {
            $employees = collect([$user]);
        }
        
        return view('visits.edit', compact('visit', 'clients', 'employees', 'governorates', 'cities'));
    }

    public function update(Request $request, Visit $visit)
    {
        $this->authorize('update', $visit);
        
        $request->validate([
            'employee_id' => 'required|exists:users,id',
            'client_id' => 'required|exists:clients,id',
            'governorate_id' => 'required|exists:governorates,id',
            'city_id' => 'required|exists:cities,id',
            'area' => 'required|string|max:255',
            'latitude' => 'nullable|numeric|between:-90,90',
            'longitude' => 'nullable|numeric|between:-180,180',
            'scheduled_date' => 'required|date',
            'scheduled_time' => 'required',
            'comments' => 'nullable|string',
            'status' => 'required|in:scheduled,in_progress,completed,cancelled',
        ]);

        try {
            DB::beginTransaction();
            
            $visit->update([
                'employee_id' => $request->employee_id,
                'client_id' => $request->client_id,
                'governorate_id' => $request->governorate_id,
                'city_id' => $request->city_id,
                'area' => $request->area,
                'latitude' => $request->latitude,
                'longitude' => $request->longitude,
                'scheduled_date' => $request->scheduled_date,
                'scheduled_time' => $request->scheduled_time,
                'comments' => $request->comments,
                'status' => $request->status,
            ]);
            
            DB::commit();
            
            return redirect()->route('visits.index')
                ->with('success', 'Visit updated successfully.');
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'Failed to update visit: ' . $e->getMessage());
        }
    }

    public function destroy(Visit $visit)
    {
        $this->authorize('delete', $visit);
        
        $visit->delete();
        
        return redirect()->route('visits.index')
            ->with('success', 'Visit deleted successfully.');
    }

    public function myVisits()
    {
        $user = auth()->user();
        $visits = Visit::with(['client', 'governorate', 'city'])
            ->where('employee_id', $user->id)
            ->latest()
            ->paginate(15);
            
        return view('visits.my-visits', compact('visits'));
    }

    public function startVisit(Request $request, Visit $visit)
    {
        $this->authorize('update', $visit);
        
        if ($visit->status !== 'scheduled') {
            return back()->with('error', 'Visit cannot be started.');
        }
        
        $visit->update([
            'status' => 'in_progress',
            'started_at' => now(),
        ]);
        
        return back()->with('success', 'Visit started successfully.');
    }

    public function completeVisit(Request $request, Visit $visit)
    {
        $this->authorize('update', $visit);
        
        $request->validate([
            'employee_notes' => 'nullable|string',
        ]);
        
        if ($visit->status !== 'in_progress') {
            return back()->with('error', 'Visit is not in progress.');
        }
        
        $visit->update([
            'status' => 'completed',
            'completed_at' => now(),
            'employee_notes' => $request->employee_notes,
        ]);
        
        return back()->with('success', 'Visit completed successfully.');
    }

    public function getClientData(Request $request)
    {
        $client = Client::with(['governorate', 'city'])->find($request->client_id);
        
        if (!$client) {
            return response()->json(['error' => 'Client not found'], 404);
        }
        
        return response()->json([
            'governorate_id' => $client->governorate_id,
            'city_id' => $client->city_id,
            'area' => $client->area,
            'latitude' => $client->latitude,
            'longitude' => $client->longitude,
            'address' => $client->address,
        ]);
    }
}