<?php

declare(strict_types=1);

namespace App\Http\Controllers\Market;

use App\Http\Controllers\FilesMainController;
use App\Http\Controllers\Helpers\ResponseHelper;
use App\Models\Market\CooperativeDocument;
use App\Models\Market\Organization;
use App\Models\FileList;
use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
use App\Enums\UserActions;
use Hypervel\Support\Str;

class CooperativeDocumentController
{
    public function listDocuments(Request $request)
    {
        $orgHash = $request->input('orgHash');
        if (!$orgHash) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $org = Organization::where('hashkey', $orgHash)->first();
        if (!$org) {
            return ResponseHelper::returnError('Organization not found', 404);
        }

        // Get latest versions (where parent_hashkey IS NULL or it is the latest in its group)
        // For simplicity, we'll fetch all active docs and group them by parent_hashkey or hashkey
        $allDocs = CooperativeDocument::where('organization_id', $org->id)
            ->where('is_active', true)
            ->orderBy('version_number', 'desc')
            ->get();

        $fileHashes = $allDocs->pluck('file_hashkey')->filter()->unique()->toArray();
        $fileLists = FileList::whereIn('hashkey', $fileHashes)->with('fileContent')->get()->keyBy('hashkey');

        $grouped = [];
        foreach ($allDocs as $doc) {
            $rootKey = $doc->parent_hashkey ?? $doc->hashkey;
            if (!isset($grouped[$rootKey])) {
                $grouped[$rootKey] = [];
            }
            $grouped[$rootKey][] = $doc;
        }

        $data = [];
        foreach ($grouped as $rootKey => $versions) {
            $latest = $versions[0]; // ordered desc by version_number
            $fileList = $fileLists[$latest->file_hashkey] ?? null;
            if ($fileList) {
                $history = [];
                foreach ($versions as $v) {
                    $vFileList = $fileLists[$v->file_hashkey] ?? null;
                    if ($vFileList) {
                        $history[] = [
                            'hashkey' => $v->hashkey,
                            'version' => $v->version_number,
                            'name' => $vFileList->filename,
                            'date' => $v->created_at ? $v->created_at->format('Y-m-d H:i') : null,
                            'note' => $v->revision_note,
                            'url' => $vFileList->resolvedUrl()
                        ];
                    }
                }

                $data[] = [
                    'hashkey' => $latest->hashkey,
                    'parent_hashkey' => $latest->parent_hashkey,
                    'name' => $fileList->filename,
                    'type' => $latest->document_type ?? 'Document',
                    'date' => $latest->created_at ? $latest->created_at->toDateString() : null,
                    'size' => $this->formatBytes($fileList->fileContent->size_in_bytes ?? 0),
                    'url' => $fileList->resolvedUrl(),
                    'version' => $latest->version_number,
                    'note' => $latest->revision_note,
                    'history' => $history
                ];
            }
        }

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

    public function uploadDocument(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ManageOrganizations)) {
            return ResponseHelper::returnUnauthorized();
        }

        $orgHash = $request->input('orgHash');
        $docType = $request->input('type', 'OTHERS');
        
        if (!$orgHash || !$request->hasFile('file')) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $org = Organization::where('hashkey', $orgHash)->first();
        if (!$org) {
            return ResponseHelper::returnError('Organization not found', 404);
        }

        $file = $request->file('file');
        $filename = $file->getClientFilename();

        $fileList = FilesMainController::uploadFileList(
            $file,
            $filename,
            $filename,
            'Cooperative Document for ' . $org->name,
            ['type' => 'coop_document', 'org_id' => $org->id],
            'CooperativeDocuments',
            [],
            0,
            'cooperative_document',
        );

        if (!$fileList || !isset($fileList->hashkey)) {
            return ResponseHelper::returnError('File upload failed');
        }

        $doc = new CooperativeDocument([
            'hashkey' => (string) Str::uuid(),
            'organization_id' => $org->id,
            'file_hashkey' => $fileList->hashkey,
            'document_type' => $docType,
            'created_by' => Auth::id(),
            'is_active' => true,
        ]);

        if ($doc->save()) {
            return response()->json([
                'success' => true,
                'message' => 'Document uploaded successfully',
                'data' => [
                    'hashkey' => $doc->hashkey,
                    'name' => $filename,
                    'url' => $fileList->resolvedUrl()
                ]
            ]);
        }

        return ResponseHelper::returnError('Failed to save document record');
    }

    public function reviseDocument(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ManageOrganizations)) {
            return ResponseHelper::returnUnauthorized();
        }

        $parentHash = $request->input('parentHash');
        $note = $request->input('note');
        
        if (!$parentHash || !$request->hasFile('file')) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $parentDoc = CooperativeDocument::where('hashkey', $parentHash)->first();
        if (!$parentDoc) {
            return ResponseHelper::returnError('Original document not found', 404);
        }

        // The real parent is either its own parent or it is the parent
        $rootHash = $parentDoc->parent_hashkey ?? $parentDoc->hashkey;
        
        // Find highest version number
        $lastVersion = CooperativeDocument::where('hashkey', $rootHash)
            ->orWhere('parent_hashkey', $rootHash)
            ->max('version_number');

        $file = $request->file('file');
        $filename = $file->getClientFilename();

        $fileList = FilesMainController::uploadFileList(
            $file,
            $filename,
            $filename,
            'Revision of ' . $parentDoc->hashkey,
            ['type' => 'coop_document_revision', 'parent_id' => $parentDoc->id],
            'CooperativeDocuments',
            [],
            0,
            'cooperative_document_revision',
        );

        if (!$fileList) {
            return ResponseHelper::returnError('File upload failed');
        }

        $doc = new CooperativeDocument([
            'hashkey' => (string) Str::uuid(),
            'parent_hashkey' => $rootHash,
            'version_number' => $lastVersion + 1,
            'organization_id' => $parentDoc->organization_id,
            'file_hashkey' => $fileList->hashkey,
            'document_type' => $parentDoc->document_type,
            'revision_note' => $note,
            'created_by' => Auth::id(),
            'is_active' => true,
        ]);

        if ($doc->save()) {
            return response()->json([
                'success' => true,
                'message' => 'Revision uploaded successfully',
                'data' => $doc
            ]);
        }

        return ResponseHelper::returnError('Failed to save revision record');
    }

    public function deleteDocument(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ManageOrganizations)) {
            return ResponseHelper::returnUnauthorized();
        }

        $hashkey = $request->input('hashkey');
        if (!$hashkey) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $doc = CooperativeDocument::where('hashkey', $hashkey)->first();
        if (!$doc) {
            return ResponseHelper::returnError('Document not found', 404);
        }

        // If it's a version, we might want to just deactivate that version.
        // If it's the root, we might want to deactivate all versions.
        // For now, let's just deactivate the specific one.
        $doc->is_active = false;
        if ($doc->save()) {
            return response()->json(['success' => true, 'message' => 'Document/Revision deleted']);
        }

        return ResponseHelper::returnError('Failed to delete document');
    }

    private function formatBytes($bytes, $precision = 1)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= (1 << (10 * $pow));
        return round($bytes, $precision) . ' ' . $units[$pow];
    }
}
