<?php
/**
 * CustomerdocumentController
 *
 * Handles listing, creating, editing, and toggling customer documents.
 * Fixed: Customer ownership validation, standardized validation, security hardening.
 */
class CustomerdocumentController extends Controller
{
    /** Allowed upload extension whitelist */
    private static $allowedExtensions = array('pdf', 'doc', 'docx', 'png', 'jpg', 'jpeg');
    /** Max upload size in bytes (5 MB) */
    private static $maxFileSize = 5242880;

    public function filters()
    {
        return array('accessControl');
    }

    /**
     * Fixed accessRules: Added customer ownership check for document actions.
     * Yii1 lowercases action IDs - always use lowercase here.
     */
    public function accessRules()
    {
        return array(
            array('allow', 'actions' => array('login', 'error', 'logout'), 'users' => array('*')),
            array(
                'allow',
                'actions' => array(
                    'index', 'getlist', 'create', 'save', 'disable',
                    'getstates'
                ),
                'expression' => '$user->isMember()',
            ),
            array('deny', 'users' => array('*')),
        );
    }

    /**
     * Get customer_id from request (POST/GET param).
     */
    private function _getCustomerIdFromRequest()
    {
        $customerId = Yii::app()->request->getParam('customer_id', Yii::app()->request->getPost('CustomerDocuments.customer_id', 0));
        return (int) $customerId;
    }

    /**
     * Validate if current user owns or has admin access to the customer.
     */
    private function _validateCustomerAccess($customerId)
    {
        if ($customerId <= 0 || Yii::app()->user->getState('user_group_id') == 1) {
            return true; // Admins can access all
        }
        $customer = Customers::model()->findByPk($customerId);
        return $customer && $customer->created_by == Yii::app()->user->id;
    }

    public function actionIndex()
    {
        $this->render('index');
    }

    public function actionGetList()
    {
        $request = Yii::app()->request;
        if (!$request->isPostRequest) {
            throw new CHttpException(400, 'Invalid request method.');
        }

        try {
            $draw = (int) $request->getPost('draw', 1);
            $offset = (int) $request->getPost('start', 0);
            $limit = max(1, min((int) $request->getPost('length', 10), 100));
            $customerId = (int) $request->getPost('customer_id', 0);
            $searchValue = trim((string) @$request->getPost('search.value', ''));

            // Validate customer access if specified
            if ($customerId > 0 && !$this->_validateCustomerAccess($customerId)) {
                echo CJSON::encode(array('draw' => $draw, 'recordsTotal' => 0, 'recordsFiltered' => 0, 'data' => array()));
                Yii::app()->end();
            }

            $baseWhere = "cd.isActive = 'Y'";
            $baseParams = array();
            if ($searchValue !== '') {
                $baseWhere .= " AND (cd.id LIKE :search OR cd.document_title LIKE :search OR cd.customer_document LIKE :search)";
                $baseParams[':search'] = '%' . $searchValue . '%';
            }
            if ($customerId > 0) {
                $baseWhere .= ' AND cd.customer_id = :cid';
                $baseParams[':cid'] = $customerId;
            }

            $count = (int) Yii::app()->db->createCommand()
                ->select('COUNT(*)')->from('customer_documents cd')
                ->where($baseWhere, $baseParams)->queryScalar();

            $rows = Yii::app()->db->createCommand()
                ->select('cd.id, cd.document_title, cd.customer_document, cd.isActive, c.customer_name')
                ->from('customer_documents cd')
                ->leftJoin('customers c', 'c.id = cd.customer_id')
                ->where($baseWhere, $baseParams)
                ->order('cd.id ASC')->limit($limit)->offset($offset)
                ->queryAll();

            $rowData = array();
            $counter = $offset;
            foreach ($rows as $row) {
                $rowData[] = array(
                    ++$counter,
                    CHtml::encode($row['customer_name']),
                    CHtml::encode($row['document_title']),
                    CHtml::encode($row['customer_document']),
                    array(
                        'id' => (int) $row['id'],
                        'title' => $row['document_title'],
                        'document' => $row['customer_document'],
                        'status' => $row['isActive'],
                    ),
                );
            }

            echo CJSON::encode(array(
                'draw' => $draw,
                'recordsTotal' => $count,
                'recordsFiltered' => $count,
                'data' => $rowData,
            ));
        } catch (Exception $e) {
            Yii::log('actionGetList error: ' . $e->getMessage(), CLogger::LEVEL_ERROR);
            echo CJSON::encode(array(
                'draw' => isset($draw) ? $draw : 1,
                'recordsTotal' => 0,
                'recordsFiltered' => 0,
                'data' => array(),
                'error' => 'An error occurred while fetching records.',
            ));
        }
    }

    public function actionCreate()
    {
        $id = (int) Yii::app()->request->getParam('id', 0);
        $model = new CustomerDocuments();

        if ($id > 0) {
            $existing = CustomerDocuments::model()->findByPk($id);
            if ($existing === null) {
                throw new CHttpException(404, 'Document not found.');
            }
            $model = $existing;
            // Validate ownership
            if (!$this->_validateCustomerAccess($model->customer_id)) {
                throw new CHttpException(403, 'Access denied.');
            }
        }

        $this->_suppressDuplicateJquery();
        $allCustomers = Customers::model()->findAll(array('order' => 'customer_name ASC'));
        $customers = CHtml::listData($allCustomers, 'id', 'customer_name');

        $this->render('create', array(
            'model' => $model,
            'customers' => $customers,
        ), false, true);
    }

    public function actionSaveDocument()
    {
        $request = Yii::app()->request;
        if (!$request->isPostRequest) {
            throw new CHttpException(400, 'Invalid request method.');
        }

        $postData = $request->getPost('CustomerDocuments');
        if (empty($postData)) {
            echo CJSON::encode(array('status' => 'error', 'message' => 'No data submitted.'));
            return;
        }

        $id = isset($postData['id']) ? (int) $postData['id'] : 0;
        $model = new CustomerDocuments();

        if ($id > 0) {
            $existing = CustomerDocuments::model()->findByPk($id);
            if ($existing === null) {
                echo CJSON::encode(array('status' => 'error', 'message' => 'Record not found.'));
                return;
            }
            $model = $existing;
        }

        // Validate customer ownership
        $customerId = isset($postData['customer_id']) ? (int) $postData['customer_id'] : 0;
        if (!$this->_validateCustomerAccess($customerId)) {
            echo CJSON::encode(array('status' => 'error', 'message' => 'Access denied to customer.'));
            return;
        }

        $model->attributes = $postData;
        $model->customer_id = $customerId;

        $uploadedFile = CUploadedFile::getInstance($model, 'customer_document');
        if ($uploadedFile !== null) {
            $fileError = $this->_validateUploadedFile($uploadedFile);
            if ($fileError !== null) {
                echo CJSON::encode(array('status' => 'error', 'message' => $fileError));
                return;
            }

            $uploadPath = Yii::app()->basePath . '/../uploads/customer_docs/';
            if (!is_dir($uploadPath) && !mkdir($uploadPath, 0755, true)) {
                echo CJSON::encode(array('status' => 'error', 'message' => 'Upload directory could not be created.'));
                return;
            }

            // Delete old file if replacing
            if (!$model->isNewRecord && !empty($model->customer_document)) {
                $oldFile = $uploadPath . $model->customer_document;
                if (is_file($oldFile)) {
                    @unlink($oldFile);
                }
            }

            $fileName = time() . '_' . preg_replace('/[^a-zA-Z0-9_\-\.]/', '_', $uploadedFile->name);
            if (!$uploadedFile->saveAs($uploadPath . $fileName)) {
                echo CJSON::encode(array('status' => 'error', 'message' => 'File could not be saved.'));
                return;
            }
            $model->customer_document = $fileName;
        }

        if ($model->validate()) {
            if ($model->save(false)) {
                echo CJSON::encode(array('status' => 'success', 'id' => (int) $model->id, 'filename' => $model->customer_document));
            } else {
                echo CJSON::encode(array('status' => 'error', 'message' => 'Record could not be saved.'));
            }
        } else {
            $errors = array();
            foreach ($model->getErrors() as $attribute => $attributeErrors) {
                $errors[$attribute] = $attributeErrors;
            }
            echo CJSON::encode(array('status' => 'error', 'errors' => $errors));
        }
    }

    public function actionDisable()
    {
        $request = Yii::app()->request;
        $id = (int) $request->getParam('id', 0);
        $status = $request->getParam('status', 'Y');

        if ($id <= 0) {
            echo CJSON::encode(array('status' => 'error', 'message' => 'Invalid ID.'));
            return;
        }

        $model = CustomerDocuments::model()->findByPk($id);
        if ($model === null) {
            echo CJSON::encode(array('status' => 'error', 'message' => 'Record not found.'));
            return;
        }

        // Validate ownership
        if (!$this->_validateCustomerAccess($model->customer_id)) {
            echo CJSON::encode(array('status' => 'error', 'message' => 'Access denied.'));
            return;
        }

        $model->isActive = ($status === 'Y') ? 'N' : 'Y';
        if ($model->save(false)) {
            echo CJSON::encode(array('status' => 'success', 'isActive' => $model->isActive));
        } else {
            echo CJSON::encode(array('status' => 'error', 'message' => 'Status could not be updated.'));
        }
    }

    private function _validateUploadedFile(CUploadedFile $file)
    {
        $ext = strtolower($file->extensionName);
        if (!in_array($ext, self::$allowedExtensions, true)) {
            return 'Invalid file type. Allowed types: ' . implode(', ', self::$allowedExtensions) . '.';
        }
        if ($file->size > self::$maxFileSize) {
            return 'File exceeds the maximum allowed size of ' . (self::$maxFileSize / 1048576) . ' MB.';
        }
        return null;
    }

    private function _suppressDuplicateJquery()
    {
        Yii::app()->clientScript->scriptMap = array(
            '*jquery.js' => false,
            '*jquery.min.js' => false,
            'jquery.min.js' => false,
            '*jquery-ui.js' => false,
            '*jquery-ui.min.js' => false,
            'jquery-2.1.4.min.js' => false,
        );
    }
}
