<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Schema;
use Carbon\Carbon;

class SalesmanMobileVisitController extends Controller
{
    /**
     * 2. AMBIL RUTE JADWAL KUNJUNGAN HARI INI (MORNING SYNC - STATUS LOCK)
     */
    public function getTodayRoutes(Request $request)
    {
        $user = $request->user();
        
        // Bypass rute rutin untuk Supervisor (karena SPV hanya pakai Extra Call)
        if ($user->role === 'supervisor_sales') {
            return response()->json([
                'success' => true,
                'metadata' => [
                    'salesman_code' => 'SPV',
                    'date' => Carbon::now()->isoFormat('D MMMM YYYY'),
                    'day' => Carbon::now()->isoFormat('dddd')
                ],
                'data' => []
            ], 200);
        }

        $salesman = DB::table('salesmen')->where('user_id', $user->id)->first();
        if (!$salesman) {
            return response()->json(['success' => false, 'message' => 'Data Salesman tidak ditemukan.'], 404);
        }

        $dayOfWeekMap = ['Monday' => 1, 'Tuesday' => 2, 'Wednesday' => 3, 'Thursday' => 4, 'Friday' => 5, 'Saturday' => 6, 'Sunday' => 7];
        $currentDayName = Carbon::now()->format('l');
        $dayNum = $dayOfWeekMap[$currentDayName] ?? 1;

        $journeyPlans = DB::table('master_journey_plans')
            ->join('customers', 'master_journey_plans.customer_id', '=', 'customers.id')
            ->where('master_journey_plans.salesman_id', $salesman->id)
            ->where('master_journey_plans.day_of_week', $dayNum)
            ->where('master_journey_plans.is_active', 1)
            // PENAMBAHAN: Pastikan master plan tidak bocor lintas cabang
            ->where('customers.branch_id', $user->branch_id)
            ->select('customers.id as customer_id', 'customers.customer_code', 'customers.name as customer_name', 'customers.address')
            ->get();

        $formattedRoutes = [];
        $todayDate = Carbon::today()->toDateString();

        foreach ($journeyPlans as $plan) {
            $visitRecord = DB::table('salesman_visits')
                ->where('salesman_id', $salesman->id)
                ->where('customer_id', $plan->customer_id)
                ->where('visit_date', $todayDate)
                ->first();

            $status = 'pending';
            if ($visitRecord) {
                // LOGIKA FIX: Jika sudah ada waktu checkout, status wajib 'completed'
                if (!empty($visitRecord->check_out_time)) {
                    $status = 'completed';
                } elseif ($visitRecord->visit_status === 'check_in') {
                    $status = 'check_in';
                }
            }

            $formattedRoutes[] = [
                'customer_id' => $plan->customer_id,
                'customer_code' => $plan->customer_code,
                'customer_name' => $plan->customer_name,
                'address' => $plan->address ?? 'Alamat belum diatur',
                'status' => $status,
                'visit_id' => $visitRecord ? $visitRecord->id : null
            ];
        }

        return response()->json([
            'success' => true,
            'metadata' => [
                'salesman_code' => $salesman->id,
                'date' => Carbon::now()->isoFormat('D MMMM YYYY'),
                'day' => Carbon::now()->isoFormat('dddd')
            ],
            'data' => $formattedRoutes
        ], 200);
    }

    /**
     * TAHAP 2A: CHECK-IN KUNJUNGAN GPS KHUSUS MOBILE + GEO-FENCING INTEGRATION + TRACKER SPASIAL REALTIME
     */
    public function storeCheckIn(Request $request)
    {
        $request->validate([
            'customer_id' => 'required|exists:customers,id',
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
        ]);

        $user = $request->user();
        
        // Pengecekan entitas untuk TO/Canvas vs Supervisor
        $salesman = null;
        if ($user->role === 'salesman') {
            $salesman = DB::table('salesmen')->where('user_id', $user->id)->first();
            if (!$salesman) return response()->json(['success' => false, 'message' => 'Akses ditolak.'], 403);
        }

        // PENAMBAHAN: Validasi Keamanan API (Mencegah check-in ke toko cabang lain)
        $customer = DB::table('customers')->where('id', $request->customer_id)->first();
        if (!$customer || $customer->branch_id !== $user->branch_id) {
            return response()->json(['success' => false, 'message' => 'Toko tidak valid atau berada di luar wilayah cabang Anda.'], 403);
        }

        $today = Carbon::today()->toDateString();
        $targetSalesmanId = $salesman ? $salesman->id : $customer->salesman_id; // Jika SPV, gunakan ID salesman toko tersebut

        $existingVisit = DB::table('salesman_visits')
            ->where('salesman_id', $targetSalesmanId)
            ->where('customer_id', $request->customer_id)
            ->whereDate('visit_date', $today)
            ->first();

        if ($existingVisit && $user->role === 'salesman') {
            return response()->json(['success' => false, 'message' => 'Anda sudah melakukan check-in di toko ini hari ini.'], 400);
        }

        // ========================================================================
        // 庁 INTEGRASI MODUL POIN 2: UPDATE TRACKER KOORDINAT SPASIAL REALTIME SALESMEN
        // ========================================================================
        if ($salesman) {
            DB::table('salesmen')->where('id', $salesman->id)->update([
                'last_latitude' => $request->latitude,
                'last_longitude' => $request->longitude,
                'last_activity_at' => Carbon::now('Asia/Jakarta'), // Wajib sesuai zona waktu
                'updated_at' => Carbon::now('Asia/Jakarta')
            ]);
        }

        // ========================================================================
        // LOGIKA ENTERPRISE: VALIDASI TITIK KOORDINAT & PERHITUNGAN RADIUS 50M
        // ========================================================================
        $isOutOfRadius = false;
        $distanceMeters = 0;
        $isFirstLock = false;

        // A. Jika koordinat di master pelanggan masih kosong, kunci otomatis koordinat saat check-in pertama kali
        if (empty($customer->latitude) || empty($customer->longitude) || (float)$customer->latitude == 0 || (float)$customer->longitude == 0) {
            DB::table('customers')->where('id', $customer->id)->update([
                'latitude' => $request->latitude,
                'longitude' => $request->longitude,
                'updated_at' => Carbon::now()
            ]);
            $isFirstLock = true;
        } else {
            // B. Hitung Jarak Menggunakan Formula Haversine (Aman Murni Tanpa Plugin Eksternal)
            $earthRadius = 6371000; // Konstanta bumi dalam satuan Meter
            $latFrom = deg2rad((float)$customer->latitude);
            $lonFrom = deg2rad((float)$customer->longitude);
            $latTo = deg2rad((float)$request->latitude);
            $lonTo = deg2rad((float)$request->longitude);

            $latDelta = $latTo - $latFrom;
            $lonDelta = $lonTo - $lonFrom;

            $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) + cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
            $distanceMeters = $angle * $earthRadius;

            // C. Evaluasi Radius Batas Toleransi Enterprise (50 Meter)
            if ($distanceMeters > 50) {
                $isOutOfRadius = true;
            }
        }
        // ========================================================================

        $isScheduled = DB::table('master_journey_plans')
            ->where('salesman_id', $targetSalesmanId)
            ->where('customer_id', $request->customer_id)
            ->where('day_of_week', Carbon::today()->dayOfWeekIso)
            ->exists();

        // PERBAIKAN: Menghapus logika override 'supervisor_call' untuk mencegah error ENUM
        $insertData = [
            'salesman_id' => $targetSalesmanId, 
            'customer_id' => $request->customer_id,
            'visit_date' => $today,
            'visit_category' => $isScheduled ? 'scheduled' : 'extra_call',
            'visit_status' => 'check_in',
            'check_in_time' => Carbon::now('Asia/Jakarta'),
            'check_in_lat' => $request->latitude,
            'check_in_lng' => $request->longitude,
            'visit_result' => 'pending', 
            'created_at' => Carbon::now('Asia/Jakarta'),
            'updated_at' => Carbon::now('Asia/Jakarta'),
        ];

        // 庁 INTEGRASI MODUL POIN 1: PENGISIAN FIELD AUDIT GEOFENCE SECARA PERMANEN
        if (Schema::hasColumn('salesman_visits', 'is_out_of_radius')) {
            $insertData['is_out_of_radius'] = $isOutOfRadius ? 1 : 0;
        }
        if (Schema::hasColumn('salesman_visits', 'distance_meters')) {
            $insertData['distance_meters'] = round($distanceMeters, 2);
        }
        if (Schema::hasColumn('salesman_visits', 'verified_at')) {
            $insertData['verified_at'] = Carbon::now('Asia/Jakarta');
        }

        // Jika sudah ada (karena SPV check-in menimpa/melanjutkan sesi TO), gunakan ID yang ada
        if ($existingVisit) {
            $visitId = $existingVisit->id;
        } else {
            $visitId = DB::table('salesman_visits')->insertGetId($insertData);
        }

        // Kustomisasi pesan notifikasi interaktif ke aplikasi Flutter Salesman
        $responseMessage = 'Check-in berhasil. Selamat bertugas!';
        if ($isFirstLock) {
            $responseMessage = 'Check-in sukses! Titik koordinat master pelanggan ini berhasil dikunci untuk pertama kalinya.';
        } elseif ($isOutOfRadius) {
            $responseMessage = 'Check-in sukses! Peringatan: Anda berada ' . round($distanceMeters) . ' meter di luar jangkauan area toko (Log Audit Terkirim ke Pusat).';
        }

        return response()->json([
            'success' => true, 
            'message' => $responseMessage,
            'visit_id' => $visitId,
            'is_out_of_radius' => $isOutOfRadius,
            'distance_meters' => round($distanceMeters, 2)
        ], 201);
    }

    /**
     * TAHAP 2B: CHECK-OUT & UPLOAD FOTO (MANDATORY PHOTO) + TRACKER SPASIAL REALTIME
     */
    public function storeCheckOut(Request $request)
    {
        $request->validate([
            'visit_id' => 'required',
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
            'photo_proof' => 'required|image|max:3072', 
            'visit_result' => 'required|in:order,payment,order_and_payment,no_order',
            'no_order_reason_id' => 'required_if:visit_result,no_order|nullable|integer'
        ]);

        $user = $request->user();
        
        $visit = DB::table('salesman_visits')
            ->where('id', $request->visit_id)
            ->first();

        if (!$visit) return response()->json(['success' => false, 'message' => 'Sesi kunjungan tidak ditemukan.'], 404);
        
        $customer = DB::table('customers')->where('id', $visit->customer_id)->first();
        if (!$customer || $customer->branch_id !== $user->branch_id) {
            return response()->json(['success' => false, 'message' => 'Akses ditolak: Data kunjungan tidak valid atau pelanggan bukan dari cabang Anda.'], 403);
        }

        if ($visit->visit_status === 'completed') return response()->json(['success' => false, 'message' => 'Kunjungan ini sudah di-checkout.'], 400);

        if ($user->role === 'salesman') {
            $salesman = DB::table('salesmen')->where('user_id', $user->id)->first();
            if ($salesman) {
                DB::table('salesmen')->where('id', $salesman->id)->update([
                    'last_latitude' => $request->latitude,
                    'last_longitude' => $request->longitude,
                    'last_activity_at' => Carbon::now('Asia/Jakarta'),
                    'updated_at' => Carbon::now('Asia/Jakarta')
                ]);
            }
        }

        $photoPath = null;
        if ($request->hasFile('photo_proof')) {
            $file = $request->file('photo_proof');
            $prefixId = $user->role === 'supervisor_sales' ? 'SPV_' . $user->id : 'SLS_' . $visit->salesman_id;
            $filename = 'VISIT_PROOF_' . $prefixId . '_' . $visit->customer_id . '_' . time() . '.' . $file->getClientOriginalExtension();
            $photoPath = $file->storeAs('visit_proofs', $filename, 'public');
        }

        DB::table('salesman_visits')->where('id', $visit->id)->update([
            'visit_status' => 'completed',
            'check_out_time' => Carbon::now('Asia/Jakarta'),
            'check_out_lat' => $request->latitude,
            'check_out_lng' => $request->longitude,
            'photo_proof' => $photoPath,
            'visit_result' => $request->visit_result,
            'no_order_reason_id' => $request->visit_result === 'no_order' ? $request->no_order_reason_id : null,
            'no_order_reason' => null, 
            'updated_at' => Carbon::now('Asia/Jakarta'),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Check-out berhasil disimpan. Kunjungan Selesai!',
            'data' => [
                'visit_id' => $visit->id,
                'result' => $request->visit_result,
                'photo_url' => asset('storage/' . $photoPath)
            ]
        ], 200);
    }

    /**
     * AMBIL DAFTAR CONSUMER UNTUK EXTRA CALL (RBAC SUPERVISOR & SALES)
     */
    public function getExtraCustomers(Request $request)
    {
        $user = $request->user();
        $todayDate = Carbon::today()->toDateString();

        $customerQuery = DB::table('customers')
            ->where('branch_id', $user->branch_id) 
            ->where('is_active', 1);

        $targetSalesmanIds = [];

        if ($user->role === 'supervisor_sales') {
            $bawahanIds = DB::table('salesmen')->where('supervisor_id', $user->id)->pluck('id')->toArray();
            
            if (empty($bawahanIds)) {
                return response()->json(['success' => true, 'data' => []], 200);
            }
            
            $customerQuery->whereIn('salesman_id', $bawahanIds);
            $targetSalesmanIds = $bawahanIds;

        } elseif ($user->role === 'salesman') {
            $salesman = DB::table('salesmen')->where('user_id', $user->id)->first();
            if (!$salesman) {
                return response()->json(['success' => false, 'message' => 'Data Salesman tidak valid.'], 403);
            }

            $customerQuery->where('salesman_id', $salesman->id);
            $targetSalesmanIds = [$salesman->id];
        } else {
            return response()->json(['success' => false, 'message' => 'Role tidak berwenang.'], 403);
        }

        $allCustomers = $customerQuery
            ->select('id as customer_id', 'customer_code', 'name as customer_name', 'address', 'salesman_id')
            ->orderBy('name', 'asc')
            ->get();

        $visitedToday = DB::table('salesman_visits')
            ->whereIn('salesman_id', $targetSalesmanIds)
            ->where('visit_date', $todayDate)
            ->get()
            ->keyBy('customer_id');

        $formattedData = $allCustomers->map(function ($c) use ($visitedToday) {
            $hasVisit = $visitedToday->get($c->customer_id);
            
            $status = 'pending';
            if ($hasVisit) {
                if (!empty($hasVisit->check_out_time)) {
                    $status = 'completed';
                } elseif ($hasVisit->visit_status === 'check_in') {
                    $status = 'check_in';
                }
            }
            
            return [
                'customer_id' => $c->customer_id,
                'customer_code' => $c->customer_code,
                'customer_name' => $c->customer_name,
                'address' => $c->address ?? 'Alamat belum diatur',
                'status' => $status,
                'visit_id' => $hasVisit ? $hasVisit->id : null,
                'salesman_id' => $c->salesman_id 
            ];
        });

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

    /**
     * FETCH DATA MASTER ALASAN NO-ORDER UNTUK DROPDOWN MOBILE FLUTTER
     */
    public function getNoOrderReasons(Request $request)
    {
        try {
            $reasons = DB::table('no_order_reasons')
                ->where('is_active', 1)
                ->select('id', 'reason_name')
                ->orderBy('id', 'asc')
                ->get();

            return response()->json([
                'success' => true,
                'data' => $reasons
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Gagal memuat opsi alasan penolakan: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * AMBIL DAFTAR PIUTANG TOKO UNTUK DITAGIH
     */
    public function getCustomerUnpaidInvoices(Request $request, $customerId)
    {
        try {
            $user = $request->user();

            $customerCheck = DB::table('customers')->where('id', $customerId)->first();
            if (!$customerCheck || $customerCheck->branch_id !== $user->branch_id) {
                return response()->json(['success' => false, 'message' => 'Akses ditolak: Pelanggan ini berada di luar cabang Anda.'], 403);
            }

            $invoices = DB::table('sales')
                ->where('customer_id', $customerId)
                ->where('branch_id', $user->branch_id)
                ->whereIn('payment_status', ['pending', 'partial'])
                ->select('id', 'invoice_number', 'grand_total', 'paid_amount', 'due_date')
                ->orderBy('created_at', 'asc')
                ->get()
                ->map(function($inv) {
                    $inv->outstanding = $inv->grand_total - $inv->paid_amount;
                    return $inv;
                })
                ->filter(function($inv) {
                    return $inv->outstanding > 0; 
                })->values();

            return response()->json(['success' => true, 'data' => $invoices], 200);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Gagal memuat piutang: ' . $e->getMessage()], 500);
        }
    }

    /**
     * SUBMIT KUNJUNGAN + PENAGIHAN (MENDUKUNG UPLOAD BUKTI MULTIPART)
     */
    public function submitVisitWithPayment(Request $request)
    {
        $request->validate([
            'visit_id' => 'required|exists:salesman_visits,id',
            'visit_result' => 'required|in:order,payment,order_and_payment,no_order',
            'latitude_out' => 'required',
            'longitude_out' => 'required',
            'no_order_reason_id' => 'nullable|required_if:visit_result,no_order',
            'payments' => 'nullable|array',
            'payments.*.sale_id' => 'required_with:payments|exists:sales,id',
            'payments.*.amount' => 'required_with:payments|numeric|min:1',
            'payments.*.payment_method' => 'required_with:payments|in:cash,transfer,giro',
        ]);

        DB::beginTransaction();
        try {
            $user = auth()->user();

            $visitRecord = DB::table('salesman_visits')->where('id', $request->visit_id)->first();
            if (!$visitRecord) {
                throw new \Exception("Akses ditolak: Data kunjungan tidak valid.");
            }

            DB::table('salesman_visits')->where('id', $request->visit_id)->update([
                'visit_result' => $request->visit_result,
                'no_order_reason_id' => $request->no_order_reason_id,
                'check_out_time' => Carbon::now(),
                'check_out_lat' => $request->latitude_out,
                'check_out_lng' => $request->longitude_out,
                'visit_status' => 'completed',
                'updated_at' => Carbon::now()
            ]);

            if (in_array($request->visit_result, ['payment', 'order_and_payment']) && $request->has('payments')) {
                
                foreach ($request->payments as $index => $payData) {
                    $sale = DB::table('sales')->where('id', $payData['sale_id'])->first();
                    
                    if (!$sale || $sale->branch_id !== $user->branch_id) {
                        throw new \Exception("Data tagihan tidak valid atau bukan kewenangan cabang Anda.");
                    }

                    $proofPath = null;
                    if ($request->hasFile("payments.{$index}.proof_image")) {
                        $proofPath = $request->file("payments.{$index}.proof_image")->store('payment_proofs', 'public');
                    }

                    $paymentStatus = 'completed'; 
                    $giroStatus = 'cleared';
                    
                    if ($payData['payment_method'] === 'cash') {
                        $paymentStatus = 'pending'; 
                    } elseif ($payData['payment_method'] === 'transfer') {
                        $paymentStatus = 'pending'; 
                    } elseif ($payData['payment_method'] === 'giro') {
                        $paymentStatus = 'pending'; 
                        $giroStatus = 'pending'; 
                    }

                    DB::table('debt_payments')->insert([
                        'sale_id' => $sale->id,
                        'branch_id' => $sale->branch_id,
                        'user_id' => $user->id,
                        'visit_id' => $request->visit_id, 
                        'amount' => $payData['amount'],
                        'account_id' => null, 
                        'payment_method' => $payData['payment_method'],
                        'payment_type' => 'receivable',
                        'payment_status' => $paymentStatus, 
                        'giro_number' => $payData['giro_number'] ?? null,
                        'giro_due_date' => $payData['giro_due_date'] ?? null,
                        'giro_status' => $giroStatus,
                        'proof_image_path' => $proofPath,
                        'note' => 'Ditagih via Mobile ERP',
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now()
                    ]);
                }
            }

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Check-out berhasil! Data kunjungan & penagihan telah tersimpan.']);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => 'Gagal check-out: ' . $e->getMessage()], 500);
        }
    }
}