<?php

namespace App\Http\Controllers;

use App\Models\Project;
use App\Models\ProjectAuditLog;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class ProjectController extends Controller
{
    /**
     * Display a listing of projects
     */
    public function index()
    {
        $projects = Project::query()
            ->with(['components', 'assignedUsers:id,name,email,role'])
            ->withCount([
                'tasks',
                'tasks as pending_tasks_count' => function ($query) {
                    $query->where('status', '!=', 'completed');
                },
            ])
            ->latest()
            ->get();

        return response()->json([
            'data' => $projects,
            'total' => $projects->count(),
        ]);
    }

    /**
     * Store a newly created project
     */
    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'category' => 'nullable|string|max:255',
            'contract_number' => 'nullable|string|max:255',
            'ahp_name' => 'nullable|string|max:255',
            'project_duration' => 'nullable|string|max:100',
            'client' => 'nullable|string|max:255',
            'contractor' => 'nullable|string|max:255',
            'consultant' => 'nullable|string|max:255',
            'description' => 'nullable|string',
            'location' => 'nullable|string|max:255',
            'ward' => 'nullable|string|max:255',
            'constituency' => 'nullable|string|max:255',
            'county' => 'nullable|string|max:255',
            'budget' => 'nullable|numeric|min:0',
            'project_sum' => 'nullable|numeric|min:0',
            'units' => 'nullable|integer|min:0',
            'spent' => 'nullable|numeric|min:0',
            'progress' => 'nullable|integer|min:0|max:100',
            'status' => ['nullable', Rule::in(['pending', 'active', 'on_hold', 'completed', 'cancelled'])],
            'start_date' => 'required|date',
            'end_date' => 'required|date|after_or_equal:start_date',
            'project_manager_id' => 'nullable|exists:users,id',
            'components' => 'nullable|array',
            'components.*' => 'required|string|max:255',
        ]);

        $project = Project::create([
            'name' => $request->name,
            'category' => $request->category,
            'contract_number' => $request->contract_number,
            'ahp_name' => $request->ahp_name,
            'project_duration' => $request->project_duration,
            'client' => $request->client,
            'contractor' => $request->contractor,
            'consultant' => $request->consultant,
            'description' => $request->description,
            'location' => $request->location,
            'ward' => $request->ward,
            'constituency' => $request->constituency,
            'county' => $request->county,
            'budget' => $request->budget,
            'project_sum' => $request->project_sum,
            'units' => $request->units,
            'spent' => $request->spent ?? 0,
            'progress' => $request->progress ?? 0,
            'status' => $request->status ?? 'pending',
            'start_date' => $request->start_date,
            'end_date' => $request->end_date,
            'project_manager_id' => $request->project_manager_id ?? auth('api')->id(),
        ]);

        if ($request->filled('components')) {
            foreach ($request->components as $index => $componentName) {
                $project->components()->create([
                    'name' => $componentName,
                    'sort_order' => $index,
                    'is_active' => true,
                ]);
            }
            $project->recalculateProgressFromComponents();
        }

        $project->assignedUsers()->syncWithoutDetaching([
            ($project->project_manager_id ?? auth('api')->id()) => [
                'assigned_role' => 'project_manager',
                'assigned_by_id' => auth('api')->id(),
            ],
        ]);

        $project->load(['components', 'assignedUsers:id,name,email,role']);

        // Audit log
        $user = auth('api')->user();
        if ($user) {
            ProjectAuditLog::log(
                $project,
                'project_created',
                "Project '{$project->name}' created",
                $user,
                'project',
                $project->id
            );
        }

        return response()->json([
            'data' => $project,
        ], 201);
    }

    /**
     * Display the specified project
     */
    public function show($id)
    {
        $project = Project::with([
            'components',
            'assignedUsers:id,name,email,role',
            'tasks.assignedTo:id,name,email,role',
            'tasks.createdBy:id,name,email,role',
        ])->find($id);

        if (!$project) {
            return response()->json(['message' => 'Project not found'], 404);
        }

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

    /**
     * Update the specified project
     */
    public function update(Request $request, $id)
    {
        $request->validate([
            'name' => 'nullable|string|max:255',
            'category' => 'nullable|string|max:255',
            'contract_number' => 'nullable|string|max:255',
            'ahp_name' => 'nullable|string|max:255',
            'project_duration' => 'nullable|string|max:100',
            'client' => 'nullable|string|max:255',
            'contractor' => 'nullable|string|max:255',
            'consultant' => 'nullable|string|max:255',
            'description' => 'nullable|string',
            'location' => 'nullable|string|max:255',
            'ward' => 'nullable|string|max:255',
            'constituency' => 'nullable|string|max:255',
            'county' => 'nullable|string|max:255',
            'budget' => 'nullable|numeric|min:0',
            'project_sum' => 'nullable|numeric|min:0',
            'units' => 'nullable|integer|min:0',
            'spent' => 'nullable|numeric|min:0',
            'progress' => 'nullable|integer|min:0|max:100',
            'status' => ['nullable', Rule::in(['pending', 'active', 'on_hold', 'completed', 'cancelled'])],
            'start_date' => 'required|date',
            'end_date' => 'required|date|after_or_equal:start_date',
            'project_manager_id' => 'nullable|exists:users,id',
            'components' => 'nullable|array',
            'components.*' => 'required|string|max:255',
        ]);

        $project = Project::find($id);

        if (!$project) {
            return response()->json(['message' => 'Project not found'], 404);
        }

        $oldData = $project->toArray();

        $project->update($request->only([
            'name',
            'category',
            'contract_number',
            'ahp_name',
            'project_duration',
            'client',
            'contractor',
            'consultant',
            'description',
            'location',
            'ward',
            'constituency',
            'county',
            'budget',
            'project_sum',
            'units',
            'spent',
            'progress',
            'status',
            'start_date',
            'end_date',
            'project_manager_id',
        ]));

        if ($request->has('components')) {
            $project->components()->delete();
            foreach (($request->components ?? []) as $index => $componentName) {
                $project->components()->create([
                    'name' => $componentName,
                    'sort_order' => $index,
                    'is_active' => true,
                ]);
            }

            $project->recalculateProgressFromComponents();
        }

        $project->load(['components', 'assignedUsers:id,name,email,role']);

        // Audit log
        $user = auth('api')->user();
        if ($user) {
            $changes = array_diff_assoc($project->toArray(), $oldData);
            ProjectAuditLog::log(
                $project,
                'project_updated',
                "Project '{$project->name}' updated",
                $user,
                'project',
                $project->id,
                $changes ?: null
            );
        }

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

    /**
     * Remove the specified project
     */
    public function destroy($id)
    {
        $project = Project::find($id);

        if (!$project) {
            return response()->json(['message' => 'Project not found'], 404);
        }

        // Audit log before delete
        $user = auth('api')->user();
        if ($user) {
            ProjectAuditLog::log(
                $project,
                'project_deleted',
                "Project '{$project->name}' deleted",
                $user,
                'project',
                $project->id
            );
        }

        $project->delete();

        return response()->json([
            'message' => 'Project deleted successfully'
        ]);
    }
}
