<?php
declare(strict_types=1);

namespace App\Modules\Documents\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Core\Logger;
use App\Modules\Documents\Models\Document;

class DocumentController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'search'        => trim((string) $request->get('q', '')),
            'document_type' => $request->get('document_type', ''),
            'member_id'     => $request->get('member_id', ''),
        ];
        $page = max(1, (int) $request->get('page', 1));
        $result = Document::search($filters, 25, $page);

        return $this->view('Documents.Views.index', [
            'rows'       => $result['data'],
            'pagination' => $result['pagination'],
            'filters'    => $filters,
            'docTypes'   => Document::getDocumentTypes(),
        ]);
    }

    public function upload(Request $request, string $memberId): Response
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ? AND is_archived = 0", [(int) $memberId]);
        if (!$member) {
            return $this->redirect('/members')->withError('العضو غير موجود');
        }

        if ($request->method() === 'GET') {
            $existingDocs = Document::getForMember((int) $memberId);
            return $this->view('Documents.Views.upload', [
                'member'    => $member,
                'documents' => $existingDocs,
                'docTypes'  => Document::getDocumentTypes(),
            ]);
        }

        // POST — handle upload
        $documentType = trim($request->post('document_type', ''));
        $description = trim($request->post('description', ''));
        $relatedEntityType = trim($request->post('related_entity_type', ''));
        $relatedEntityId = $request->post('related_entity_id') ? (int) $request->post('related_entity_id') : null;

        if ($documentType === '') {
            return $this->redirect("/documents/upload/{$memberId}")->withError('نوع المستند مطلوب');
        }

        if (!$request->hasFile('document_file')) {
            return $this->redirect("/documents/upload/{$memberId}")->withError('يرجى اختيار ملف');
        }

        $file = $request->file('document_file');
        if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
            return $this->redirect("/documents/upload/{$memberId}")->withError('خطأ في رفع الملف');
        }

        // Validate file
        $maxSize = (int) config('filestorage.max_upload_size', 10485760); // 10MB
        if ($file['size'] > $maxSize) {
            return $this->redirect("/documents/upload/{$memberId}")->withError('حجم الملف يتجاوز الحد المسموح (' . round($maxSize / 1048576) . ' ميجا)');
        }

        $allowedTypes = ['application/pdf', 'image/jpeg', 'image/png', 'image/jpg'];
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        $mimeType = $finfo->file($file['tmp_name']);
        if (!in_array($mimeType, $allowedTypes)) {
            return $this->redirect("/documents/upload/{$memberId}")->withError('نوع الملف غير مسموح (PDF, JPG, PNG فقط)');
        }

        // Generate stored filename
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $storedFilename = 'doc_' . (int) $memberId . '_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.' . $ext;

        // Ensure upload directory exists
        $uploadDir = App::getInstance()->basePath() . '/storage/uploads/documents/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        $filePath = $uploadDir . $storedFilename;
        if (!move_uploaded_file($file['tmp_name'], $filePath)) {
            return $this->redirect("/documents/upload/{$memberId}")->withError('فشل في حفظ الملف');
        }

        $employee = App::getInstance()->currentEmployee();

        $doc = Document::create([
            'member_id'           => (int) $memberId,
            'document_type'       => $documentType,
            'original_filename'   => $file['name'],
            'stored_filename'     => $storedFilename,
            'file_path'           => 'storage/uploads/documents/' . $storedFilename,
            'file_size'           => (int) $file['size'],
            'mime_type'           => $mimeType,
            'related_entity_type' => $relatedEntityType ?: null,
            'related_entity_id'   => $relatedEntityId,
            'description'         => $description ?: null,
            'uploaded_by'         => $employee ? (int) $employee->id : null,
        ]);

        EventBus::dispatch('document.uploaded', [
            'document_id' => (int) $doc->id,
            'member_id'   => (int) $memberId,
            'type'        => $documentType,
            'filename'    => $file['name'],
        ]);

        return $this->redirect("/documents/upload/{$memberId}")->withSuccess('تم رفع المستند: ' . $file['name']);
    }

    public function download(Request $request, string $id): Response
    {
        $doc = Document::find((int) $id);
        if (!$doc || $doc->is_archived) {
            return $this->redirect('/documents')->withError('المستند غير موجود');
        }

        $fullPath = App::getInstance()->basePath() . '/' . $doc->file_path;
        if (!file_exists($fullPath)) {
            return $this->redirect('/documents')->withError('الملف غير موجود على الخادم');
        }

        $response = new Response();
        return $response->download($fullPath, $doc->original_filename);
    }

    public function preview(Request $request, string $id): Response
    {
        $doc = Document::find((int) $id);
        if (!$doc || $doc->is_archived) {
            return $this->redirect('/documents')->withError('المستند غير موجود');
        }

        $fullPath = App::getInstance()->basePath() . '/' . $doc->file_path;
        if (!file_exists($fullPath)) {
            return $this->redirect('/documents')->withError('الملف غير موجود على الخادم');
        }

        header('Content-Type: ' . $doc->mime_type);
        header('Content-Disposition: inline; filename="' . $doc->original_filename . '"');
        header('Content-Length: ' . filesize($fullPath));
        readfile($fullPath);
        exit;
    }

    public function archive(Request $request, string $id): Response
    {
        $doc = Document::find((int) $id);
        if (!$doc) {
            return $this->redirect('/documents')->withError('المستند غير موجود');
        }

        $employee = App::getInstance()->currentEmployee();
        $db = App::getInstance()->db();

        $db->update('documents', [
            'is_archived' => 1,
            'archived_at' => date('Y-m-d H:i:s'),
            'archived_by' => $employee ? (int) $employee->id : null,
            'updated_at'  => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        EventBus::dispatch('document.archived', [
            'document_id' => (int) $id,
            'member_id'   => (int) $doc->member_id,
        ]);

        $redirectUrl = $request->post('redirect_url', '/documents');
        return $this->redirect($redirectUrl)->withSuccess('تم أرشفة المستند');
    }

    public function memberDocuments(Request $request, string $memberId): Response
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);
        $docs = Document::getForMember((int) $memberId);

        return $this->view('Documents.Views.index', [
            'rows'       => array_map(fn($d) => array_merge($d, ['member_name' => $member['full_name_ar'] ?? '', 'membership_number' => $member['membership_number'] ?? '']), $docs),
            'pagination' => ['last_page' => 1, 'current_page' => 1],
            'filters'    => ['search' => '', 'document_type' => '', 'member_id' => (string) $memberId],
            'docTypes'   => Document::getDocumentTypes(),
            'member'     => $member,
        ]);
    }
}