<?php

namespace App\Http\Controllers;

use App\Models\TimeEntry;
use App\Models\StaffTaskType;
use App\Models\Job;
use App\Models\JobEmployeeTaskAssignment;
use Illuminate\Http\Request;
use Carbon\Carbon;

class TimesheetController extends Controller
{
    public function index()
    {
        $user        = auth()->user();
        $isTrades    = $user->role?->name === 'trades';
        $isProcessor = $user->role?->name === 'processor';
        $isEmployee  = $user->role?->name === 'factory_employee';

        if ($isProcessor) {
            $taskTypes = StaffTaskType::where('is_active', true)->where('task_category', 'processor')->orderBy('name')->get();
        } elseif ($isEmployee) {
            $taskTypes = StaffTaskType::where('is_active', true)->where('task_category', 'employee')->orderBy('name')->get();
        } else {
            $taskTypes = StaffTaskType::where('is_active', true)->orderBy('name')->get();
        }

        // For factory_employee: only show jobs where they have assigned tasks
        if ($isEmployee) {
            $assignedJobIds = JobEmployeeTaskAssignment::where('user_id', $user->id)->where('task_status', '!=', 'completed')
                ->pluck('job_id')
                ->unique();

            $jobs = Job::with(['contact'])
                ->whereIn('id', $assignedJobIds)
                ->where('stage', 'processing')
                ->orderBy('job_number')
                ->get();

            // Build a map of job_id -> [task_type_id, ...] for dynamic filtering in the view
            $assignments = JobEmployeeTaskAssignment::where('user_id', $user->id)->where('task_status', '!=', 'completed')
                ->whereIn('job_id', $assignedJobIds)
                ->with('taskType', 'job.contact')
                ->orderBy('id', 'desc')
                ->get();

            $jobTaskMap = [];
            foreach ($assignments as $a) {
                $jobTaskMap[$a->job_id][] = $a->task_type_id;
            }

            // All employee task types as array for JS
            $allTaskTypesJson = $taskTypes->map(fn($t) => ['id' => $t->id, 'name' => $t->name])->values();

        } elseif ($isTrades) {
            $jobs = $user->assignedJobs()
                ->where('status', '!=', 'completed')
                ->orderBy('job_number')
                ->get();
            $assignments      = collect();
            $jobTaskMap       = null;
            $allTaskTypesJson = null;
        } elseif ($isProcessor) {
            $jobs = Job::with(['contact', 'consultant', 'manager'])
                ->whereHas('checkMeasures', fn($q) => $q->where('status', 'completed'))
                ->where('stage', 'processing')
                ->orderBy('job_number', 'desc')
                ->get();
            $assignments      = collect();
            $jobTaskMap       = null;
            $allTaskTypesJson = null;
        } else {
            $jobs = Job::whereIn('status', ['active'])->orderBy('job_number')->get();
            $assignments      = collect();
            $jobTaskMap       = null;
            $allTaskTypesJson = null;
        }

        // Running timer — first one for non-employee compat (e.g. the header ticker)
        $running = TimeEntry::where('user_id', $user->id)
            ->where('status', 'running')
            ->with('taskType', 'job')
            ->first();

        // All running timers — used by factory_employee multi-timer view
        $runningEntries = TimeEntry::where('user_id', $user->id)
            ->where('status', 'running')
            ->with('taskType', 'job')
            ->get();

        // Paused entries (most recent per job+task combo) — so employee can resume
        $pausedEntries = TimeEntry::where('user_id', $user->id)
            ->where('status', 'paused')
            ->with('taskType', 'job')
            ->orderByDesc('stopped_at')
            ->get();

        // Recent entries
        $entries = TimeEntry::where('user_id', $user->id)
            ->with('taskType', 'job')
            ->orderByDesc('started_at')
            ->paginate(20);

        // Weekly summary — include both paused and completed in totals
        $weekStart     = Carbon::now()->startOfWeek();
        $weeklyEntries = TimeEntry::where('user_id', $user->id)
            ->where('started_at', '>=', $weekStart)
            ->whereIn('status', ['paused', 'completed'])
            ->get();
        $weeklyHours    = $weeklyEntries->sum('duration_minutes') / 60;
        $weeklyEarnings = $weeklyHours * ($user->hourly_rate ?? 0);

        $statuscompleted = false;

        return view('timesheet.index', compact(
            'taskTypes', 'jobs', 'running', 'runningEntries', 'entries', 'weeklyHours', 'weeklyEarnings',
            'jobTaskMap', 'allTaskTypesJson', 'assignments', 'pausedEntries', 'statuscompleted'
        ));
    }

    public function timesheetemployeecompleted()
    {
        $user        = auth()->user();
        $isTrades    = $user->role?->name === 'trades';
        $isProcessor = $user->role?->name === 'processor';
        $isEmployee  = $user->role?->name === 'factory_employee';

        if ($isProcessor) {
            $taskTypes = StaffTaskType::where('is_active', true)->where('task_category', 'processor')->orderBy('name')->get();
        } elseif ($isEmployee) {
            $taskTypes = StaffTaskType::where('is_active', true)->where('task_category', 'employee')->orderBy('name')->get();
        } else {
            $taskTypes = StaffTaskType::where('is_active', true)->orderBy('name')->get();
        }

        // For factory_employee: only show jobs where they have assigned tasks
        if ($isEmployee) {
            $assignedJobIds = JobEmployeeTaskAssignment::where('user_id', $user->id)
                ->where('task_status', 'completed')
                ->pluck('job_id')
                ->unique();

            $jobs = Job::with(['contact'])
                ->whereIn('id', $assignedJobIds)
                ->where('stage', 'processing')
                ->orderBy('job_number')
                ->get();

            // Build a map of job_id -> [task_type_id, ...] for dynamic filtering in the view
            $assignments = JobEmployeeTaskAssignment::where('user_id', $user->id)
                ->where('task_status', 'completed')
                ->whereIn('job_id', $assignedJobIds)
                ->with('taskType', 'job.contact')
                ->orderBy('id', 'desc')
                ->get();

            $jobTaskMap = [];
            foreach ($assignments as $a) {
                $jobTaskMap[$a->job_id][] = $a->task_type_id;
            }

            // All employee task types as array for JS
            $allTaskTypesJson = $taskTypes->map(fn($t) => ['id' => $t->id, 'name' => $t->name])->values();

        } elseif ($isTrades) {
            $jobs = $user->assignedJobs()
                ->where('status', '!=', 'completed')
                ->orderBy('job_number')
                ->get();
            $assignments      = collect();
            $jobTaskMap       = null;
            $allTaskTypesJson = null;
        } elseif ($isProcessor) {
            $jobs = Job::with(['contact', 'consultant', 'manager'])
                ->whereHas('checkMeasures', fn($q) => $q->where('status', 'completed'))
                ->where('stage', 'processing')
                ->orderBy('job_number', 'desc')
                ->get();
            $assignments      = collect();
            $jobTaskMap       = null;
            $allTaskTypesJson = null;
        } else {
            $jobs = Job::whereIn('status', ['active'])->orderBy('job_number')->get();
            $assignments      = collect();
            $jobTaskMap       = null;
            $allTaskTypesJson = null;
        }

        // Running timer — first one for non-employee compat
        $running = TimeEntry::where('user_id', $user->id)
            ->where('status', 'running')
            ->with('taskType', 'job')
            ->first();

        // All running timers — used by factory_employee multi-timer view
        $runningEntries = TimeEntry::where('user_id', $user->id)
            ->where('status', 'running')
            ->with('taskType', 'job')
            ->get();

        // Paused entries (most recent per job+task combo) — so employee can resume
        $pausedEntries = TimeEntry::where('user_id', $user->id)
            ->where('status', 'paused')
            ->with('taskType', 'job')
            ->orderByDesc('stopped_at')
            ->get();

        // Recent entries
        $entries = TimeEntry::where('user_id', $user->id)
            ->with('taskType', 'job')
            ->orderByDesc('started_at')
            ->paginate(20);

        // Weekly summary — include both paused and completed in totals
        $weekStart     = Carbon::now()->startOfWeek();
        $weeklyEntries = TimeEntry::where('user_id', $user->id)
            ->where('started_at', '>=', $weekStart)
            ->whereIn('status', ['paused', 'completed'])
            ->get();
        $weeklyHours    = $weeklyEntries->sum('duration_minutes') / 60;
        $weeklyEarnings = $weeklyHours * ($user->hourly_rate ?? 0);

        $statuscompleted = true;

        return view('timesheet.index', compact(
            'taskTypes', 'jobs', 'running', 'runningEntries', 'entries', 'weeklyHours', 'weeklyEarnings',
            'jobTaskMap', 'allTaskTypesJson', 'assignments', 'pausedEntries', 'statuscompleted'
        ));
    }

    public function start(Request $request)
    {
        $user       = auth()->user();
        $isEmployee = $user->role?->name === 'factory_employee';

        // For non-employee users only: pause any currently running timer before starting a new one
        if (!$isEmployee) {
            $current = TimeEntry::where('user_id', $user->id)->where('status', 'running')->first();
            if ($current) {
                $mins = $current->started_at->diffInMinutes(now());
                $current->update([
                    'stopped_at'       => now(),
                    'duration_minutes' => $mins,
                    'status'           => 'paused',
                ]);
            }
        }
        // Factory employees can run multiple timers simultaneously — no auto-pause.

        $isTrades = $user->role?->name === 'trades';
        $rules = [
            'job_id' => 'required|exists:crm_jobs,id',
            'notes'  => 'nullable|string|max:255',
        ];
        if (! $isTrades) {
            $rules['task_type_id'] = 'required|exists:staff_task_types,id';
        }
        $data = $request->validate($rules);

        // For factory employees: prevent starting a duplicate running timer for the same job+task
        if ($isEmployee && isset($data['task_type_id']) && isset($data['job_id'])) {
            $alreadyRunning = TimeEntry::where('user_id', $user->id)
                ->where('status', 'running')
                ->where('job_id', $data['job_id'])
                ->where('task_type_id', $data['task_type_id'])
                ->exists();
            if ($alreadyRunning) {
                return back()->with('error', 'A timer for this task is already running.');
            }
        }

        TimeEntry::create([
            'user_id'      => $user->id,
            'task_type_id' => $data['task_type_id'] ?? null,
            'job_id'       => $data['job_id'] ?? null,
            'started_at'   => now(),
            'status'       => 'running',
            'notes'        => $data['notes'] ?? null,
        ]);

        // Mark task assignment as in_progress
        if (isset($data['task_type_id']) && isset($data['job_id'])) {
            JobEmployeeTaskAssignment::where('user_id', $user->id)
                ->where('job_id', $data['job_id'])
                ->where('task_type_id', $data['task_type_id'])
                ->where('task_status', 'pending')
                ->update(['task_status' => 'in_progress']);
        }

        return back()->with('success', 'Timer started.');
    }

    /**
     * Pause a running timer.
     * For factory employees: requires job_id + task_type_id to identify which timer to pause.
     * For other users: pauses the single running timer.
     */
    public function stop(Request $request)
    {
        $user       = auth()->user();
        $isEmployee = $user->role?->name === 'factory_employee';

        if ($isEmployee) {
            // Target the specific task's running timer
            $entry = TimeEntry::where('user_id', $user->id)
                ->where('status', 'running')
                ->where('job_id', $request->input('job_id'))
                ->where('task_type_id', $request->input('task_type_id'))
                ->first();
        } else {
            // Non-employee: pause whichever timer is running
            $entry = TimeEntry::where('user_id', $user->id)->where('status', 'running')->first();
        }

        if ($entry) {
            $mins = $entry->started_at->diffInMinutes(now());
            $entry->update([
                'stopped_at'       => now(),
                'duration_minutes' => $mins,
                'status'           => 'paused',
            ]);

            // Mark task assignment as paused if it was in_progress
            if ($entry->task_type_id && $entry->job_id) {
                JobEmployeeTaskAssignment::where('user_id', $user->id)
                    ->where('job_id', $entry->job_id)
                    ->where('task_type_id', $entry->task_type_id)
                    ->where('task_status', 'in_progress')
                    ->update(['task_status' => 'paused']);
            }

            return back()->with('success', 'Timer paused. ' . $entry->elapsed . ' recorded. You can resume it anytime.');
        }
        return back()->with('error', 'No running timer found.');
    }

    /**
     * Resume a paused task — starts a new TimeEntry for same job+task.
     * For factory employees: does NOT pause other running timers.
     * For other users: pauses any currently running timer first.
     */
    public function resume(Request $request)
    {
        $user       = auth()->user();
        $isEmployee = $user->role?->name === 'factory_employee';

        $data = $request->validate([
            'job_id'       => 'required|exists:crm_jobs,id',
            'task_type_id' => 'nullable|exists:staff_task_types,id',
        ]);

        // For non-employee users: pause any currently running timer first
        if (!$isEmployee) {
            $current = TimeEntry::where('user_id', $user->id)->where('status', 'running')->first();
            if ($current) {
                $mins = $current->started_at->diffInMinutes(now());
                $current->update([
                    'stopped_at'       => now(),
                    'duration_minutes' => $mins,
                    'status'           => 'paused',
                ]);
            }
        }
        // Factory employees: other timers keep running — no auto-pause.

        // For factory employees: prevent duplicate running timer for same job+task
        if ($isEmployee && !empty($data['task_type_id'])) {
            $alreadyRunning = TimeEntry::where('user_id', $user->id)
                ->where('status', 'running')
                ->where('job_id', $data['job_id'])
                ->where('task_type_id', $data['task_type_id'])
                ->exists();
            if ($alreadyRunning) {
                return back()->with('error', 'A timer for this task is already running.');
            }
        }

        // Start a new timer entry (continuation)
        TimeEntry::create([
            'user_id'      => $user->id,
            'task_type_id' => $data['task_type_id'] ?? null,
            'job_id'       => $data['job_id'],
            'started_at'   => now(),
            'status'       => 'running',
            'notes'        => 'Resumed',
        ]);

        // Mark assignment back to in_progress
        if (!empty($data['task_type_id'])) {
            JobEmployeeTaskAssignment::where('user_id', $user->id)
                ->where('job_id', $data['job_id'])
                ->where('task_type_id', $data['task_type_id'])
                ->whereIn('task_status', ['paused', 'pending'])
                ->update(['task_status' => 'in_progress']);
        }

        return back()->with('success', 'Timer resumed.');
    }

    /**
     * Manually complete a task assignment.
     * Stops any running timer for this task, marks all paused entries as completed,
     * and marks the assignment itself as completed.
     * This allows the task hours to count in the gross profit report.
     */
    public function completeTask(Request $request)
    {
        $user = auth()->user();

        $data = $request->validate([
            'assignment_id' => 'required|exists:job_employee_task_assignments,id',
        ]);

        $assignment = JobEmployeeTaskAssignment::where('id', $data['assignment_id'])
            ->where('user_id', $user->id)
            ->firstOrFail();

        // Stop running timer if it's for this task
        $running = TimeEntry::where('user_id', $user->id)
            ->where('status', 'running')
            ->where('job_id', $assignment->job_id)
            ->where('task_type_id', $assignment->task_type_id)
            ->first();

        if ($running) {
            $mins = $running->started_at->diffInMinutes(now());
            $running->update([
                'stopped_at'       => now(),
                'duration_minutes' => $mins,
                'status'           => 'completed',
            ]);
        }

        // Mark all paused entries for this task as completed (so they appear in gross profit)
        TimeEntry::where('user_id', $user->id)
            ->where('job_id', $assignment->job_id)
            ->where('task_type_id', $assignment->task_type_id)
            ->where('status', 'paused')
            ->update(['status' => 'completed']);

        // Mark the assignment as completed
        $assignment->update(['task_status' => 'completed']);

        return back()->with('success', 'Task marked as completed. Hours are now included in the gross profit report.');
    }

    public function destroy(TimeEntry $entry)
    {
        $user = auth()->user();
        if ($entry->user_id !== $user->id && $user->role?->name !== 'office_admin') {
            abort(403);
        }
        $entry->delete();
        return back()->with('success', 'Entry deleted.');
    }

    // Admin: view all timesheets
    public function admin()
    {
        $entries = TimeEntry::with('user', 'taskType', 'job')
            ->orderByDesc('started_at')
            ->paginate(50);

        $users = \App\Models\User::with('role')
            ->whereHas('role', fn($q) => $q->whereIn('name', ['factory_employee', 'trades', 'processor']))
            ->orderBy('name')
            ->get();

        return view('timesheet.admin', compact('entries', 'users'));
    }
}
