<?php

namespace Database\Seeders;

use App\Models\AssessmentQuestion;
use App\Models\AssessmentTemplate;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use RuntimeException;

/**
 * Loads platform assessment content packs from database/data/assessments/*.json.
 * Upserts by (code, version); replaces questions for that template version.
 */
class AssessmentTemplateSeeder extends Seeder
{
    public function run(): void
    {
        $dir = database_path('data/assessments');
        if (! is_dir($dir)) {
            $this->command?->warn("No assessment packs directory at {$dir}");

            return;
        }

        $files = collect(File::files($dir))
            ->filter(fn ($file) => str_ends_with(strtolower($file->getFilename()), '.json'))
            ->sortBy(fn ($file) => $file->getFilename())
            ->values();

        if ($files->isEmpty()) {
            $this->command?->warn('No assessment JSON packs found.');

            return;
        }

        foreach ($files as $file) {
            $this->seedPack($file->getPathname());
        }
    }

    public function seedPack(string $path): AssessmentTemplate
    {
        $raw = File::get($path);
        $data = json_decode($raw, true);
        if (! is_array($data) || ! isset($data['template'], $data['questions'])) {
            throw new RuntimeException("Invalid assessment pack: {$path}");
        }

        $t = $data['template'];
        foreach (['code', 'name', 'category', 'version'] as $required) {
            if (! array_key_exists($required, $t)) {
                throw new RuntimeException("Assessment pack missing template.{$required}: {$path}");
            }
        }

        return DB::transaction(function () use ($t, $data, $path) {
            $template = AssessmentTemplate::withTrashed()
                ->whereNull('organization_id')
                ->where('code', $t['code'])
                ->where('version', (int) $t['version'])
                ->first();

            $attributes = [
                'organization_id' => null,
                'code' => $t['code'],
                'name' => $t['name'],
                'category' => $t['category'],
                'description' => $t['description'] ?? null,
                'version' => (int) $t['version'],
                'is_current' => (bool) ($t['is_current'] ?? true),
                'is_active' => (bool) ($t['is_active'] ?? true),
                'scoring_strategy' => $t['scoring_strategy'] ?? null,
                'meta' => $t['meta'] ?? null,
                'deleted_at' => null,
            ];

            if ($template) {
                if ($template->trashed()) {
                    $template->restore();
                }
                $template->fill(collect($attributes)->except('deleted_at')->all())->save();
            } else {
                $template = AssessmentTemplate::create(collect($attributes)->except('deleted_at')->all());
            }

            if ($template->is_current) {
                AssessmentTemplate::query()
                    ->whereNull('organization_id')
                    ->where('code', $template->code)
                    ->where('id', '!=', $template->id)
                    ->where('is_current', true)
                    ->update(['is_current' => false]);
            }

            // Upsert questions by code so live answers keep their FK targets.
            $keptCodes = [];
            $sort = 0;
            foreach ($data['questions'] as $q) {
                if (empty($q['code']) || empty($q['label']) || empty($q['answer_type'])) {
                    throw new RuntimeException("Invalid question in pack {$path}");
                }
                $sort++;
                $keptCodes[] = $q['code'];
                $attributes = [
                    'section' => $q['section'] ?? null,
                    'label' => $q['label'],
                    'help_text' => $q['help_text'] ?? null,
                    'answer_type' => $q['answer_type'],
                    'options' => $q['options'] ?? null,
                    'is_required' => (bool) ($q['is_required'] ?? false),
                    'sort_order' => (int) ($q['sort_order'] ?? $sort),
                    'score_key' => $q['score_key'] ?? null,
                    'validation' => $q['validation'] ?? null,
                ];

                $question = AssessmentQuestion::query()
                    ->where('template_id', $template->id)
                    ->where('code', $q['code'])
                    ->first();

                if ($question) {
                    $question->fill($attributes)->save();
                } else {
                    AssessmentQuestion::create(array_merge($attributes, [
                        'template_id' => $template->id,
                        'code' => $q['code'],
                    ]));
                }
            }

            // Drop obsolete pack questions only when nothing references them.
            AssessmentQuestion::query()
                ->where('template_id', $template->id)
                ->whereNotIn('code', $keptCodes)
                ->whereDoesntHave('answers')
                ->delete();

            $this->command?->info(sprintf(
                'Seeded assessment pack %s v%d (%d questions)',
                $template->code,
                $template->version,
                count($data['questions']),
            ));

            return $template->fresh('questions');
        });
    }
}
