<?php

namespace App\Http\Controllers;

use App\Models\CheckMeasure;
use App\Models\Document;
use App\Models\Installation;
use App\Models\Job;
use App\Models\ActivityLog;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class DocumentController extends Controller
{
    private const TYPE_MAP = [
        'Contract'     => \App\Models\Contract::class,
        'CheckMeasure' => \App\Models\CheckMeasure::class,
        'Delivery'     => \App\Models\Delivery::class,
        'Installation' => \App\Models\Installation::class,
        'Completion'   => \App\Models\Completion::class,
        'Job'          => \App\Models\Job::class,
        'Lead'         => \App\Models\Lead::class,
    ];

    private function resolveJobId(Document $document): ?int
    {
        $model = $document->documentable;
        if (! $model) {
            return null;
        }
        if ($model instanceof Job) {
            return $model->id;
        }
        return $model->job_id ?? null;
    }

    private function userCanAccess(Document $document, User $user): bool
    {
        $role = $user->role?->name ?? 'staff';

        if (in_array($role, ['office_admin', 'project_manager'])) {
            return true;
        }

        $jobId = $this->resolveJobId($document);

        if (! $jobId) {
            return in_array($role, ['sales_consultant']);
        }

        return match ($role) {
            'sales_consultant' => Job::where('id', $jobId)
                ->where('consultant_id', $user->id)
                ->exists(),

            'lead_installer' => Installation::where('job_id', $jobId)
                ->where('lead_installer_id', $user->id)
                ->exists(),

            'check_measurer' => CheckMeasure::where('job_id', $jobId)
                ->where('measurer_id', $user->id)
                ->exists(),

            // Processors can upload/manage processor_drawing documents on any job
            'processor' => true,

            // Factory employees can view/download processor_drawing documents
            'factory_employee' => true,

            default => false,
        };
    }

    private function resolveDocumentable(string $type, int $id): ?object
    {
        $fqcn = self::TYPE_MAP[$type] ?? null;
        if (! $fqcn) {
            return null;
        }
        return $fqcn::find($id);
    }

    public function store(Request $request)
    {
        $request->validate([
            'documentable_type' => 'required|string|in:Contract,CheckMeasure,Delivery,Installation,Completion,Job,Lead',
            'documentable_id'   => 'required|integer',
            'file'              => 'required|file|max:20480|mimes:pdf,doc,docx,jpg,jpeg,png,gif,xls,xlsx,csv,txt,zip',
            'name'              => 'nullable|string|max:255',
            'category'          => 'nullable|string|in:general,processor_drawing',
        ]);

        $type   = $request->input('documentable_type');
        $id     = (int) $request->input('documentable_id');
        $user   = auth()->user();
        $role   = $user->role?->name ?? 'staff';

        // Factory employees cannot upload documents
        if ($role === 'factory_employee') {
            abort(403, 'Factory employees cannot upload documents.');
        }

        $parent = $this->resolveDocumentable($type, $id);
        abort_if(! $parent, 404, 'The target record does not exist.');

        $stub                    = new Document();
        $stub->documentable_type = self::TYPE_MAP[$type];
        $stub->documentable_id   = $id;
        $stub->setRelation('documentable', $parent);

        if (! $this->userCanAccess($stub, $user)) {
            abort(403, 'You are not assigned to this record.');
        }

        $category = $request->input('category', 'general');

        // Processors can only upload processor_drawing category
        if ($role === 'processor') {
            $category = 'processor_drawing';
        }

        $file   = $request->file('file');
        $folder = 'documents/' . strtolower($type) . '/' . $id;
        $path   = $file->store($folder, 'local');

        $document = Document::create([
            'documentable_type' => self::TYPE_MAP[$type],
            'documentable_id'   => $id,
            'name'              => $request->input('name') ?: $file->getClientOriginalName(),
            'category'          => $category,
            'file_path'         => $path,
            'file_type'         => $file->getClientMimeType(),
            'file_size'         => $file->getSize(),
            'uploaded_by'       => $user->id,
        ]);

        ActivityLog::create([
            'user_id'       => $user->id,
            'loggable_type' => $type,
            'loggable_id'   => $id,
            'action'        => 'Document Uploaded',
            'description'   => "File '{$document->name}' uploaded to {$type} #{$id}",
        ]);

        if ($request->expectsJson()) {
            return response()->json(['success' => true, 'document' => $document]);
        }

        return back()->with('success', "Document '{$document->name}' uploaded successfully.");
    }

    public function destroy(Document $document)
    {
        $user = auth()->user();
        $role = $user->role?->name ?? 'staff';

        // Factory employees cannot delete documents
        if ($role === 'factory_employee') {
            abort(403, 'Factory employees cannot delete documents.');
        }

        $isAdminOrPm  = in_array($role, ['office_admin', 'project_manager']);
        $isOwnUpload  = $document->uploaded_by === $user->id;

        // Processors can only delete their own processor_drawing documents
        if ($role === 'processor') {
            abort_unless($isOwnUpload && $document->category === 'processor_drawing', 403, 'You can only delete your own processor drawing documents.');
        } elseif (!$isAdminOrPm) {
            abort_unless($isOwnUpload, 403, 'You can only delete documents you uploaded.');
            abort_unless($this->userCanAccess($document, $user), 403, 'You do not have permission to delete this document.');
        }

        $filePath = $document->file_path;
        $type     = class_basename($document->documentable_type);
        $id       = $document->documentable_id;
        $name     = $document->name;

        $document->delete();
        Storage::disk('local')->delete($filePath);

        ActivityLog::create([
            'user_id'       => $user->id,
            'loggable_type' => $type,
            'loggable_id'   => $id,
            'action'        => 'Document Deleted',
            'description'   => "File '{$name}' removed from {$type} #{$id}",
        ]);

        return back()->with('success', "Document '{$name}' deleted.");
    }

    public function download(Document $document)
    {
        $user = auth()->user();
        $role = $user->role?->name ?? 'staff';

        // Processors and factory employees can only download processor_drawing documents
        if (in_array($role, ['processor', 'factory_employee'])) {
            abort_unless($document->category === 'processor_drawing', 403, 'You do not have permission to download this document.');
        } elseif (! $this->userCanAccess($document, $user)) {
            abort(403, 'You do not have permission to download this document.');
        }

        abort_unless(Storage::disk('local')->exists($document->file_path), 404);

        return Storage::disk('local')->download($document->file_path, $document->name);
    }
}
