<?php

try {
    require_once(dirname(__FILE__) . '/application.php');
    require_once(dirname(__FILE__) . '/setup.php');
    require_once(dirname(__FILE__) . '/lib/import.php');
    require_once(dirname(__FILE__) . '/lib/fix.php');
    $tplPath = dirname(__FILE__) . "/tpl/import.html";

    @set_time_limit(0);

    class Surfacer_Import extends Surfacer
    {
        /**
         * @var array $ids
         */
        protected $ids = [];

        public function buildSurface(&$Tpl, $root)
        {
            $this->listBlog($Tpl, $root);

            /**
             * list yaml name
             */
            $binPath = dirname(__FILE__) . '/bin/';
            if (Storage::isDirectory($binPath)) {
                $dh = opendir($binPath);
                if ($dh === false) {
                    return;
                }
                while (false !== ($bin = readdir($dh))) {
                    if (
                        is_dir($binPath . $bin) &&
                        $bin !== '.' &&
                        $bin !== '..' &&
                        preg_match('/^[^.][^@]*$/', $bin)
                    ) {
                        $flg = true;
                        $vars = ['name' => $bin];
                        if ($vars['name'] == $this->Post->get('name')) {
                            $vars += ['checked' => ' checked="checked"'];
                        }
                        $Tpl->add(['name:loop', $root], $vars);
                    }
                }
            }

            /**
             * detect existion
             */
            if (empty($flg)) {
                $Tpl->add(['notFound', $root]);
            } else {
                $Tpl->add(['binExist', $root]);
            }
        }

        public function validate()
        {
            $DB = DB::singleton(dsn());

            if ($this->Post->isNull('bid')) {
                $this->Error['blog_select'] = true;
            }
            if ($this->Post->isNull('name')) {
                $this->Error['name_select'] = true;
            }
            if ($this->Post->isNull('marker')) {
                $this->Error['marker_input'] = true;
            }

            if (!$this->Post->isNull('parent')) {
                $SQL = SQL::newSelect('blog');
                $SQL->addSelect('blog_id', 'blog_amount', null, 'count');
                $DB->query($SQL->get(dsn()), 'one');

                if ($this->Post->get('blog_code') === '') {
                    $this->Error['blog_code_input'] = true;
                }
                if ($this->Post->get('blog_name') === '') {
                    $this->Error['blod_name_input'] = true;
                }
            }

            if (!SetupCommon::checkPermission(PATH_ARCHIVES)) {
                $this->Error['archives_permission'] = true;
            }
            if (!SetupCommon::checkPermission(PATH_THEMES)) {
                $this->Error['themes_permission'] = true;
            }

            /**
             * confliction check of blog_code
             */
            $SQL = SQL::newSelect('blog');
            if (!$this->Post->isNull('parent')) {
                $SQL->addWhereOpr('blog_id', $this->Post->get('bid'));
            } else {
                $SQL->addWhereOpr('blog_id', 0);
            }
            $PARENT = $DB->query($SQL->get(dsn()), 'row');

            $SQL = SQL::newSelect('blog');
            $SQL->setSelect('blog_code');
            if (isset($PARENT['blog_domain']) && !!$PARENT['blog_domain']) {
                $SQL->addWhereOpr('blog_domain', $PARENT['blog_domain']);
            }
            $SQL->addWhereOpr('blog_code', $this->Post->get('blog_code'));
            $exe = $DB->query($SQL->get(dsn()), 'one');
            if (!empty($exe)) {
                $this->Error['blog_code_conflict'] = true;
            }

            $this->detectStep();
        }

        public function business()
        {
            error_reporting(E_ALL); // すべての種類のエラーを報告
            ini_set('display_errors', '1'); // エラー表示を有効化

            $DB = DB::singleton(dsn());
            $uid = $_SESSION['auth'];
            @set_time_limit(0);

            $_path = dirname(__FILE__) . '/bin/' . $this->Post->get('name');
            $path['yaml'] = $_path . '/' . $this->Post->get('name') . '.yaml';
            $path['archives'] = $_path . '/archives/';
            $path['themes'] = $_path . '/themes/';
            $path['media'] = $_path . '/media/';
            $path['storage'] = $_path . '/storage/';

            /**
             * detect config import & delete
             */
            $config = [];
            if ($this->Post->isExists('config_import')) {
                $config['import'] = true;
            }
            if ($this->Post->isExists('config_delete')) {
                $config['delete'] = true;
            }

            /**
             * detect contents delete
             */
            if ($this->Post->isExists('contents_drop')) {
                $config['drop'] = true;
            }

            /**
             * detect escape marker
             */
            if ($this->Post->isExists('marker')) {
                $config['marker'] = $this->Post->get('marker');
            }

            /**
             * detect blog method
             */
            if (Storage::exists($path['yaml'])) {
                if (!$this->Post->isNull('parent')) {
                    $this->registerNewIDs($path['yaml']);

                    $SQL = SQL::newSelect('blog');
                    $SQL->addWhereOpr('blog_id', $this->Post->get('bid'));
                    $row = $DB->query($SQL->get(dsn()), 'row');

                    $blog['code'] = $this->Post->get('blog_code');
                    $blog['name'] = $this->Post->get('blog_name');
                    $blog['parent'] = $row['blog_id'];
                    $blog['domain'] = $row['blog_domain'];

                    $import = new Import_Add_Child($path, $this->ids, $blog, $uid, $config);
                    $bid = $import->getBlogId();
                    $this->Post->set('bid', $bid);
                } else {
                    $bid = intval($this->Post->get('bid'));
                    $this->registerNewIDs($path['yaml'], $bid);

                    new Import_Add_Merge($path, $this->ids, $bid, $uid, $config);
                    $this->Post->set('bid', $bid);
                }
                Cache::allFlush();
            } else {
                $this->Error['yaml_exist'] = true;
            }
            $this->detectStep();
        }

        private function registerNewIDs(string $yamlPath, ?int $bid = null): void
        {
            $tables = [
                'blog', 'column', 'entry', 'category', 'rule', 'module', 'comment', 'user',
                'form', 'schedule', 'media', 'config_set',
            ];
            foreach ($tables as $table) {
                $yaml = Config::yamlLoad($yamlPath);
                if (isset($yaml[$table]) && is_array($yaml[$table])) {
                    foreach ($yaml[$table] as $record) {
                        if (!isset($record[$table . '_id'])) {
                            continue;
                        }
                        $id = $record[$table . '_id'];
                        if (isset($this->ids[$table][$id])) {
                            continue;
                        }
                        if ($table === 'column') {
                            $this->ids[$table][$id] = uuidv4();
                        } elseif ($table === 'blog') {
                            if ($bid !== null) {
                                $this->ids[$table][$id] = $bid;
                            } else {
                                $this->ids[$table][$id] = DB::query(SQL::nextval($table . '_id', dsn()), 'seq');
                            }
                        } else {
                            $this->ids[$table][$id] = DB::query(SQL::nextval($table . '_id', dsn()), 'seq');
                        }
                    }
                }
            }
        }
    }

    class Import_Add_Child extends Import
    {
        public function __construct($path, $ids, $blog, $uid, $config)
        {
            parent::__construct();
            $array = Config::yamlLoad($path['yaml']);
            $this->setIds($ids);

            $oldBID = isset($array['blog'][0]['blog_id']) ? $array['blog'][0]['blog_id'] : 1;
            $blog['id'] = $this->getRAM('blog', $oldBID);
            $this->generateBlog($blog);
            $this->UID = $uid;

            if (isset($array['config_set'])) {
                $this->insertConfigSet($array['config_set']);
            }
            if (isset($array['media'])) {
                $this->insertMedia($array['media']);
            }
            if (isset($array['media_tag'])) {
                $this->insertMediaTag($array['media_tag']);
            }
            $this->copyArchives($path['archives'], ROOT_DIR . ARCHIVES_DIR);
            $this->copyArchives($path['media'], ROOT_DIR . MEDIA_LIBRARY_DIR);
            $this->copyArchives($path['storage'], ROOT_DIR . MEDIA_STORAGE_DIR);
            $this->copyThemes($path['themes'], ROOT_DIR . 'themes/');

            $this->insertCategory($array['category'], false);
            $this->insertEntry($array['entry'], false);
            $this->insertTag($array['tag']);
            $this->insertComment($array['comment']);

            if (!empty($config['import'])) {
                $this->insertModule($array['module']);
                $this->insertLayout($array['layout_grid']);
                $this->insertRule($array['rule']);
                $this->insertConfig($array['config']);
            }

            $this->insertColumn($array['column'], $config['marker']);
            $this->insertForm($array['form']);
            $this->insertDashboard($array['dashboard']);
            $this->insertField($array['field']);

            if (isset($array['blog'])) {
                $this->updateBlogConfigSet($array['blog']);
            }

            $this->fixPrimaryImage();
            $this->generateFulltext();
        }
    }

    class Import_Add_Merge extends Import
    {
        public function __construct($path, $ids, $bid, $uid, $config)
        {
            parent::__construct();
            $array = Config::yamlLoad($path['yaml']);
            $this->setIds($ids);

            $this->BID = $bid;
            $this->UID = $uid;

            $this->copyArchives($path['archives'], ROOT_DIR . ARCHIVES_DIR);
            $this->copyArchives($path['media'], ROOT_DIR . MEDIA_LIBRARY_DIR);
            $this->copyArchives($path['storage'], ROOT_DIR . MEDIA_STORAGE_DIR);
            $this->copyThemes($path['themes'], ROOT_DIR . 'themes/');

            if (!empty($config['drop'])) {
                $this->deleteCategory();
                $this->deleteEntry();
                $this->deleteColumn();
                $this->deleteTag();
                $this->deleteComment();
                $this->deleteFulltext();
                $this->deleteField();
            }

            $this->insertCategory($array['category']);
            $this->insertEntry($array['entry']);
            $this->insertTag($array['tag']);
            $this->insertComment($array['comment']);

            if (!empty($config['delete'])) {
                $this->deleteDashboard();
                $this->deleteModule();
                $this->deleteLayout();
                $this->deleteRule();
                $this->deleteConfig();
                $this->deleteConfigSet();
            }
            if (isset($array['config_set'])) {
                $this->insertConfigSet($array['config_set']);
            }
            if (isset($array['media'])) {
                $this->insertMedia($array['media']);
            }
            if (isset($array['media_tag'])) {
                $this->insertMediaTag($array['media_tag']);
            }
            if (!empty($config['import'])) {
                $this->insertModule($array['module']);
                $this->insertLayout($array['layout_grid']);
                $this->insertRule($array['rule']);
                $this->insertConfig($array['config']);
            }

            $this->insertColumn($array['column'], $config['marker']);
            $this->insertForm($array['form']);
            $this->insertDashboard($array['dashboard']);
            $this->insertField($array['field']);

            $this->fixPrimaryImage();
            $this->generateFulltext();

            $this->updateBlogConfigSet($array['blog']);
        }
    }

    new Surfacer_Import($tplPath);

    App::checkException();
} catch (Exception $e) {
    App::showError($e, false);
}
