<?php
namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\{Visit, Client, User, Ticket, ActivityLog};
use App\Services\NotificationService;
use Illuminate\Http\Request;

class VisitController extends Controller
{
    public function index(Request $request)
    {
        $q = Visit::with(['client','technician'])->orderByDesc('visit_date');
        if ($request->client_id)     $q->where('client_id', $request->client_id);
        if ($request->technician_id) $q->where('technician_id', $request->technician_id);
        if ($request->status)        $q->where('status', $request->status);
        if ($request->month)         $q->whereMonth('visit_date', $request->month)->whereYear('visit_date', $request->year ?? now()->year);
        $visits      = $q->paginate(20)->withQueryString();
        $clients     = Client::where('is_active',1)->orderBy('name')->get();
        $technicians = User::where('role','technician')->where('is_active',1)->get();
        return view('admin.visits.index', compact('visits','clients','technicians'));
    }

    public function calendar()
    {
        return view('admin.visits.calendar');
    }

    public function calendarEvents(Request $request)
    {
        $start = $request->start ?? now()->startOfMonth();
        $end   = $request->end   ?? now()->endOfMonth();
        $visits = Visit::with(['client','technician'])
            ->whereBetween('visit_date', [$start, $end])
            ->get();

        $events = [];
        foreach ($visits as $v) {
            $techName = $v->technician ? $v->technician->name : 'TBD';
            $color    = '#6b7280';
            if ($v->status === 'scheduled')  $color = '#3b82f6';
            if ($v->status === 'in_progress') $color = '#f59e0b';
            if ($v->status === 'done')        $color = '#10b981';
            if ($v->status === 'cancelled')   $color = '#ef4444';

            $startDt = $v->visit_date->format('Y-m-d').($v->visit_time_start ? 'T'.$v->visit_time_start : '');
            $endDt   = $v->visit_date->format('Y-m-d').($v->visit_time_end   ? 'T'.$v->visit_time_end   : '');

            $events[] = [
                'id'    => $v->id,
                'title' => "[{$v->client->name}] {$techName}",
                'start' => $startDt,
                'end'   => $endDt,
                'color' => $color,
                'url'   => route('admin.visits.show', $v->id),
                'extendedProps' => ['status'=>$v->status,'is_extra'=>$v->is_extra],
            ];
        }
        return response()->json($events);
    }

    public function create(Request $request)
    {
        $clients        = Client::where('is_active',1)->orderBy('name')->get();
        $technicians    = User::where('role','technician')->where('is_active',1)->get();
        $clientId       = $request->client_id ?: old('client_id');
        $selectedClient = $clientId ? Client::find($clientId) : null;
        $selectedTicket = $request->ticket_id ? Ticket::find($request->ticket_id) : null;
        if (!$selectedTicket && old('tickets')) {
            $selectedTicket = Ticket::find(collect(old('tickets'))->first());
        }
        if (!$selectedClient && $selectedTicket) {
            $selectedClient = $selectedTicket->client;
        }
        // Include tickets for this client, but exclude tickets that are attached to an active visit
        // unless the ticket itself is not resolved/closed (i.e. problem not finished) —
        // in that case show it so the technician can continue work.
        $clientTickets = collect();
        if ($selectedClient) {
            $clientTickets = Ticket::where('client_id', $selectedClient->id)
                ->where(function ($q) {
                    $q->whereDoesntHave('visits', function ($v) {
                        $v->whereIn('status', ['scheduled', 'in_progress']);
                    })
                    ->orWhereNotIn('status', ['resolved', 'closed']);
                })
                ->orderBy('ticket_number')
                ->get();
        }
        return view('admin.visits.create', compact('clients','technicians','selectedClient','selectedTicket','clientTickets'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'client_id'        => 'required|exists:clients,id',
            'tickets'          => 'nullable|array',
            'tickets.*'        => 'nullable|exists:tickets,id',
            'technician_id'    => 'nullable|exists:users,id',
            'visit_date'       => 'required|date',
            'visit_time_start' => 'nullable|date_format:H:i',
            'visit_time_end'   => 'nullable|date_format:H:i',
            'purpose'          => 'nullable|string',
            'notes'            => 'nullable|string',
        ]);
        $data['created_by'] = auth()->id();

        $client = Client::find($data['client_id']);
        if (!empty($data['tickets'])) {
            $ticketCount = Ticket::whereIn('id', $data['tickets'])->where('client_id', $data['client_id'])->count();
            if ($ticketCount !== count($data['tickets'])) {
                return back()->withErrors(['tickets'=>'Semua tiket harus terkait dengan klien yang dipilih.'])->withInput();
            }
        }
        if ($client->type === 'maintenance') {
            $used = $client->getVisitsThisMonth();
            if ($used >= $client->max_visits_per_month) {
                $data['is_extra']     = true;
                $data['extra_charge'] = $client->extra_visit_fee;
            }
        }

        if (!empty($data['tickets'])) {
            $data['ticket_id'] = $data['tickets'][0];
        }

        $visit = Visit::create($data);
        if (!empty($data['tickets'])) {
            $visit->tickets()->sync($data['tickets']);
        }

        ActivityLog::log('visit','created',"Kunjungan ke {$client->name} pada {$visit->visit_date->format('d/m/Y')}", $visit);

        $visit->load(['client','technician']);
        app(NotificationService::class)->notifyVisitScheduled($visit);

        return redirect()->route('admin.visits.show', $visit)->with('success','Kunjungan dijadwalkan.');
    }

    public function show(Visit $visit)
    {
        $visit->load(['client','technician','tickets','checklists']);

        $attachedTicketIds = $visit->tickets->pluck('id')->toArray();
        if ($visit->ticket_id) {
            $attachedTicketIds[] = $visit->ticket_id;
        }
        $availableTickets = Ticket::where('client_id', $visit->client_id)
            ->whereNotIn('id', array_unique($attachedTicketIds))
            ->orderByDesc('created_at')
            ->get();

        if ($visit->ticket_id && $visit->tickets->isEmpty()) {
            $visit->load('ticket');
        }
        return view('admin.visits.show', compact('visit','availableTickets'));
    }

    public function update(Request $request, Visit $visit)
    {
        $data = $request->validate([
            'technician_id'    => 'nullable|exists:users,id',
            'visit_date'       => 'required|date',
            'visit_time_start' => 'nullable|date_format:H:i',
            'visit_time_end'   => 'nullable|date_format:H:i',
            'purpose'          => 'nullable|string',
            'notes'            => 'nullable|string',
        ]);
        $visit->update($data);
        return back()->with('success','Kunjungan diperbarui.');
    }

    public function changeStatus(Request $request, Visit $visit)
    {
        $request->validate(['status'=>'required|in:scheduled,in_progress,done,cancelled']);
        $visit->update(['status'=>$request->status]);
        ActivityLog::log('visit','status_changed',"Status kunjungan: {$request->status}", $visit);
        return back()->with('success','Status kunjungan diperbarui.');
    }

    public function sendReminder(Request $request, Visit $visit)
    {
        app(NotificationService::class)->notifyVisitScheduled($visit);
        ActivityLog::log('visit','reminder',"Reminder dikirim untuk kunjungan #{$visit->id}", $visit);
        return back()->with('success','Reminder terkirim.');
    }

    public function attachTicket(Request $request, Visit $visit)
    {
        $data = $request->validate(['ticket_id' => 'required|exists:tickets,id']);
        $ticket = Ticket::find($data['ticket_id']);
        if (!$ticket || $ticket->client_id !== $visit->client_id) {
            return back()->withErrors(['ticket_id' => 'Tiket harus milik klien yang sama dengan kunjungan ini.']);
        }

        $visit->tickets()->syncWithoutDetaching([$ticket->id]);
        if (!$visit->ticket_id) {
            $visit->update(['ticket_id' => $ticket->id]);
        }

        ActivityLog::log('visit','ticket_added',"Tiket #{$ticket->ticket_number} ditambahkan ke kunjungan {$visit->visit_date->format('d/m/Y')}", $visit, [], ['ticket_id'=>$ticket->id]);
        ActivityLog::log('ticket','visit_assigned',"Tiket #{$ticket->ticket_number} ditautkan ke kunjungan {$visit->visit_date->format('d/m/Y')}", $ticket, [], ['visit_id'=>$visit->id]);

        return back()->with('success','Tiket berhasil ditambahkan ke kunjungan.');
    }

    public function destroy(Visit $visit)
    {
        $visit->delete();
        return redirect()->route('admin.visits.index')->with('success','Kunjungan dihapus.');
    }
}
