<?php

namespace App\Http\Controllers;

use App\Models\Project;
use App\Models\ProjectVersion;
use App\Models\ProjectCollaborator;
use App\Models\Milestone;
use Illuminate\Http\Request;
use App\Repositories\Contracts\ProjectRepositoryInterface;
use App\Http\Traits\ResponseTrait;
use App\Http\Resources\ResponseCollection;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;

class ProjectController extends Controller
{
    use ResponseTrait;

    protected $projectRepository;

    public function __construct(ProjectRepositoryInterface $projectRepository)
    {
        $this->projectRepository = $projectRepository;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $perPage = $request->per_page ? $request->per_page : 100;

        return new ResponseCollection(
            $this->paginateResponse($this->projectRepository->all($request), $perPage)
        );
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // $request->validate([
        //     'name' => 'required|string|max:255',
        //     'location' => 'required|string|max:255',
        //     'owner_id' => 'required|numeric',
        // ]);

        $project = $this->projectRepository->create($request->toArray());

        return $this->successResponse($project, 'Project added successfully!');
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Project  $project
     * @return \Illuminate\Http\Response
     */
    public function show(Project $project)
    {
        return $this->successResponse($project);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Project  $project
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Project $project)
    {
        $this->projectRepository->update($project, $request->toArray());

        return $this->updateResponse('Project updated successfully!');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Project  $project
     * @return \Illuminate\Http\Response
     */
    public function destroy(Project $project)
    {
        $this->projectRepository->delete($project);

        return $this->updateResponse('Project deleted successfully!');
    }

    /**
     * Upload project version
     * POST /projects/{id}/versions
     */
    public function uploadVersion(Request $request, Project $project)
    {
        $user = $request->user();

        // Check permissions
        if (!$project->canUserUploadVersions($user->id)) {
            return $this->errorResponse('You do not have permission to upload versions for this project');
        }

        $request->validate([
            'file' => 'required|file|max:102400', // 100MB max
            'version_number' => 'required|string|max:50',
            'notes' => 'nullable|string|max:1000',
            'changes_summary' => 'nullable|string|max:2000',
        ]);

        $file = $request->file('file');
        $filePath = $file->store('projects/' . $project->id . '/versions', 'public');
        $fileUrl = Storage::url($filePath);

        $version = ProjectVersion::create([
            'project_id' => $project->id,
            'uploaded_by' => $user->id,
            'version_number' => $request->version_number,
            'file_path' => $filePath,
            'file_url' => $fileUrl,
            'file_size' => $file->getSize(),
            'notes' => $request->notes,
            'changes_summary' => $request->changes_summary,
        ]);

        return response()->json([
            'code' => 201,
            'error' => false,
            'status' => 'success',
            'message' => 'Project version uploaded successfully',
            'data' => [
                'version' => [
                    'id' => $version->id,
                    'version_number' => $version->version_number,
                    'file_url' => $version->file_url,
                    'uploaded_at' => $version->created_at,
                    'notes' => $version->notes,
                    'changes_summary' => $version->changes_summary,
                ],
            ],
        ], 201, [], JSON_NUMERIC_CHECK);
    }

    /**
     * Get project versions
     * GET /projects/{id}/versions
     */
    public function getVersions(Request $request, Project $project)
    {
        $user = $request->user();

        // Check if user has access (owner, collaborator, or client)
        if ($project->researcher_id !== $user->id 
            && $project->client_id !== $user->id 
            && !$project->isCollaborator($user->id)) {
            return $this->errorResponse('You do not have access to this project');
        }

        $versions = $project->versions()->with('uploadedBy:id,name')->get()->map(function ($version) {
            return [
                'id' => $version->id,
                'version_number' => $version->version_number,
                'file_url' => $version->file_url,
                'uploaded_at' => $version->created_at,
                'uploaded_by' => [
                    'id' => $version->uploadedBy->id,
                    'name' => $version->uploadedBy->name,
                ],
                'notes' => $version->notes,
                'changes_summary' => $version->changes_summary,
                'file_size' => $version->file_size,
            ];
        });

        return $this->successResponse($versions, 'Project versions retrieved successfully');
    }

    /**
     * Get project milestones
     * GET /projects/{id}/milestones
     */
    public function getMilestones(Request $request, Project $project)
    {
        $user = $request->user();

        // Check if user has access
        if ($project->researcher_id !== $user->id 
            && $project->client_id !== $user->id 
            && !$project->isCollaborator($user->id)) {
            return $this->errorResponse('You do not have access to this project');
        }

        $milestones = $project->milestones()->get()->map(function ($milestone) {
            return [
                'id' => $milestone->id,
                'title' => $milestone->title,
                'description' => $milestone->description,
                'due_date' => $milestone->due_date,
                'status' => $milestone->status,
                'completion_criteria' => $milestone->completion_criteria,
                'completed_at' => $milestone->completed_at,
                'order' => $milestone->order,
            ];
        });

        // Calculate summary
        $summary = [
            'total' => $milestones->count(),
            'completed' => $milestones->where('status', 'completed')->count(),
            'in_progress' => $milestones->whereIn('status', ['in_progress', 'in_review'])->count(),
            'not_started' => $milestones->where('status', 'not_started')->count(),
        ];

        $response = [
            'code' => 200,
            'error' => false,
            'status' => 'success',
            'message' => 'Project milestones retrieved successfully',
            'data' => $milestones,
            'meta' => [
                'summary' => $summary,
            ],
        ];
        return response()->json($response, 200, [], JSON_NUMERIC_CHECK);
    }

    /**
     * Update milestone status
     * PUT /projects/{id}/milestones/{milestone_id}
     */
    public function updateMilestone(Request $request, Project $project, Milestone $milestone)
    {
        $user = $request->user();

        // Verify milestone belongs to project
        if ($milestone->project_id !== $project->id) {
            return $this->notFoundResponse();
        }

        // Check permissions
        if ($project->researcher_id !== $user->id && !$project->canUserEdit($user->id)) {
            return $this->errorResponse('You do not have permission to update milestones for this project');
        }

        $request->validate([
            'status' => 'required|string|in:not_started,in_progress,in_review,completed,blocked',
            'notes' => 'nullable|string|max:1000',
        ]);

        $milestone->update([
            'status' => $request->status,
            'completed_at' => $request->status === 'completed' ? now() : null,
        ]);

        if ($request->has('notes')) {
            $milestone->update(['ai_feedback' => $request->notes]);
        }

        return $this->successResponse([
            'milestone' => [
                'id' => $milestone->id,
                'title' => $milestone->title,
                'status' => $milestone->status,
                'completed_at' => $milestone->completed_at,
            ],
        ], 'Milestone updated successfully');
    }

    /**
     * Get project collaborators
     * GET /projects/{id}/collaborators
     */
    public function getCollaborators(Request $request, Project $project)
    {
        $user = $request->user();

        // Check if user has access
        if ($project->researcher_id !== $user->id 
            && $project->client_id !== $user->id 
            && !$project->isCollaborator($user->id)) {
            return $this->errorResponse('You do not have access to this project');
        }

        $collaborators = $project->collaborators()->with('user:id,name,email,profile_photo')->get()->map(function ($collaborator) {
            return [
                'id' => $collaborator->id,
                'user' => [
                    'id' => $collaborator->user->id,
                    'name' => $collaborator->user->name,
                    'email' => $collaborator->user->email,
                    'profile_photo' => $collaborator->user->profile_photo,
                ],
                'role' => $collaborator->role,
                'added_at' => $collaborator->added_at,
                'permissions' => $collaborator->permissions,
            ];
        });

        return $this->successResponse($collaborators, 'Project collaborators retrieved successfully');
    }

    /**
     * Add collaborator to project
     * POST /projects/{id}/collaborators
     */
    public function addCollaborator(Request $request, Project $project)
    {
        $user = $request->user();

        // Only project owner can add collaborators
        if ($project->researcher_id !== $user->id) {
            return $this->errorResponse('Only the project owner can add collaborators');
        }

        $request->validate([
            'user_id' => 'required|exists:users,id',
            'role' => 'required|string|max:50',
            'permissions' => 'nullable|array',
            'permissions.can_edit' => 'boolean',
            'permissions.can_upload_versions' => 'boolean',
            'permissions.can_manage_milestones' => 'boolean',
        ]);

        // Check if user is already a collaborator
        if ($project->collaborators()->where('user_id', $request->user_id)->exists()) {
            return $this->errorResponse('User is already a collaborator on this project');
        }

        // Cannot add project owner as collaborator
        if ($request->user_id == $project->researcher_id) {
            return $this->errorResponse('Project owner cannot be added as a collaborator');
        }

        $collaborator = ProjectCollaborator::create([
            'project_id' => $project->id,
            'user_id' => $request->user_id,
            'role' => $request->role,
            'can_edit' => $request->input('permissions.can_edit', false),
            'can_upload_versions' => $request->input('permissions.can_upload_versions', false),
            'can_manage_milestones' => $request->input('permissions.can_manage_milestones', false),
        ]);

        return response()->json([
            'code' => 201,
            'error' => false,
            'status' => 'success',
            'message' => 'Collaborator added successfully',
            'data' => [
                'collaborator' => [
                    'id' => $collaborator->id,
                    'user_id' => $collaborator->user_id,
                    'role' => $collaborator->role,
                    'permissions' => $collaborator->permissions,
                ],
            ],
        ], 201, [], JSON_NUMERIC_CHECK);
    }

    /**
     * Remove collaborator from project
     * DELETE /projects/{id}/collaborators/{collaborator_id}
     */
    public function removeCollaborator(Request $request, Project $project, ProjectCollaborator $projectCollaborator)
    {
        $user = $request->user();

        // Verify collaborator belongs to project
        if ($projectCollaborator->project_id !== $project->id) {
            return $this->notFoundResponse();
        }

        // Only project owner can remove collaborators
        if ($project->researcher_id !== $user->id) {
            return $this->errorResponse('Only the project owner can remove collaborators');
        }

        $projectCollaborator->delete();

        return $this->successResponse([], 'Collaborator removed successfully');
    }

    /**
     * Upload scope document
     * POST /projects/{id}/scope-document
     */
    public function uploadScopeDocument(Request $request, Project $project)
    {
        $user = $request->user();

        // Check permissions
        if ($project->researcher_id !== $user->id && !$project->canUserEdit($user->id)) {
            return $this->errorResponse('You do not have permission to upload scope documents for this project');
        }

        $request->validate([
            'file' => 'required|file|mimes:pdf,doc,docx|max:10240', // 10MB max
            'document_type' => 'nullable|string|max:100',
        ]);

        $file = $request->file('file');
        $filePath = $file->store('projects/' . $project->id . '/scope-documents', 'public');
        $fileUrl = Storage::url($filePath);

        // Store document URL in project (you might want to add a scope_document_url field to projects table)
        // For now, we'll just return the URL

        return response()->json([
            'code' => 201,
            'error' => false,
            'status' => 'success',
            'message' => 'Scope document uploaded successfully',
            'data' => [
                'document_url' => $fileUrl,
            ],
        ], 201, [], JSON_NUMERIC_CHECK);
    }
}
