<?php

namespace Acms\Services\Form;

/**
 * フォームのインポート処理。エントリー/ブログ/モジュールのインポートと同様に専用クラスとして用意する。
 *
 * 対象ブログに同じ form_code が存在する場合は form_id を維持して上書きし、
 * 投稿ログ（log_form）・エントリー（entry_form_id）の紐付けを保持する。
 * 存在しない場合は新規に採番して作成する。
 * 認可（form_edit ロール等）と CSRF はハンドラ側の責務とする。
 */
class Import
{
    /**
     * @var RepositoryInterface
     */
    private $repository;

    /**
     * @var array<int, array<string, mixed>>
     */
    private $failedContents = [];

    /**
     * @param RepositoryInterface|null $repository
     */
    public function __construct(?RepositoryInterface $repository = null)
    {
        $this->repository = $repository ?? new Repository();
    }

    /**
     * フォームを YAML（パース済み配列）からインポートする
     *
     * @param int $blogId
     * @param array<string, mixed> $yaml
     * @return void
     *
     * @throws \RuntimeException
     */
    public function run($blogId, $yaml)
    {
        if (!isset($yaml['form']) || !is_array($yaml['form'])) {
            throw new \RuntimeException('インポートするフォームのデータが見つかりません。');
        }
        $this->failedContents = [];

        foreach ($yaml['form'] as $record) {
            if (!is_array($record) || (string)($record['form_code'] ?? '') === '') {
                $this->failedContents[] = [
                    'table' => 'form',
                    'type' => 'invalid',
                ];
                continue;
            }
            $attributes = [
                'code' => (string)$record['form_code'],
                'name' => (string)($record['form_name'] ?? ''),
                'scope' => (string)($record['form_scope'] ?? 'local'),
                'log' => (string)($record['form_log'] ?? '1') === '0' ? '0' : '1',
                'data' => (string)($record['form_data'] ?? ''),
            ];

            $existingId = $this->repository->findIdByCodeInBlog((string)$record['form_code'], $blogId);
            if ($existingId !== null) {
                $this->repository->update($existingId, $blogId, $attributes);
            } else {
                $this->repository->insert($blogId, $attributes);
            }
        }

        $this->repository->optimizeSequence();
    }

    /**
     * インポートに失敗した内容を取得する
     *
     * @return array<int, array<string, mixed>>
     */
    public function getFailedContents()
    {
        return $this->failedContents;
    }
}
