<?php

namespace App\Services;

use App\Models\Complaint;
use App\Models\Dispatch;
use App\Models\DispatchUnit;
use App\Models\Officer;
use App\Models\Polsek;
use App\Services\NotificationService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class DispatchService
{
    public function __construct(
        private NotificationService $notificationService
    ) {}

    /**
     * Auto-dispatch complaint
     */
    public function autoDispatch(Complaint $complaint): ?Dispatch
    {
        DB::beginTransaction();
        
        try {
            // Find responsible Polsek
            $polsek = $this->findResponsiblePolsek($complaint);
            
            if (!$polsek) {
                Log::warning("No responsible Polsek found for complaint {$complaint->id}");
                return null;
            }

            // Get recommended unit type
            $classificationService = new ComplaintClassificationService();
            $disposition = $classificationService->getRecommendedDisposition($complaint->category);
            $unitType = $disposition['unit_type'] ?? 'samapta';

            // Create dispatch
            $dispatch = Dispatch::create([
                'complaint_id' => $complaint->id,
                'polsek_id' => $polsek->id,
                'unit_type' => $unitType,
                'status' => 'pending',
                'instructions' => $this->generateInstructions($complaint),
                'dispatcher_id' => $complaint->operator_id,
                'dispatched_at' => now(),
            ]);

            // Assign officers
            $this->assignOfficers($dispatch, $unitType, $polsek->id);

            // Send notifications
            $this->notificationService->sendDispatchNotification($dispatch);

            // Coordinate with external agencies if needed
            if (!empty($disposition['external_agencies'])) {
                $this->coordinateExternal($complaint, $disposition['external_agencies']);
            }

            // Update complaint status
            $complaint->update([
                'status' => 'dispatched',
                'dispatched_at' => now(),
                'polsek_id' => $polsek->id,
            ]);

            DB::commit();
            
            return $dispatch;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error("Auto-dispatch failed: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Find responsible Polsek
     */
    private function findResponsiblePolsek(Complaint $complaint): ?Polsek
    {
        if ($complaint->polsek_id) {
            return Polsek::find($complaint->polsek_id);
        }

        if ($complaint->location) {
            $locationService = new LocationTrackingService();
            return $locationService->findResponsiblePolsek($complaint->location);
        }

        // Fallback: find by regency/district from location
        if ($complaint->location && $complaint->location->regency) {
            return Polsek::where('regency', 'like', '%' . $complaint->location->regency . '%')
                ->where('is_active', true)
                ->first();
        }

        return null;
    }

    /**
     * Assign officers to dispatch
     */
    private function assignOfficers(Dispatch $dispatch, string $unitType, int $polsekId): void
    {
        // Find available officers
        $officers = Officer::where('polsek_id', $polsekId)
            ->where('unit_type', $unitType)
            ->where('status', 'available')
            ->where('is_active', true)
            ->limit(3) // Assign up to 3 officers
            ->get();

        foreach ($officers as $officer) {
            DispatchUnit::create([
                'dispatch_id' => $dispatch->id,
                'officer_id' => $officer->id,
                'status' => 'assigned',
                'assigned_at' => now(),
            ]);

            // Update officer status
            $officer->update(['status' => 'busy']);

            // Send notification to officer
            $this->notificationService->sendToOfficer($officer, $dispatch);
        }
    }

    /**
     * Generate instructions for dispatch
     */
    private function generateInstructions(Complaint $complaint): string
    {
        $instructions = "Aduan: {$complaint->description}\n";
        
        if ($complaint->location) {
            $instructions .= "Lokasi: {$complaint->location->address}\n";
            $instructions .= "Koordinat: {$complaint->location->latitude}, {$complaint->location->longitude}\n";
        }

        if ($complaint->caller_name) {
            $instructions .= "Pelapor: {$complaint->caller_name}\n";
        }

        if ($complaint->caller_phone) {
            $instructions .= "Kontak: {$complaint->caller_phone}\n";
        }

        return $instructions;
    }

    /**
     * Coordinate with external agencies
     */
    private function coordinateExternal(Complaint $complaint, array $agencies): void
    {
        foreach ($agencies as $agency) {
            $complaint->coordinations()->create([
                'type' => 'external',
                'external_type' => $agency,
                'message' => "Koordinasi untuk aduan: {$complaint->description}",
                'status' => 'pending',
            ]);
        }
    }

    /**
     * Escalate dispatch
     */
    public function escalate(Dispatch $dispatch, string $reason): void
    {
        $dispatch->update([
            'escalation_level' => $dispatch->escalation_level + 1,
            'escalation_reason' => $reason,
            'status' => 'escalated',
        ]);

        // Notify higher level (Polres or Polda)
        $this->notificationService->sendEscalationNotification($dispatch);
    }
}
