<?php

declare(strict_types=1);

namespace app\admin\controller;

use ba\Terminal;
use ba\TableManager;
use support\think\Db;
use app\admin\model\AdminLog;
use app\common\library\Upload;
use app\common\library\upload\WebmanUploadedFile;
use app\common\controller\Backend;
use Webman\Http\Request;
use support\Response;

class Ajax extends Backend
{
    protected array $noNeedPermission = ['*'];
    protected array $noNeedLogin = ['terminal'];

    public function upload(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        AdminLog::instance($request)->setTitle(__('upload'));
        $file = $request->file('file');
        if (!$file) {
            return $this->error(__('No files were uploaded'));
        }
        $file = new WebmanUploadedFile($file);
        $driver = $request->get('driver', $request->post('driver', 'local'));
        $topic = $request->get('topic', $request->post('topic', 'default'));
        try {
            $upload = new Upload();
            $attachment = $upload
                ->setFile($file)
                ->setDriver($driver)
                ->setTopic($topic)
                ->upload(null, $this->auth->id);
            unset($attachment['create_time'], $attachment['quote']);
        } catch (\Throwable $e) {
            return $this->error($e->getMessage());
        }
        return $this->success(__('File uploaded successfully'), [
            'file' => $attachment ?? []
        ]);
    }

    public function area(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        return $this->success('', get_area($request));
    }

    public function buildSuffixSvg(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        $suffix = $request->get('suffix', $request->post('suffix', 'file'));
        $background = $request->get('background', $request->post('background'));
        $content = build_suffix_svg((string) $suffix, (string) $background);
        return response($content, 200, [
            'Content-Length' => strlen($content),
            'Content-Type' => 'image/svg+xml'
        ]);
    }

    public function getDatabaseConnectionList(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        $quickSearch = $request->get('quickSearch', '');
        $connections = config('thinkorm.connections', config('database.connections', []));
        $desensitization = [];
        foreach ($connections as $key => $connection) {
            $connConfig = TableManager::getConnectionConfig($key);
            $desensitization[] = [
                'type' => $connConfig['type'] ?? 'mysql',
                'database' => substr_replace($connConfig['database'] ?? '', '****', 1, strlen($connConfig['database'] ?? '') > 4 ? 2 : 1),
                'key' => $key,
            ];
        }
        if ($quickSearch) {
            $desensitization = array_values(array_filter($desensitization, function ($item) use ($quickSearch) {
                return preg_match("/$quickSearch/i", $item['key']);
            }));
        }
        return $this->success('', ['list' => $desensitization]);
    }

    public function getTablePk(Request $request, ?string $table = null, ?string $connection = null): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        $table = $table ?? $request->get('table', $request->post('table'));
        $connection = $connection ?? $request->get('connection', $request->post('connection'));
        if (!$table) {
            return $this->error(__('Parameter error'));
        }
        $table = TableManager::tableName($table, true, $connection);
        if (!TableManager::phinxAdapter(false, $connection)->hasTable($table)) {
            return $this->error(__('Data table does not exist'));
        }
        $conn = TableManager::getConnection($connection);
        $tablePk = Db::connect($conn)->table($table)->getPk();
        return $this->success('', ['pk' => $tablePk]);
    }

    public function getTableList(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        $quickSearch = $request->get('quickSearch', $request->post('quickSearch', ''));
        $connection = $request->get('connection', $request->post('connection'));
        $samePrefix = filter_var($request->get('samePrefix', $request->post('samePrefix', true)), FILTER_VALIDATE_BOOLEAN);
        $excludeTable = $request->get('excludeTable', $request->post('excludeTable', []));
        $excludeTable = is_array($excludeTable) ? $excludeTable : [];

        $dbConfig = TableManager::getConnectionConfig($connection);
        $tables = TableManager::getTableList($connection);
        if ($quickSearch) {
            $tables = array_filter($tables, function ($comment) use ($quickSearch) {
                return preg_match("/$quickSearch/i", $comment);
            });
        }
        $pattern = '/^' . preg_quote($dbConfig['prefix'] ?? '', '/') . '/i';
        $outTables = [];
        foreach ($tables as $table => $comment) {
            if ($samePrefix && !preg_match($pattern, $table)) continue;
            $tableNoPrefix = preg_replace($pattern, '', $table);
            if (!in_array($tableNoPrefix, $excludeTable)) {
                $outTables[] = [
                    'table' => $tableNoPrefix,
                    'comment' => $comment,
                    'connection' => $connection,
                    'prefix' => $dbConfig['prefix'] ?? '',
                ];
            }
        }
        return $this->success('', ['list' => $outTables]);
    }

    public function getTableFieldList(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        $table = $request->get('table', $request->post('table'));
        $clean = filter_var($request->get('clean', $request->post('clean', true)), FILTER_VALIDATE_BOOLEAN);
        $connection = $request->get('connection', $request->post('connection'));
        if (!$table) {
            return $this->error(__('Parameter error'));
        }
        $conn = TableManager::getConnection($connection);
        $tablePk = Db::connect($conn)->name($table)->getPk();
        return $this->success('', [
            'pk' => $tablePk,
            'fieldList' => TableManager::getTableColumns($table, $clean, $conn),
        ]);
    }

    public function changeTerminalConfig(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        AdminLog::instance($request)->setTitle(__('Change terminal config'));
        if (Terminal::changeTerminalConfig()) {
            return $this->success();
        }
        return $this->error(__('Failed to modify the terminal configuration. Please modify the configuration file manually:%s', ['/config/terminal.php']));
    }

    public function clearCache(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        AdminLog::instance($request)->setTitle(__('Clear cache'));
        $type = $request->post('type');
        if ($type === 'tp' || $type === 'all') {
            clear_config_cache();
        } else {
            return $this->error(__('Parameter error'));
        }
        event_trigger('cacheClearAfter');
        return $this->success(__('Cache cleaned~'));
    }

    public function terminal(Request $request): Response
    {
        $response = $this->initializeBackend($request);
        if ($response !== null) return $response;

        (new Terminal())->exec();
        return $this->success();
    }
}
