<?php

namespace FluentSupport\App\Http\Controllers;

use FluentSupport\App\Models\Attachment;
use FluentSupport\App\Models\Ticket;
use FluentSupport\App\Services\EmailNotification\Settings;
use FluentSupport\App\Services\Helper;
use FluentSupport\Framework\Http\Request\Request;
use FluentSupport\App\Services\Includes\UploadService;

/**
 * UploaderController class is responsible for uploading file
 * @package FluentSupport\App\Http\Controllers
 *
 * @version 1.0.0
 */
class UploaderController extends Controller
{
    /**
     * uploadTicketFiles method will upload all the attached file in a ticket
     * @param Request $request
     * @return array[]
     * @throws \FluentSupport\Framework\Validator\ValidationException
     */
    public function uploadTicketFiles(Request $request)
    {
        $settings = (new Settings())->globalBusinessSettings();
        $maxFileSize = floatval($settings['max_file_size']);
        $mimeHeadings = Helper::getAcceptedMimeHeadings();
        $maxSizeBytes = $maxFileSize * 1024;
        $imageType = $request->type ? $request->type : null;

        $this->validateUploadedFiles($request->files(), $maxSizeBytes, $mimeHeadings, $maxFileSize);
        $ticketId = $this->resolveTicketId($request);
        $person = $this->resolvePerson($ticketId, $request);

        $this->checkPermissionToUploadFile($person);

        try {
            $uploadedFiles = UploadService::handleTempFileUpload($request->files());
        } catch (\Exception $e) {
            return $this->sendError([
                'message' => Helper::getSafeErrorMessage($e),
            ]);
        }

        if (is_wp_error($uploadedFiles)) {
            return $this->sendError([
                'message' => $uploadedFiles->get_error_message(),
            ]);
        }

        $attachmentHashes = $this->createAttachmentRecords($uploadedFiles, $ticketId, $person, $imageType);

        return [
            'attachments' => $attachmentHashes,
        ];
    }

    private function validateUploadedFiles($files, $maxSizeBytes, $mimeHeadings, $maxFileSize)
    {
        $validationRules = [
            'file' => 'max:' . $maxSizeBytes . '|mimetypes:' . implode(',', Helper::ticketAcceptedFileMiles()),
        ];

        $validationMessages = [
            // translators: %s is a comma-separated list of allowed file types (e.g., "jpg, png, pdf")
            'file.mimetypes' => sprintf(__('Only %s files are allowed.', 'fluent-support'), implode(', ', $mimeHeadings)),
            // translators: %.01f is the maximum file size in megabytes
            'file.max'       => sprintf(__('The file cannot be more than %.01fMB. Please upload somewhere like Dropbox/Google Drive and paste the link in the response', 'fluent-support'), $maxFileSize),
        ];

        $this->validate($files, $validationRules, $validationMessages);
    }

    private function resolveTicketId($request)
    {
        $ticketId = $request->getSafe('ticket_id', 'intval');
        return $ticketId == 'undefined' ? null : $ticketId;
    }

    private function resolvePerson($ticketId, Request $request)
    {
        if ($request->getSafe('is_agent', 'sanitize_text_field') == 'yes') {
            return Helper::getCurrentAgent();
        }

        if ($ticketId && Helper::isPublicSignedTicketEnabled()) {
            $intendedTicketHash = $request->getSafe('intended_ticket_hash', 'sanitize_text_field');
            if ($intendedTicketHash && $intendedTicketHash != 'undefined') {
                $ticket = Ticket::with(['customer'])
                    ->where('hash', $intendedTicketHash)
                    ->find($ticketId);

                if ($ticket && $ticket->customer) {
                    return $ticket->customer;
                }
            }
        }

        return Helper::getCurrentPerson();
    }

    private function checkPermissionToUploadFile($person)
    {
        if (!$person) {
            return $this->sendError([
                'message' => __('You do not have permission to upload a file', 'fluent-support'),
            ]);
        }

        if ($person->person_type === 'customer') {
            $disabledFields = apply_filters('fluent_support/disabled_ticket_fields', []);
            if (in_array('file_upload', $disabledFields)) {
                return $this->sendError([
                    'message' => __('You do not have permission to upload a file', 'fluent-support'),
                ]);
            }
        }
    }

    private function createAttachmentRecords($uploadedFiles, $ticketId, $person, $imageType)
    {
        $attachments = [];
        $full_path = null;

        foreach ($uploadedFiles as $file) {
            if (empty($file['file_path'])) continue;

            $fileData = [
                'ticket_id' => intval($ticketId) ?: NULL,
                'person_id' => intval($person->id),
                'file_type' => $file['type'],
                'file_path' => $file['file_path'],
                'full_url'  => esc_url($file['url']),
                'title'     => sanitize_file_name($file['name']),
                'driver'    => 'local',
                'status'    => 'in-active',
                'settings'  => [
                    'local_temp_path' => $file['file_path'],
                ]
            ];

            if($imageType == 'direct_paste'){
                $full_path = esc_url($file['url']);
            }

            try {
                $attachment = Attachment::create($fileData);
                $attachments[] = $attachment->file_hash;
                do_action('fluent_support/attachment_uploaded_as_temp', $attachment, $ticketId);
                $driver = Helper::getUploadDriverKey();

                do_action_ref_array('fluent_support/attachment_uploaded_as_temp_' . $driver, [&$attachment, $ticketId]);
            } catch (\Exception $exception) {
                continue;
            }
        }

        return $imageType == 'direct_paste' ? $full_path : $attachments;
    }

    public function uploadImage(Request $request)
    {
        $images = $request->files();
        $ticketId = $this->resolveTicketId($request);

        $validationError = $this->isValidImageType($images);
        if ($validationError) {
            return $validationError;
        }

        try {
            $uploadedFiles = UploadService::handleUploadToLocal($ticketId, $images);
        } catch (\Exception $e) {
            return $this->sendError([
                'message' => Helper::getSafeErrorMessage($e),
            ]);
        }

        return [
            'images' => $uploadedFiles,
        ];
    }

    private function isValidImageType($images)
    {
        if (empty($images['image'])) {
            return $this->sendError([
                'message' => __('No image file provided.', 'fluent-support'),
            ]);
        }

        $file = $images['image'];
        $tempPath = $file->getPathname();
        $extension = strtolower($file->getClientOriginalExtension());
        $allowedExtensions = ['gif', 'ief', 'jpeg', 'jpg', 'webp', 'pjpeg', 'ktx', 'png'];

        if (!in_array($extension, $allowedExtensions)) {
            return $this->sendError([
                'message' => __('Invalid image file type.', 'fluent-support'),
            ]);
        }

        $allowedMimes = Helper::getMimeGroups()['images']['mimes'];
        $realMime = $this->detectMimeType($tempPath);

        if (!$realMime || !in_array($realMime, $allowedMimes)) {
            return $this->sendError([
                'message' => __('File content does not match the image type.', 'fluent-support'),
            ]);
        }

        return null;
    }

    private function detectMimeType($filePath)
    {
        if (function_exists('finfo_open')) {
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $mime = finfo_file($finfo, $filePath);
            finfo_close($finfo);
            return $mime;
        }

        if (function_exists('mime_content_type')) {
            return mime_content_type($filePath);
        }

        // getimagesize works for standard image formats as last resort
        $imageInfo = @getimagesize($filePath);
        return $imageInfo ? $imageInfo['mime'] : false;
    }
}
