<?php

namespace Database\Seeders;

use App\Models\Topic;
use App\Models\TopicCategory;
use App\Models\TopicComment;
use App\Models\TopicFollow;
use App\Models\TopicTag;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Role;

class ForumSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        // まずロールを作成
        $expertRole = Role::firstOrCreate(['name' => 'expert']);
        $userRole = Role::firstOrCreate(['name' => 'user']);

        // カテゴリを作成
        $categories = $this->createTopicCategories();

        // タグを作成
        $tags = $this->createTopicTags();

        // ユーザーを作成
        $users = $this->createUsers($expertRole, $userRole);

        // トピックを作成
        $topics = $this->createTopics($users, $categories, $tags);

        // コメントを作成
        $this->createTopicComments($topics, $users);

        // フォローを作成
        $this->createTopicFollows($topics, $users);
    }

    /**
     * トピックカテゴリを作成
     */
    private function createTopicCategories(): array
    {
        $categories = [
            ['name' => 'プログラミング', 'slug' => 'programming', 'description' => 'プログラミングに関する質問や議論', 'color' => '#3B82F6'],
            ['name' => 'AI・機械学習', 'slug' => 'ai-ml', 'description' => '人工知能と機械学習に関するトピック', 'color' => '#8B5CF6'],
            ['name' => 'Web開発', 'slug' => 'web-development', 'description' => 'Webアプリケーション開発について', 'color' => '#10B981'],
            ['name' => 'モバイル開発', 'slug' => 'mobile-development', 'description' => 'iOS、Android開発について', 'color' => '#F59E0B'],
            ['name' => 'データベース', 'slug' => 'database', 'description' => 'データベース設計と管理', 'color' => '#EF4444'],
            ['name' => 'クラウド・インフラ', 'slug' => 'cloud-infrastructure', 'description' => 'AWS、Azure、GCPなどのクラウドサービス', 'color' => '#06B6D4'],
            ['name' => 'プロジェクト管理', 'slug' => 'project-management', 'description' => 'プロジェクトの進め方や管理手法', 'color' => '#84CC16'],
            ['name' => 'キャリア', 'slug' => 'career', 'description' => 'エンジニアのキャリアについて', 'color' => '#F97316'],
        ];

        $createdCategories = [];
        foreach ($categories as $index => $category) {
            $createdCategories[] = TopicCategory::firstOrCreate(
                ['slug' => $category['slug']],
                [
                    'name'        => $category['name'],
                    'slug'        => $category['slug'],
                    'description' => $category['description'],
                    'color'       => $category['color'],
                    'sort_order'  => $index + 1,
                    'is_active'   => true,
                ]);
        }

        return $createdCategories;
    }

    /**
     * トピックタグを作成
     */
    private function createTopicTags(): array
    {
        $tags = [
            ['name' => 'PHP', 'slug' => 'php', 'color' => '#777BB4'],
            ['name' => 'Laravel', 'slug' => 'laravel', 'color' => '#FF2D20'],
            ['name' => 'JavaScript', 'slug' => 'javascript', 'color' => '#F7DF1E'],
            ['name' => 'Vue.js', 'slug' => 'vuejs', 'color' => '#4FC08D'],
            ['name' => 'React', 'slug' => 'react', 'color' => '#61DAFB'],
            ['name' => 'Python', 'slug' => 'python', 'color' => '#3776AB'],
            ['name' => 'Django', 'slug' => 'django', 'color' => '#092E20'],
            ['name' => 'Node.js', 'slug' => 'nodejs', 'color' => '#339933'],
            ['name' => 'MySQL', 'slug' => 'mysql', 'color' => '#4479A1'],
            ['name' => 'PostgreSQL', 'slug' => 'postgresql', 'color' => '#336791'],
            ['name' => 'MongoDB', 'slug' => 'mongodb', 'color' => '#47A248'],
            ['name' => 'Docker', 'slug' => 'docker', 'color' => '#2496ED'],
            ['name' => 'AWS', 'slug' => 'aws', 'color' => '#FF9900'],
            ['name' => 'Azure', 'slug' => 'azure', 'color' => '#0078D4'],
            ['name' => 'TypeScript', 'slug' => 'typescript', 'color' => '#3178C6'],
            ['name' => 'Swift', 'slug' => 'swift', 'color' => '#FA7343'],
            ['name' => 'Kotlin', 'slug' => 'kotlin', 'color' => '#7F52FF'],
            ['name' => 'Flutter', 'slug' => 'flutter', 'color' => '#02569B'],
            ['name' => 'Git', 'slug' => 'git', 'color' => '#F05032'],
            ['name' => 'API', 'slug' => 'api', 'color' => '#000000'],
            ['name' => 'セキュリティ', 'slug' => 'security', 'color' => '#DC2626'],
            ['name' => 'パフォーマンス', 'slug' => 'performance', 'color' => '#059669'],
            ['name' => 'テスト', 'slug' => 'testing', 'color' => '#7C3AED'],
            ['name' => 'DevOps', 'slug' => 'devops', 'color' => '#0F172A'],
            ['name' => 'アーキテクチャ', 'slug' => 'architecture', 'color' => '#1F2937'],
            ['name' => 'UI/UX', 'slug' => 'ui-ux', 'color' => '#EC4899'],
            ['name' => '初心者', 'slug' => 'beginner', 'color' => '#22C55E'],
            ['name' => 'バグ修正', 'slug' => 'bug-fix', 'color' => '#EF4444'],
            ['name' => 'ベストプラクティス', 'slug' => 'best-practices', 'color' => '#6366F1'],
            ['name' => 'レビュー依頼', 'slug' => 'code-review', 'color' => '#F59E0B'],
        ];

        $createdTags = [];
        foreach ($tags as $tag) {
            $createdTags[] = TopicTag::firstOrCreate(
                ['slug' => $tag['slug']],
                [
                    'name'        => $tag['name'],
                    'slug'        => $tag['slug'],
                    'description' => $tag['name'] . 'に関するトピック',
                    'color'       => $tag['color'],
                    'usage_count' => rand(0, 50),
                ]);
        }

        return $createdTags;
    }

    /**
     * ユーザーを作成
     */
    private function createUsers($expertRole, $userRole): array
    {
        $users = [];

        // エキスパートユーザーを10人作成
        $expertNames = [
            '田中一郎', '佐藤花子', '鈴木太郎', '高橋美咲', '伊藤健二',
            '山田雅子', '中村拓也', '小林真理', '加藤直樹', '渡辺恵子',
        ];

        foreach ($expertNames as $index => $name) {
            $user = User::firstOrCreate(
                ['email' => 'expert' . ($index + 1) . '@example.com'],
                [
                    'name'              => $name,
                    'email'             => 'expert' . ($index + 1) . '@example.com',
                    'password'          => Hash::make('password'),
                    'email_verified_at' => now(),
                ]);
            $user->assignRole($expertRole);
            $users[] = $user;
        }

        // 一般ユーザーを20人作成
        $userNames = [
            '松本和也', '井上由美', '木村正人', '森下千春', '清水誠',
            '橋本佳子', '山本博文', '吉田みどり', '坂本健太', '岡田理恵',
            '前田裕介', '藤田さくら', '福田大輔', '石川ひろみ', '村田光一',
            '池田麻衣', '青木慎一', '岩田あゆみ', '原田俊明', '長谷川のぞみ',
        ];

        foreach ($userNames as $index => $name) {
            $user = User::firstOrCreate(
                ['email' => 'user' . ($index + 1) . '@example.com'],
                [
                    'name'              => $name,
                    'email'             => 'user' . ($index + 1) . '@example.com',
                    'password'          => Hash::make('password'),
                    'email_verified_at' => now(),
                ]);
            $user->assignRole($userRole);
            $users[] = $user;
        }

        return $users;
    }

    /**
     * トピックを作成
     */
    private function createTopics($users, $categories, $tags): array
    {
        $topicData = [
            [
                'title'            => 'Laravelで大量データを効率的に処理する方法',
                'content'          => '数万件のデータをLaravelで処理する際のベストプラクティスを教えてください。現在、メモリ不足エラーが発生してしまいます。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [0], // プログラミング
                'tag_indexes'      => [0, 1], // PHP, Laravel
            ],
            [
                'title'            => 'Vue.js 3のComposition APIを使った状態管理',
                'content'          => 'Vue.js 3のComposition APIを使って複雑な状態管理を行う方法について質問があります。Vuexを使わずに実装したいです。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [2], // Web開発
                'tag_indexes'      => [2, 4], // JavaScript, Vue.js
            ],
            [
                'title'            => 'Dockerコンテナ間の通信エラーを解決したい',
                'content'          => 'DockerでLaravelとMySQLのコンテナを立ち上げているのですが、データベースに接続できません。設定方法を教えてください。',
                'status'           => 'published',
                'priority'         => 'urgent',
                'category_indexes' => [5], // クラウド・インフラ
                'tag_indexes'      => [1, 8, 11], // Laravel, MySQL, Docker
            ],
            [
                'title'            => 'React Hooksを使ったパフォーマンス最適化',
                'content'          => 'Reactアプリケーションのレンダリングが遅くなってしまいました。useMemoやuseCallbackの効果的な使い方を教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [2], // Web開発
                'tag_indexes'      => [2, 5, 21], // JavaScript, React, パフォーマンス
            ],
            [
                'title'            => 'AIチャットボットの自然言語処理を改善したい',
                'content'          => 'Pythonで作成したチャットボットの回答精度を上げたいです。どのような手法が効果的でしょうか？',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [1], // AI・機械学習
                'tag_indexes'      => [5, 6], // Python, Django
            ],
            [
                'title'            => 'iOSアプリのメモリリークを特定する方法',
                'content'          => 'Swiftで開発しているiOSアプリでメモリリークが発生しています。効率的なデバッグ方法を教えてください。',
                'status'           => 'published',
                'priority'         => 'urgent',
                'category_indexes' => [3], // モバイル開発
                'tag_indexes'      => [15, 27], // Swift, バグ修正
            ],
            [
                'title'            => 'PostgreSQLのクエリパフォーマンス向上について',
                'content'          => 'JOIN文を多用するクエリが遅いです。インデックスの設定方法や最適化のコツを教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [4], // データベース
                'tag_indexes'      => [9, 21], // PostgreSQL, パフォーマンス
            ],
            [
                'title'            => 'プロジェクトの技術選定で迷っています',
                'content'          => '新しいWebアプリケーションプロジェクトでフレームワークを選ぶ際の基準を教えてください。LaravelとDjangoで迷っています。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [6], // プロジェクト管理
                'tag_indexes'      => [1, 6, 28], // Laravel, Django, ベストプラクティス
            ],
            [
                'title'            => 'TypeScriptの型定義でエラーが解決できない',
                'content'          => '外部ライブラリの型定義でエラーが発生します。@types/を使った解決方法を教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [0], // プログラミング
                'tag_indexes'      => [2, 14], // JavaScript, TypeScript
            ],
            [
                'title'            => 'AWSでのCI/CDパイプライン構築',
                'content'          => 'GitHub ActionsとAWSを使ったデプロイメントパイプラインを構築したいです。設定手順を教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [5], // クラウド・インフラ
                'tag_indexes'      => [12, 18, 23], // AWS, Git, DevOps
            ],
            [
                'title'            => 'Flutterアプリの状態管理ライブラリの選び方',
                'content'          => 'FlutterアプリでRiverpod、Bloc、Providerのどれを選ぶべきか迷います。プロジェクトの規模による使い分けを教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [3], // モバイル開発
                'tag_indexes'      => [17, 28], // Flutter, ベストプラクティス
            ],
            [
                'title'            => 'セキュアなAPI認証の実装方法',
                'content'          => 'REST APIでJWT認証を実装していますが、セキュリティ面で不安があります。ベストプラクティスを教えてください。',
                'status'           => 'published',
                'priority'         => 'urgent',
                'category_indexes' => [2], // Web開発
                'tag_indexes'      => [19, 20], // API, セキュリティ
            ],
            [
                'title'            => 'MongoDBのスケーリング戦略について',
                'content'          => '大規模なデータを扱うためのMongoDBの設計とスケーリング手法について教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [4], // データベース
                'tag_indexes'      => [10, 24], // MongoDB, アーキテクチャ
            ],
            [
                'title'            => 'Node.jsのパフォーマンス監視ツール',
                'content'          => '本番環境でのNode.jsアプリケーションの監視に適したツールを教えてください。メトリクス収集も含めて知りたいです。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [2], // Web開発
                'tag_indexes'      => [7, 21, 23], // Node.js, パフォーマンス, DevOps
            ],
            [
                'title'            => 'エンジニア転職で重視すべきポイント',
                'content'          => '3年目のエンジニアです。転職を考えていますが、技術力以外で重視すべき点があれば教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [7], // キャリア
                'tag_indexes'      => [], // タグなし
            ],
            [
                'title'            => 'Kotlinでのコルーチン活用術',
                'content'          => 'AndroidアプリでKotlinのコルーチンを使った非同期処理のベストプラクティスを教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [3], // モバイル開発
                'tag_indexes'      => [16, 28], // Kotlin, ベストプラクティス
            ],
            [
                'title'            => 'UIコンポーネントの設計指針',
                'content'          => '再利用可能なUIコンポーネントを設計する際の原則や注意点について教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [2], // Web開発
                'tag_indexes'      => [25, 28], // UI/UX, ベストプラクティス
            ],
            [
                'title'            => 'Pythonでの機械学習モデルの本番運用',
                'content'          => '開発したMLモデルを本番環境にデプロイする際の課題と解決策を教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [1], // AI・機械学習
                'tag_indexes'      => [5, 23], // Python, DevOps
            ],
            [
                'title'            => 'テスト自動化の導入手順',
                'content'          => 'レガシーシステムにテスト自動化を導入したいのですが、段階的な進め方を教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [0], // プログラミング
                'tag_indexes'      => [22, 28], // テスト, ベストプラクティス
            ],
            [
                'title'            => 'Azure DevOpsでのチーム開発最適化',
                'content'          => 'Azure DevOpsを使った効率的なチーム開発フローの構築方法について教えてください。',
                'status'           => 'published',
                'priority'         => 'normal',
                'category_indexes' => [6], // プロジェクト管理
                'tag_indexes'      => [13, 23], // Azure, DevOps
            ],
        ];

        $topics = [];
        foreach ($topicData as $index => $data) {
            // ランダムにユーザーを選択（エキスパートと一般ユーザー両方から）
            $randomUser = $users[array_rand($users)];

            $topic = Topic::create([
                'title'              => $data['title'],
                'slug'               => 'topic-' . ($index + 1) . '-' . Str::random(6),
                'short_description'  => mb_substr($data['content'], 0, 100) . '...',
                'content'            => $data['content'],
                'view_count'         => rand(10, 500),
                'user_id'            => $randomUser->id,
                'status'             => $data['status'],
                'priority'           => $data['priority'],
                'comment_permission' => ['all', 'experts_only', 'users_only'][rand(0, 2)],
                'is_featured'        => rand(0, 1) === 1,
                'is_pinned'          => rand(0, 5) === 1, // 20%の確率
                'like_count'         => rand(0, 50),
                'comment_count'      => 0, // コメント作成時に自動更新される
                'last_activity_at'   => now()->subDays(rand(0, 30)),
                'created_at'         => now()->subDays(rand(0, 60)),
            ]);

            // カテゴリを関連付け
            foreach ($data['category_indexes'] as $categoryIndex) {
                if (isset($categories[$categoryIndex])) {
                    $topic->categories()->attach($categories[$categoryIndex]->id);
                }
            }

            // タグを関連付け
            foreach ($data['tag_indexes'] as $tagIndex) {
                if (isset($tags[$tagIndex])) {
                    $topic->tags()->attach($tags[$tagIndex]->id);
                    $tags[$tagIndex]->incrementUsage();
                }
            }

            $topics[] = $topic;
        }

        return $topics;
    }

    /**
     * トピックコメントを作成
     */
    private function createTopicComments($topics, $users): void
    {
        $commentTemplates = [
            'ありがとうございます！とても参考になりました。',
            'この方法で解決できました。詳しい説明をありがとうございます。',
            '私も同じ問題で困っていました。',
            '別のアプローチとして{approach}はいかがでしょうか？',
            'ドキュメントの{link}部分も参考になるかもしれません。',
            'エラーログを確認していただけますか？',
            'このコードにバグがありそうです：{code}',
            'バージョンの違いが原因かもしれません。',
            '私の環境では正常に動作しています。',
            'この解決策で完璧に動きました！',
        ];

        foreach ($topics as $topic) {
            // 各トピックにランダムな数のコメントを作成（1-8個）
            $commentCount = rand(1, 8);

            for ($i = 0; $i < $commentCount; $i++) {
                $randomUser = $users[array_rand($users)];
                $isReply = rand(0, 3) === 1; // 25%の確率で返信
                $parentId = 0;

                // 返信の場合、既存のコメントから親を選択
                if ($isReply && $topic->comments()->count() > 0) {
                    $parentComment = $topic->comments()->inRandomOrder()->first();
                    $parentId = $parentComment->id;
                }

                $content = $commentTemplates[array_rand($commentTemplates)];
                $content = str_replace(
                    ['{approach}', '{link}', '{code}'],
                    ['○○ライブラリを使用する方法', 'https://example.com/docs', '`console.log(error)`'],
                    $content
                );

                // 引用コンテンツ（20%の確率）
                $quoteContent = null;
                if (rand(0, 4) === 1 && $parentId > 0) {
                    $parentComment = TopicComment::find($parentId);
                    if ($parentComment) {
                        $quoteContent = mb_substr($parentComment->content, 0, 50) . '...';
                    }
                }

                $comment = TopicComment::create([
                    'topic_id'      => $topic->id,
                    'user_id'       => $randomUser->id,
                    'content'       => $content,
                    'parent_id'     => $parentId,
                    'quote_content' => $quoteContent,
                    'like_count'    => rand(0, 20),
                    'dislike_count' => rand(0, 5),
                    'is_approved'   => true,
                    'is_solution'   => rand(0, 10) === 1, // 10%の確率で解決策
                    'created_at'    => now()->subDays(rand(0, 30)),
                ]);

                // 解決策の場合、トピックのステータスを更新
                if ($comment->is_solution && $topic->status !== 'resolved') {
                    $topic->update(['status' => 'resolved']);
                }
            }
        }
    }

    /**
     * トピックフォローを作成
     */
    private function createTopicFollows($topics, $users): void
    {
        foreach ($topics as $topic) {
            // 各トピックに1-10人のフォロワーを作成
            $followerCount = rand(1, 10);
            $randomUsers = collect($users)->random($followerCount);

            foreach ($randomUsers as $user) {
                TopicFollow::firstOrCreate([
                    'user_id'  => $user->id,
                    'topic_id' => $topic->id,
                ]);
            }
        }
    }
}
