<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Location;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class LocationController extends Controller
{
    /**
     * Get list of locations
     * Unified endpoint untuk semua lokasi (office + business trip destinations)
     */
    public function index(Request $request): JsonResponse
    {
        $user = $request->user();
        $query = Location::active();

        // Filter by user's company
        if ($user && $user->company_id) {
            $query->forCompany($user->company_id);
        }

        // Filter by category (internal/external)
        if ($request->has('category')) {
            $query->where('category', $request->category);
        }

        // Filter by type (headquarters, branch, bpkp, pemda, etc.)
        if ($request->has('type')) {
            $types = is_array($request->type) ? $request->type : [$request->type];
            $query->ofTypes($types);
        }

        // Filter by allow_daily_checkin
        if ($request->boolean('daily_checkin_only', false)) {
            $query->offices();
        }

        // Filter by allow_business_trip
        if ($request->boolean('business_trip_only', false)) {
            $query->businessTripDestinations();
        }

        // Filter by province
        if ($request->has('province')) {
            $query->where('province', $request->province);
        }

        // Filter by city
        if ($request->has('city')) {
            $query->where('city', $request->city);
        }

        // Search by name
        if ($request->has('search')) {
            $query->where('name', 'like', '%' . $request->search . '%');
        }

        $locations = $query->select([
            'id',
            'name',
            'code',
            'category',
            'type',
            'address',
            'city',
            'province',
            'latitude',
            'longitude',
            'radius',
            'allow_daily_checkin',
            'allow_business_trip',
        ])->get();

        return response()->json([
            'success' => true,
            'data' => $locations,
        ]);
    }

    /**
     * Get single location
     */
    public function show(Location $location): JsonResponse
    {
        return response()->json([
            'success' => true,
            'data' => $location,
        ]);
    }

    /**
     * Create a new location (admin only)
     */
    public function store(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user->hasRole(['admin', 'super_admin'])) {
            return response()->json([
                'success' => false,
                'message' => 'Hanya admin yang dapat membuat lokasi',
            ], 403);
        }

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'code' => 'nullable|string|max:50',
            'address' => 'nullable|string',
            'city' => 'nullable|string|max:100',
            'province' => 'nullable|string|max:100',
            'latitude' => 'nullable|numeric|between:-90,90',
            'longitude' => 'nullable|numeric|between:-180,180',
            'radius' => 'nullable|integer|min:10|max:10000',
            'category' => 'required|in:internal,external',
            'type' => 'required|string|max:50',
            'allow_daily_checkin' => 'sometimes|boolean',
            'allow_business_trip' => 'sometimes|boolean',
            'is_primary' => 'sometimes|boolean',
            'is_active' => 'sometimes|boolean',
        ]);

        $validated['company_id'] = $user->company_id;

        try {
            $location = Location::create($validated);

            return response()->json([
                'success' => true,
                'message' => 'Lokasi berhasil dibuat',
                'data' => $location,
            ], 201);
        } catch (\Exception $e) {
            \Log::error('Location store error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Gagal membuat lokasi: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Update a location (admin only)
     */
    public function update(Request $request, Location $location): JsonResponse
    {
        $user = $request->user();

        if (!$user->hasRole(['admin', 'super_admin'])) {
            return response()->json([
                'success' => false,
                'message' => 'Hanya admin yang dapat mengubah lokasi',
            ], 403);
        }

        if ($location->company_id !== $user->company_id && !$user->hasRole('super_admin')) {
            return response()->json([
                'success' => false,
                'message' => 'Lokasi tidak ditemukan',
            ], 404);
        }

        $validated = $request->validate([
            'name' => 'sometimes|string|max:255',
            'code' => 'nullable|string|max:50',
            'address' => 'nullable|string',
            'city' => 'nullable|string|max:100',
            'province' => 'nullable|string|max:100',
            'latitude' => 'nullable|numeric|between:-90,90',
            'longitude' => 'nullable|numeric|between:-180,180',
            'radius' => 'nullable|integer|min:10|max:10000',
            'category' => 'sometimes|in:internal,external',
            'type' => 'sometimes|string|max:50',
            'allow_daily_checkin' => 'sometimes|boolean',
            'allow_business_trip' => 'sometimes|boolean',
            'is_primary' => 'sometimes|boolean',
            'is_active' => 'sometimes|boolean',
        ]);

        try {
            $location->update($validated);

            return response()->json([
                'success' => true,
                'message' => 'Lokasi berhasil diperbarui',
                'data' => $location->fresh(),
            ]);
        } catch (\Exception $e) {
            \Log::error('Location update error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Gagal memperbarui lokasi: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get nearby locations sorted by distance
     */
    public function nearby(Request $request): JsonResponse
    {
        $request->validate([
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
            'limit' => 'nullable|integer|min:1|max:50',
        ]);

        $user = $request->user();
        $latitude = (float) $request->latitude;
        $longitude = (float) $request->longitude;
        $limit = $request->integer('limit', 5);

        $allowDailyCheckin = $request->has('daily_checkin_only')
            ? $request->boolean('daily_checkin_only')
            : null;

        $allowBusinessTrip = $request->has('business_trip_only')
            ? $request->boolean('business_trip_only')
            : null;

        $locations = Location::getNearbyLocations(
            $user->company_id,
            $latitude,
            $longitude,
            $limit,
            $allowDailyCheckin,
            $allowBusinessTrip
        );

        return response()->json([
            'success' => true,
            'data' => $locations->map(function ($loc) {
                return [
                    'id' => $loc->id,
                    'name' => $loc->name,
                    'code' => $loc->code,
                    'category' => $loc->category,
                    'category_label' => $loc->getCategoryLabel(),
                    'type' => $loc->type,
                    'type_label' => $loc->getTypeLabel(),
                    'address' => $loc->address,
                    'city' => $loc->city,
                    'province' => $loc->province,
                    'latitude' => $loc->latitude,
                    'longitude' => $loc->longitude,
                    'radius' => $loc->radius,
                    'distance' => $loc->distance,
                    'is_within_radius' => $loc->distance <= $loc->radius,
                    'allow_daily_checkin' => $loc->allow_daily_checkin,
                    'allow_business_trip' => $loc->allow_business_trip,
                ];
            }),
        ]);
    }

    /**
     * Get locations for daily check-in (offices)
     */
    public function offices(Request $request): JsonResponse
    {
        $user = $request->user();
        $query = Location::active()
            ->forCompany($user->company_id)
            ->offices();

        // Search by name
        if ($request->has('search')) {
            $query->where('name', 'like', '%' . $request->search . '%');
        }

        $locations = $query->get();

        return response()->json([
            'success' => true,
            'data' => $locations,
        ]);
    }

    /**
     * Get locations for business trip
     */
    public function businessTripDestinations(Request $request): JsonResponse
    {
        $user = $request->user();
        $query = Location::active()
            ->forCompany($user->company_id)
            ->businessTripDestinations();

        // Filter by type (bpkp, pemda, etc.)
        if ($request->has('type')) {
            $query->where('type', $request->type);
        }

        // Filter by province
        if ($request->has('province')) {
            $query->where('province', $request->province);
        }

        // Filter by city
        if ($request->has('city')) {
            $query->where('city', $request->city);
        }

        // Search by name
        if ($request->has('search')) {
            $query->where('name', 'like', '%' . $request->search . '%');
        }

        $locations = $query->get();

        return response()->json([
            'success' => true,
            'data' => $locations,
        ]);
    }

    /**
     * Get recommended locations for business trip by province/city
     */
    public function recommendations(Request $request): JsonResponse
    {
        $request->validate([
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
            'province' => 'required|string',
            'city' => 'nullable|string',
        ]);

        $user = $request->user();
        $latitude = (float) $request->latitude;
        $longitude = (float) $request->longitude;
        $province = $request->province;
        $city = $request->city;

        // BPKP di provinsi tersebut
        $bpkpLocations = Location::active()
            ->forCompany($user->company_id)
            ->where('type', 'bpkp')
            ->where('province', $province)
            ->businessTripDestinations()
            ->get()
            ->map(function ($loc) use ($latitude, $longitude) {
                $loc->distance = (int) $loc->distanceFrom($latitude, $longitude);
                return $loc;
            })
            ->sortBy('distance')
            ->values();

        // Pemda di kota tersebut
        $pemdaLocations = collect();
        if ($city) {
            $pemdaLocations = Location::active()
                ->forCompany($user->company_id)
                ->where('type', 'pemda')
                ->where('city', $city)
                ->businessTripDestinations()
                ->get()
                ->map(function ($loc) use ($latitude, $longitude) {
                    $loc->distance = (int) $loc->distanceFrom($latitude, $longitude);
                    return $loc;
                })
                ->sortBy('distance')
                ->values();
        }

        return response()->json([
            'success' => true,
            'data' => [
                'bpkp' => $bpkpLocations,
                'pemda' => $pemdaLocations,
            ],
        ]);
    }
}
