<?php

namespace Portal\Mileage\Http\Controllers;

use Portal\Mileage\Model\Users;
use Portal\Mileage\Model\Claim;
use Portal\Mileage\Model\Project;
use Portal\Mileage\Model\ProjectTeam;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;

class ProjectDirectorController extends Controller
{
    /**
     * Display the Project Director Dashboard (Monthly Filter View)
     */
    public function index(Request $request)
    {
        $director = Auth::user();
        $month = $request->input('month', Carbon::now()->format('Y-m'));

        // Validate month format
        try {
            if (!preg_match('/^\d{4}-\d{2}$/', $month)) {
                $month = now()->format('Y-m');
            }
            $parsedMonth = Carbon::createFromFormat('Y-m', $month);
        } catch (\Exception $e) {
            $month = now()->format('Y-m');
            $parsedMonth = Carbon::createFromFormat('Y-m', $month);
        }

        // Get project IDs under this Project Director
        $projectIds = ProjectTeam::where('pt_staff_id', $director->employeeCode)
            ->where('role_id', 7) // Project Director role
            ->pluck('fk_project_id');

        // Get projects under the PD
        $projects = Project::whereIn('id', $projectIds)->get();

        // Get claims for those projects in the selected month
        $claims = Claim::with(['user', 'project'])
            ->whereIn('project_id', $projectIds)
            ->whereMonth('claim_date', $parsedMonth->month)
            ->whereYear('claim_date', $parsedMonth->year)
            ->get();

        return view('mileage::projectDirector.index', compact('projects', 'claims', 'month'));
    }


    /**
     * Show all claims for one staff within a project for the selected month.
     */
    public function show($projectId, $userId, Request $request)
    {
        $month = $request->input('month', Carbon::now()->format('Y-m'));

        try {
            if (!preg_match('/^\d{4}-\d{2}$/', $month)) {
                $month = now()->format('Y-m');
            }
            $parsedMonth = Carbon::createFromFormat('Y-m', $month);
        } catch (\Exception $e) {
            $month = now()->format('Y-m');
            $parsedMonth = Carbon::createFromFormat('Y-m', $month);
        }

        $project = Project::findOrFail($projectId);
        $user = Users::findOrFail($userId);

        $claims = Claim::with(['project', 'jenisKenderaan'])
            ->where('project_id', $projectId)
            ->where('user_id', $userId)
            ->whereMonth('claim_date', $parsedMonth->month)
            ->whereYear('claim_date', $parsedMonth->year)
            ->orderBy('claim_date', 'asc')
            ->get();

        return view('mileage::projectDirector.show', compact('project', 'user', 'claims', 'month'));
    }


    /**
     * Approve all claims for a specific project in the selected month.
     */
    public function approveMonth(Request $request)
    {
        $director = Auth::user();
        $monthLabel = $request->input('month');
        $projectId = $request->input('project_id');

        // validate project_id presence
        if (!$projectId) {
            return back()->with('error', 'Sila pilih projek untuk disahkan.');
        }

        // validate month format
        try {
            if (!preg_match('/^\d{4}-\d{2}$/', $monthLabel)) {
                throw new \Exception('Invalid month format');
            }
            $parsedMonth = Carbon::createFromFormat('Y-m', $monthLabel);
        } catch (\Exception $e) {
            return back()->with('error', 'Format bulan tidak sah. Sila pilih semula bulan dalam format YYYY-MM.');
        }

        // ensure director actually oversees this project
        $allowedProjectIds = ProjectTeam::where('pt_staff_id', $director->employeeCode)
            ->where('role_id', 7)
            ->pluck('fk_project_id')
            ->toArray();

        if (!in_array($projectId, $allowedProjectIds)) {
            return back()->with('error', 'Anda tidak dibenarkan melakukan tindakan ini untuk projek terpilih.');
        }

        // update only claims that belong to this project and month and are Disokong
        $approvedCount = Claim::where('project_id', $projectId)
            ->whereMonth('claim_date', $parsedMonth->month)
            ->whereYear('claim_date', $parsedMonth->year)
            ->where('status', 'Disokong')
            ->update([
                'status' => 'Disahkan',
                'approved_by' => $director->id,
                'updated_at' => now(),
            ]);

        if ($approvedCount > 0) {
            return back()->with('success', $approvedCount . ' tuntutan telah disahkan untuk projek ini bagi bulan ' . $monthLabel . '.');
        }

        return back()->with('warning', 'Tiada tuntutan "Disokong" untuk disahkan bagi projek ini pada bulan ' . $monthLabel . '.');
    }

    /**
     * Reject all claims for a specific project in the selected month.
     */
    public function rejectMonth(Request $request)
    {
        $director = Auth::user();
        $monthLabel = $request->input('month');
        $projectId = $request->input('project_id');

        if (!$projectId) {
            return back()->with('error', 'Sila pilih projek untuk ditolak.');
        }

        // validate month format
        try {
            if (!preg_match('/^\d{4}-\d{2}$/', $monthLabel)) {
                throw new \Exception('Invalid month format');
            }
            $parsedMonth = Carbon::createFromFormat('Y-m', $monthLabel);
        } catch (\Exception $e) {
            return back()->with('error', 'Format bulan tidak sah. Sila pilih semula bulan dalam format YYYY-MM.');
        }

        // ensure director actually oversees this project
        $allowedProjectIds = ProjectTeam::where('pt_staff_id', $director->employeeCode)
            ->where('role_id', 7)
            ->pluck('fk_project_id')
            ->toArray();

        if (!in_array($projectId, $allowedProjectIds)) {
            return back()->with('error', 'Anda tidak dibenarkan melakukan tindakan ini untuk projek terpilih.');
        }
        $rejectReason = $request->input('reject_reason', 'Tiada sebab diberikan.');

        // update only claims that belong to this project and month and are Disokong
        $rejectedCount = Claim::where('project_id', $projectId)
            ->whereMonth('claim_date', $parsedMonth->month)
            ->whereYear('claim_date', $parsedMonth->year)
            ->where('status', 'Disokong')
            ->update([
                'status' => 'Ditolak',
                'rejected_by' => $director->id,
                'reject_reason' => $rejectReason,
                'updated_at' => now(),
            ]);


        return back()->with('warning', 'Tiada tuntutan "Disokong" untuk ditolak bagi projek ini pada bulan ' . $monthLabel . '.');
    }

    /**
     * Approve a single claim.
     */
    public function approveClaim($id, Request $request)
    {
        $director = Auth::user();
        $claim = Claim::findOrFail($id);

        // Ensure this director has access to the project
        $allowedProjectIds = ProjectTeam::where('pt_staff_id', $director->employeeCode)
            ->where('role_id', 7)
            ->pluck('fk_project_id')
            ->toArray();

        if (!in_array($claim->project_id, $allowedProjectIds)) {
            return back()->with('error', 'Anda tidak dibenarkan untuk meluluskan tuntutan ini.');
        }

        if ($claim->status !== 'Disokong') {
            return back()->with('warning', 'Tuntutan ini tidak berada dalam status Disokong.');
        }

        $claim->update([
            'status' => 'Disahkan',
            'approved_by' => $director->id,
            'updated_at' => now(),
        ]);

        return back()->with('success', 'Tuntutan pada ' . $claim->claim_date->format('d/m/Y') . ' telah disahkan.');
    }

    /**
     * Reject a single claim with reason.
     */
    public function rejectClaim($id, Request $request)
    {
        $director = Auth::user();
        $rejectReason = $request->input('reject_reason', 'Tiada sebab diberikan.');

        $claim = Claim::findOrFail($id);

        // Ensure this director has access to this project
        $allowedProjectIds = ProjectTeam::where('pt_staff_id', $director->employeeCode)
            ->where('role_id', 7)
            ->pluck('fk_project_id')
            ->toArray();

        if (!in_array($claim->project_id, $allowedProjectIds)) {
            return back()->with('error', 'Anda tidak dibenarkan menolak tuntutan ini.');
        }

        if ($claim->status !== 'Disokong') {
            return back()->with('warning', 'Tuntutan ini tidak berada dalam status Disokong.');
        }

        $claim->update([
            'status' => 'Ditolak',
            'rejected_by' => $director->id,
            'reject_reason' => $rejectReason,
            'updated_at' => now(),
        ]);

        return back()->with('success', 'Tuntutan telah ditolak dengan sebab: ' . $rejectReason);
    }

}
