<?php

namespace Portal\Mileage\Http\Controllers;

use Portal\Mileage\Model\Users;
use Portal\Mileage\Model\Claim;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Carbon\Carbon;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Portal\Mileage\Exports\ClaimsExport;

class FinanceController extends Controller
{
    public function index(Request $request)
    {
        $month = $request->get('month', Carbon::now()->format('Y-m'));
        $parsedMonth = Carbon::parse($month);

        $claims = Claim::with(['user', 'project'])
            ->whereIn('status', ['Disahkan', 'Disokong', 'Disemak', 'Diproses', 'Ditolak', 'Dibayar'])
            ->whereMonth('claim_date', $parsedMonth->month)
            ->whereYear('claim_date', $parsedMonth->year)
            ->get();

        $summary = [
            'processed' => $claims->where('status', 'Diproses')->count(),
            'verified'  => $claims->where('status', 'Disokong')->count(),
            'approved'  => $claims->where('status', 'Disahkan')->count(),
            'reviewed'  => $claims->where('status', 'Disemak')->count(),
            'paid'      => $claims->where('status', 'Dibayar')->count(),
            'rejected'  => $claims->where('status', 'Ditolak')->count(),
        ];

        $users = $claims
            ->groupBy('user_id')
            ->map(function ($userClaims) {
                $user = $userClaims->first()->user;
                return [
                    'id' => $user->id ?? null,
                    'name' => $user->name ?? '-',
                    'total_claims' => $userClaims->count(),
                    'total_amount' => $userClaims->sum('total_claim_amount'),
                ];
            })
            ->sortBy('name')
            ->values();

        return view('mileage::finance.index', compact('users', 'summary', 'month'));
    }

    public function show($userId, Request $request)
{
    $month = $request->get('month', Carbon::now()->format('Y-m'));
    $parsedMonth = Carbon::parse($month);

    $user = Users::findOrFail($userId);
    $claims = Claim::with(['project', 'jenisKenderaan'])
        ->where('user_id', $userId)
        ->whereMonth('claim_date', $parsedMonth->month)
        ->whereYear('claim_date', $parsedMonth->year)
        ->get();

    // === Calculate per-claim penalty (same formula as HOD/BOD) ===
    $totalPenalty = 0;
    $isBOD = false;
    $penaltyBreakdown = [];

    foreach ($claims as $claim) {
        $claimDate = Carbon::parse($claim->claim_date);
        $submissionDate = $claim->created_at ?? Carbon::now();
        $daysDiff = $claimDate->diffInDays($submissionDate);

        $claimableMileage = max(0, ($claim->total_mileage ?? 0) - 40);
        if ($claim->jenis_kenderaan_id == 1) {
            $rate = ($claimableMileage <= 500) ? 0.55 : 0.50;
        } else {
            $rate = 0.30;
        }
        $claimMileageAmount = round($claimableMileage * $rate, 2);

        if ($daysDiff <= 30) {
            $penaltyRate = 0;
            $penaltyLabel = 'Tiada penalti (≤ 1 bulan)';
        } elseif ($daysDiff <= 90) {
            $penaltyRate = 0.10;
            $penaltyLabel = 'Lewat hantar >1 ≤3 bulan (10%)';
        } elseif ($daysDiff <= 180) {
            $penaltyRate = 0.30;
            $penaltyLabel = 'Lewat hantar >3 ≤6 bulan (30%)';
        } else {
            $penaltyRate = 'BOD';
            $penaltyLabel = 'Tertakluk kepada BOD';
            $isBOD = true;
        }

        $claimPenalty = $penaltyRate === 'BOD' ? 0 : round($claimMileageAmount * $penaltyRate, 2);
        $totalPenalty += $claimPenalty;

        $penaltyBreakdown[] = [
            'claim_date' => $claim->claim_date,
            'penalty'    => $claimPenalty,
            'label'      => $penaltyLabel,
        ];
    }

    return view('mileage::finance.show', compact(
        'user', 'claims', 'month',
        'totalPenalty', 'isBOD', 'penaltyBreakdown'
    ));
}


    public function viewEach($id)
    {
        $claim = Claim::with(['user', 'project', 'jenisKenderaan'])->findOrFail($id);
        return view('mileage::finance.view', compact('claim'));
    }

    public function update(Request $request, $id)
    {
        $claim = Claim::findOrFail($id);

        $validated = $request->validate([
            'claim_date' => 'required|date',
            'distance_from' => 'required|string|max:255',
            'distance_to' => 'required|string|max:255',
            'description' => 'required|string|max:255',
            'total_mileage' => 'required|numeric|min:0',
            'toll_amount' => 'nullable|numeric|min:0',
            'others_amount' => 'nullable|numeric|min:0',
            'others_details' => 'nullable|string|max:255',
        ]);

        if (($request->others_amount ?? 0) > 0 && empty($request->others_details)) {
            return back()->with('error', 'Butiran lain-lain perlu diisi apabila jumlah lain-lain melebihi 0.');
        }

        $claim->update([
            'claim_date'     => $validated['claim_date'],
            'distance_from'  => $validated['distance_from'],
            'distance_to'    => $validated['distance_to'],
            'description'    => $validated['description'],
            'total_mileage'  => $validated['total_mileage'],
            'toll_amount'    => $validated['toll_amount'] ?? 0,
            'others_amount'  => $validated['others_amount'] ?? 0,
            'others_details' => $validated['others_details'] ?? null,
            'updated_at'     => now(),
        ]);

        $vehicleType = strtolower($claim->jenisKenderaan->name ?? 'kereta');
        $mileage = $claim->total_mileage ?? 0;
        $rateCar1 = 0.55;
        $rateCar2 = 0.50;
        $rateMoto = 0.30;

        if (in_array($vehicleType, ['motosikal', 'motorcycle'])) {
            $mileageAmount = $mileage * $rateMoto;
        } else {
            $firstPart  = min($mileage, 500);
            $secondPart = max(0, $mileage - 500);
            $mileageAmount = ($firstPart * $rateCar1) + ($secondPart * $rateCar2);
        }

        $claim->calculated_amount = $mileageAmount + ($claim->toll_amount ?? 0) + ($claim->others_amount ?? 0);
        $claim->save();

        return back()->with('success', 'Maklumat tuntutan telah berjaya dikemaskini.');
    }

    public function updateStatus(Request $request, $id)
    {
        $claim = Claim::findOrFail($id);
        $action = $request->input('action');

        if (!in_array($action, ['Disemak', 'Ditolak', 'Dibayar'])) {
            return back()->with('error', 'Tindakan tidak sah.');
        }

        if (in_array($claim->status, ['Disemak', 'Ditolak', 'Dibayar'])) {
            return back()->with('error', 'Tuntutan ini telah disemak atau dimuktamadkan.');
        }

        // update status and reviewer
        $claim->update([
            'status' => $action,
            'reviewed_by' => auth()->id(), // ✅ log who reviewed the claim
        ]);

        return back()->with('success', "Tuntutan telah dikemaskini kepada status {$action}.");
    }

    public function export(Request $request)
    {
        $month = $request->input('month');
        $userId = $request->input('user_id');
        $parsedMonth = $month ? Carbon::parse($month) : Carbon::now();

        $query = Claim::with(['user', 'project', 'approvedBy', 'reviewedBy'])
            ->where('status', 'Disemak')
            ->whereMonth('claim_date', $parsedMonth->month)
            ->whereYear('claim_date', $parsedMonth->year)
            ->orderBy('claim_date', 'asc');

        if (!empty($userId)) {
            $query->where('user_id', $userId);
        }

        $claims = Claim::with(['user', 'project', 'approvedBy', 'reviewedBy'])
            ->whereMonth('claim_date', $parsedMonth->month)
            ->whereYear('claim_date', $parsedMonth->year)
            ->where('status', 'Disemak')
            ->get();

        $user = $claims->first()->user ?? null;

        if ($claims->isEmpty()) {
            return back()->with('error', 'Tiada tuntutan dijumpai untuk bulan ini.');
        }

        $fileName = !empty($userId)
            ? 'Laporan_Tuntutan_' . str_replace(' ', '_', $user->name) . '_' . $parsedMonth->format('m-Y') . '.xlsx'
            : 'Laporan_Tuntutan_Semua_Staf_' . $parsedMonth->format('m-Y') . '.xlsx';

        $excelData = Excel::raw(new ClaimsExport($user, $claims), \Maatwebsite\Excel\Excel::XLSX);

        return new StreamedResponse(
            function () use ($excelData) {
                echo $excelData;
            },
            200,
            [
                'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'Content-Disposition' => 'inline; filename="' . $fileName . '"',
            ]
        );
    }
}
