<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\DocumentType;
use App\Models\GeneralDocument;
use App\Models\GeneralDocumentAttachment;
use App\Models\GeneralDocumentShare;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class GeneralDocumentController extends Controller
{
    private function mapAttachment($a, $doc): array
    {
        return [
            'id'          => $a->id,
            'name'        => $a->original_name,
            'size'        => $this->formatBytes($a->file_size),
            'type'        => strtoupper(pathinfo($a->original_name, PATHINFO_EXTENSION)),
            'docType'     => optional($a->documentType)->name ?? optional($doc->documentType)->name ?? 'Unknown',
            'downloadUrl' => route('admin.general-documents.download', [$doc->id, $a->id]),
        ];
    }

    public function index()
    {
        $currentUser = Auth::user();
        $docTypes    = DocumentType::active()->get();

        $gdPerms = ['view' => true, 'add' => true, 'delete' => true, 'download' => true];
        if (! $currentUser->is_super_admin) {
            $userPermSlugs = $currentUser->modulePermissions()
                ->wherePivot('is_active', true)
                ->pluck('slug')
                ->toArray();
            foreach (array_keys($gdPerms) as $action) {
                $gdPerms[$action] = in_array('generaldocument_' . $action, $userPermSlugs);
            }
        }

        $documents = GeneralDocument::with(['documentType', 'uploader', 'attachments.documentType', 'shares.user'])
            ->orderByDesc('created_at')
            ->get()
            ->map(function ($doc) use ($currentUser) {
                $isMe = $doc->uploaded_by === $currentUser->id;
                return [
                    'id'               => $doc->id,
                    'docType'          => optional($doc->documentType)->name ?? 'Unknown',
                    'docTypeId'        => $doc->document_type_id,
                    'comments'         => $doc->comments ?? '',
                    'uploadedOn'       => $doc->created_at->format('d-M-Y'),
                    'uploadedBy'       => $isMe ? 'Me' : (optional($doc->uploader)->name ?? 'Unknown'),
                    'uploadedByMe'     => $isMe,
                    'uploaderInitials' => $isMe ? 'Me' : strtoupper(substr(optional($doc->uploader)->name ?? 'UN', 0, 2)),
                    'attachmentsCount' => $doc->attachments->count(),
                    'attachments'      => $doc->attachments->map(fn($a) => $this->mapAttachment($a, $doc))->values(),
                    'sharedWith' => $doc->shares->map(fn($s) => [
                        'id'       => $s->user_id,
                        'name'     => optional($s->user)->name ?? '',
                        'email'    => optional($s->user)->email ?? '',
                        'initials' => strtoupper(substr(optional($s->user)->name ?? 'U', 0, 2)),
                    ])->values(),
                ];
            });

        return view('admin.general-documents.index', compact('docTypes', 'documents', 'gdPerms'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'comments'          => 'nullable|string|max:1000',
            'files'             => 'required|array|min:1',
            'files.*'           => 'file|max:20480',
            'file_doc_types'    => 'required|array|min:1',
            'file_doc_types.*'  => 'required|exists:document_types,id',
            'share_user_ids'    => 'nullable|array',
            'share_user_ids.*'  => 'exists:users,id',
        ]);

        $fileDocTypes  = $request->input('file_doc_types', []);
        $firstDocType  = $fileDocTypes[0] ?? null;

        $doc = GeneralDocument::create([
            'document_type_id' => $firstDocType,
            'comments'         => $request->comments,
            'uploaded_by'      => Auth::id(),
        ]);

        foreach ($request->file('files', []) as $i => $file) {
            $ext    = $file->getClientOriginalExtension();
            $stored = $file->storeAs('general-documents', Str::uuid() . '.' . $ext, 'public');
            GeneralDocumentAttachment::create([
                'general_document_id' => $doc->id,
                'document_type_id'    => $fileDocTypes[$i] ?? $firstDocType,
                'original_name'       => $file->getClientOriginalName(),
                'stored_path'         => $stored,
                'file_size'           => $file->getSize(),
                'mime_type'           => $file->getMimeType(),
            ]);
        }

        foreach ($request->input('share_user_ids', []) as $userId) {
            GeneralDocumentShare::firstOrCreate([
                'general_document_id' => $doc->id,
                'user_id'             => (int) $userId,
            ]);
        }

        $doc->load(['documentType', 'uploader', 'attachments.documentType', 'shares.user']);
        $currentUser = Auth::user();
        $isMe = $doc->uploaded_by === $currentUser->id;

        return response()->json([
            'success'  => true,
            'document' => [
                'id'               => $doc->id,
                'docType'          => optional($doc->documentType)->name ?? 'Unknown',
                'docTypeId'        => $doc->document_type_id,
                'comments'         => $doc->comments ?? '',
                'uploadedOn'       => $doc->created_at->format('d-M-Y'),
                'uploadedBy'       => $isMe ? 'Me' : (optional($doc->uploader)->name ?? 'Unknown'),
                'uploadedByMe'     => $isMe,
                'uploaderInitials' => $isMe ? 'Me' : strtoupper(substr(optional($doc->uploader)->name ?? 'UN', 0, 2)),
                'attachmentsCount' => $doc->attachments->count(),
                'attachments'      => $doc->attachments->map(fn($a) => $this->mapAttachment($a, $doc))->values(),
                'sharedWith' => $doc->shares->map(fn($s) => [
                    'id'       => $s->user_id,
                    'name'     => optional($s->user)->name ?? '',
                    'email'    => optional($s->user)->email ?? '',
                    'initials' => strtoupper(substr(optional($s->user)->name ?? 'U', 0, 2)),
                ])->values(),
            ],
        ]);
    }

    public function files(GeneralDocument $document)
    {
        $document->load('attachments.documentType', 'uploader');
        return response()->json([
            'attachments' => $document->attachments->map(fn($a) => array_merge($this->mapAttachment($a, $document), [
                'uploadedBy' => optional($document->uploader)->name ?? 'Unknown',
                'uploadedOn' => $a->created_at->format('d-M-Y'),
            ]))->values(),
        ]);
    }

    public function download(GeneralDocument $document, GeneralDocumentAttachment $attachment)
    {
        abort_unless($attachment->general_document_id === $document->id, 404);
        abort_unless(Storage::disk('public')->exists($attachment->stored_path), 404);
        return Storage::disk('public')->download($attachment->stored_path, $attachment->original_name);
    }

    public function share(Request $request, GeneralDocument $document)
    {
        $request->validate([
            'user_ids'   => 'required|array',
            'user_ids.*' => 'exists:users,id',
        ]);

        $document->shares()->delete();
        foreach ($request->user_ids as $uid) {
            GeneralDocumentShare::create([
                'general_document_id' => $document->id,
                'user_id'             => (int) $uid,
            ]);
        }

        return response()->json(['success' => true]);
    }

    public function destroy(GeneralDocument $document)
    {
        foreach ($document->attachments as $att) {
            Storage::disk('public')->delete($att->stored_path);
        }
        $document->delete();
        return response()->json(['success' => true]);
    }

    public function searchUsers(Request $request)
    {
        $q         = $request->get('q', '');
        $excludeId = Auth::id();

        $users = User::where('is_super_admin', false)
            ->where('is_active', true)
            ->where('id', '!=', $excludeId)
            ->where(function ($query) use ($q) {
                $query->where('name', 'like', "%{$q}%")
                      ->orWhere('email', 'like', "%{$q}%");
            })
            ->limit(8)
            ->get(['id', 'name', 'email']);

        return response()->json($users->map(fn($u) => [
            'id'       => $u->id,
            'name'     => $u->name,
            'email'    => $u->email,
            'initials' => strtoupper(substr($u->name, 0, 2)),
        ]));
    }

    private function formatBytes(int $bytes): string
    {
        if ($bytes < 1024) return $bytes . ' B';
        if ($bytes < 1048576) return round($bytes / 1024, 1) . ' KB';
        return round($bytes / 1048576, 1) . ' MB';
    }
}
