<?php

require_once BASE_PATH . '/app/controllers/customer/CustomerBaseController.php';
require_once BASE_PATH . '/app/models/User.php';
require_once BASE_PATH . '/app/models/SystemSetting.php';

class CustomerAvatarController extends CustomerBaseController
{
    private User $userModel;
    private SystemSetting $systemSettingModel;

    public function __construct()
    {
        $this->requireCustomer();
        $this->userModel = new User();
        $this->systemSettingModel = new SystemSetting();
    }

    public function upload(): void
    {
        $this->requirePost();
        $this->validateCsrf();

        $customerId = (int) $_SESSION['user']['id'];
        $customer = $this->userModel->findById($customerId);

        if (!$customer) {
            $this->flashError('Không thể tải tài khoản.');
            $this->redirect('customer/profile');
        }

        try {
            $newAvatar = $this->storeUploadedAvatar();
        } catch (RuntimeException $e) {
            $this->flashError($e->getMessage());
            $this->redirect('customer/profile');
        }

        try {
            $this->userModel->updateAvatar($customerId, $newAvatar);
        } catch (Throwable $e) {
            $this->deleteLocalAvatar($newAvatar);
            $this->flashError('Không thể lưu ảnh đại diện.');
            $this->redirect('customer/profile');
        }

        $_SESSION['user']['avatar'] = $newAvatar;
        $_SESSION['user']['avatar_version'] = time();
        $this->deleteLocalAvatar($customer['avatar'] ?? null);
        $this->flashSuccess('Đã cập nhật ảnh đại diện.');
        $this->redirect('customer/profile');
    }

    public function delete(): void
    {
        $this->requirePost();
        $this->validateCsrf();

        $customerId = (int) $_SESSION['user']['id'];
        $customer = $this->userModel->findById($customerId);

        if (!$customer || empty($customer['avatar'])) {
            $this->flashError('Bạn chưa có ảnh đại diện để xóa.');
            $this->redirect('customer/profile');
        }

        try {
            $this->userModel->updateAvatar($customerId, null);
        } catch (Throwable $e) {
            $this->flashError('Không thể xóa ảnh đại diện.');
            $this->redirect('customer/profile');
        }

        $_SESSION['user']['avatar'] = null;
        $_SESSION['user']['avatar_version'] = time();
        $this->deleteLocalAvatar($customer['avatar']);
        $this->flashSuccess('Đã xóa ảnh đại diện.');
        $this->redirect('customer/profile');
    }

    private function storeUploadedAvatar(): string
    {
        if (!isset($_FILES['avatar'])
            || !is_array($_FILES['avatar'])
            || ($_FILES['avatar']['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
            throw new RuntimeException('Vui lòng chọn ảnh đại diện.');
        }

        $file = $_FILES['avatar'];
        if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
            throw new RuntimeException('Upload ảnh đại diện thất bại.');
        }

        if (!is_uploaded_file((string) $file['tmp_name'])) {
            throw new RuntimeException('Tệp upload không hợp lệ.');
        }

        $maxBytes = $this->maxUploadBytes();
        if ((int) $file['size'] <= 0 || (int) $file['size'] > $maxBytes) {
            throw new RuntimeException(
                'Ảnh đại diện tối đa ' . (int) ($maxBytes / 1024 / 1024) . 'MB.'
            );
        }

        $finfo = new finfo(FILEINFO_MIME_TYPE);
        $mime = $finfo->file((string) $file['tmp_name']);
        $allowed = [
            'image/jpeg' => 'jpg',
            'image/png' => 'png',
            'image/webp' => 'webp'
        ];

        if (!isset($allowed[$mime])) {
            throw new RuntimeException('Chỉ hỗ trợ JPG, PNG hoặc WEBP.');
        }

        $directory = BASE_PATH . '/public/uploads/avatars';
        if (!is_dir($directory) && !mkdir($directory, 0755, true)) {
            throw new RuntimeException('Không thể tạo thư mục lưu ảnh.');
        }

        $filename = 'avatar_' . bin2hex(random_bytes(10)) . '.' . $allowed[$mime];
        if (!move_uploaded_file((string) $file['tmp_name'], $directory . '/' . $filename)) {
            throw new RuntimeException('Không thể lưu ảnh đại diện.');
        }

        return 'uploads/avatars/' . $filename;
    }

    private function maxUploadBytes(): int
    {
        $settings = $this->systemSettingModel->getAll();
        $maxUploadMb = (int) ($settings['max_upload_mb']['value'] ?? 5);

        if ($maxUploadMb < 1 || $maxUploadMb > 20) {
            $maxUploadMb = 5;
        }

        return $maxUploadMb * 1024 * 1024;
    }

    private function deleteLocalAvatar(?string $avatar): void
    {
        if (!is_string($avatar)) {
            return;
        }

        $relative = str_replace('\\', '/', ltrim($avatar, '/'));
        $prefix = 'uploads/avatars/';
        if (!str_starts_with($relative, $prefix)) {
            return;
        }

        $filename = substr($relative, strlen($prefix));
        if ($filename === '' || basename($filename) !== $filename
            || !preg_match('/^avatar_[a-f0-9]{20}\.(jpg|png|webp)$/', $filename)) {
            return;
        }

        $path = BASE_PATH . '/public/uploads/avatars/' . $filename;
        if (is_file($path)) {
            unlink($path);
        }
    }
}
