<?php
namespace SabaiApps\Directories\Component\Form\Controller;

use SabaiApps\Directories\Component\Form\FormComponent;
use SabaiApps\Directories\Controller;
use SabaiApps\Directories\Context;

/**
 * UploadFile controller for handling file uploads in forms.
 * Handles file upload requests, validation, storage, and file serving.
 */
class UploadFile extends Controller {

	protected function _doExecute( Context $context ) {
		// Handle file load requests (GET)
		if ( ! $context->getRequest()->isPostMethod() ) {
			$this->_handleLoadFileRequest();
		}

		// Validate required POST parameters and uploaded file
		if ( empty( $_FILES )
			|| ( ! $form_build_id = $context->getRequest()->asStr( 'drts_form_build_id' ) )
			|| ( ! $form_file_field_id = $context->getRequest()->asStr( 'drts_form_file_field_id' ) )
		) {
			$context->setBadRequestError();
			return;
		}

		if ( ( ! $_file = @$_FILES['drts_form_upload'] )
			|| ( ! $token = $this->Form_Form_useUploadToken( $form_build_id, $form_file_field_id ) )
		) {
			$context->setBadRequestError();
			return;
		}

		// Retrieve or initialize form storage for uploaded files
		if ( ! $storage = $this->getComponent( 'Form' )->getFormStorage( $form_build_id ) ) {
			$storage = array();
		}
		if ( ! isset( $storage['form_upload_files'][ $form_file_field_id ] ) ) {
			$storage['form_upload_files'][ $form_file_field_id ] = array();
		}

		// Check file upload limits
		if ( ! empty( $token['max_num_files'] ) ) {
			if ( count( $storage['form_upload_files'][ $form_file_field_id ] ) > $token['max_num_files'] * 2 ) {
				$context->setError( __( 'You have already uploaded enough files!', 'directories-pro' ) );
				return;
			}
		}

		// Prepare file array for upload
		$file = array(
			'name'     => $_file['name'],
			'type'     => $_file['type'],
			'size'     => $_file['size'],
			'tmp_name' => $_file['tmp_name'],
			'error'    => $_file['error'],
		);

		// Try uploading the file and handle errors
		try {
			$file = $this->Form_Upload( $file, $token['upload_settings'] );
		} catch ( \Exception $e ) {
			$context->setError( $e->getMessage() );
			@unlink( $file['tmp_name'] );
			return;
		}
		@unlink( $file['tmp_name'] );

		// Generate file ID and update storage
		$file_id = $file['saved_file_name'];
		if ( isset( $token['upload_settings']['upload_file_name_prefix'] ) ) {
			$file_id = substr( $file_id, strlen( $token['upload_settings']['upload_file_name_prefix'] ) );
		}

		if ( isset( $storage ) ) {
			// Add file uploaded with this token
			$storage['form_upload_files'][ $form_file_field_id ][ $file_id ] = $file;
			$this->getComponent( 'Form' )->setFormStorage( $form_build_id, $storage );
		}

		$file['_id'] = $file_id;

		// Cache the uploaded file for later retrieval
		$this->getPlatform()->setCache( $file, $file_id, FormComponent::FILE_UPLOAD_CACHE_LIFETIME, FormComponent::FILE_UPLOAD_CACHE_GROUP );

		// Return file info as JSON or output file ID
		if ( $form_file_field_id ) {
			$context->setContentType( 'json' );
			$context->addTemplate( 'system_list' )->setAttributes( array( 'list' => array( $file ) ) );
		} else {
			echo '_' . $file_id;
			exit;
		}
	}

	/**
	 * Handles file load requests (GET) for serving uploaded files.
	 */
	protected function _handleLoadFileRequest() {
		if ( ! empty( $_GET['load'] ) ) {
			if ( strpos( $_GET['load'], '_' ) === 0 ) {
				$file = $this->getPlatform()->getCache( substr( $_GET['load'], 1 ), FormComponent::FILE_UPLOAD_CACHE_GROUP );
				if ( ! empty( $file['id'] ) ) {
					// Already saved, probably when form submission failed previously
					$file = $this->getPlatform()->getFile( $file['id'] );
				} else {
					$file['path'] = $file['saved_file_path'];
				}
			} else {
				$file = $this->getPlatform()->getFile( $_GET['load'] );
			}
			if ( $file ) {
				if ( isset( $file['type'] ) ) {
					header( 'Content-Type: ' . $file['type'] );
				}
				header( 'Content-Disposition: inline; filename*=UTF-8\'\'' . urlencode( isset( $file['title'] ) ? $file['title'] : ( isset( $file['name'] ) ? $file['name'] : basename( $file['path'] ) ) ) );
				header( 'Content-Length: ' . ( isset( $file['size'] ) ? $file['size'] : filesize( $file['path'] ) ) );
				readfile( $file['path'] );
			}
		}
		exit;
	}
}
