<?php

/**
 * 文件功能：部门与职务数据填充器
 * 预填所有部门（办公厅 / 迎宾部 / 聊务部 / 宣传部）
 * 及各部门下的完整职务数据（含图标、rank、level、人数/奖励上限）
 * 并写入默认的任命权限白名单（position_appoint_limits）
 *
 * @author   ChatRoom Laravel
 *
 * @version  1.0.0
 */

namespace Database\Seeders;

use App\Models\Department;
use App\Models\Position;
use App\Support\PositionPermissionRegistry;
use Illuminate\Database\Seeder;

class DepartmentPositionSeeder extends Seeder
{
    /**
     * 执行数据填充
     */
    public function run(): void
    {
        // ── 1. 创建部门 ────────────────────────────────────────────────────
        $depts = [];
        foreach ($this->departmentsData() as $data) {
            $depts[$data['name']] = Department::firstOrCreate(
                ['name' => $data['name']],
                $data
            );
        }

        // ── 2. 创建职务 ────────────────────────────────────────────────────
        $positions = []; // key = "部门名::职务名"
        foreach ($this->positionsData() as $row) {
            $dept = $depts[$row['department']];
            $position = Position::firstOrCreate(
                ['department_id' => $dept->id, 'name' => $row['name']],
                [
                    'department_id' => $dept->id,
                    'name' => $row['name'],
                    'icon' => $row['icon'],
                    'rank' => $row['rank'],
                    'level' => $row['level'],
                    'max_persons' => $row['max_persons'],
                    'max_reward' => $row['max_reward'],
                    'sort_order' => $row['sort_order'],
                    'permissions' => PositionPermissionRegistry::defaultPermissionsForLevel((int) $row['level']),
                ]
            );
            $positions["{$row['department']}::{$row['name']}"] = $position;
        }

        // ── 3. 设置任命权限白名单 ────────────────────────────────────────────
        foreach ($this->appointLimitsData($positions) as [$appointer, $appointableList]) {
            /** @var Position $appointerPosition */
            $appointerPosition = $positions[$appointer] ?? null;
            if (! $appointerPosition) {
                continue;
            }

            // 同步任命白名单（不附加旧数据，完整覆盖）
            $appointableIds = collect($appointableList)
                ->map(fn ($key) => $positions[$key] ?? null)
                ->filter()
                ->pluck('id')
                ->toArray();

            $appointerPosition->appointablePositions()->sync($appointableIds);
        }

        $this->command->info('部门职务 Seeder 完成：'.count($positions).' 个职务已写入。');
    }

    /**
     * 部门基础数据
     *
     * @return array<int, array<string, mixed>>
     */
    private function departmentsData(): array
    {
        return [
            ['name' => '办公厅', 'rank' => 99, 'color' => '#8B0000', 'sort_order' => 1, 'description' => '站级最高指挥机构'],
            ['name' => '迎宾部', 'rank' => 80, 'color' => '#1a5276', 'sort_order' => 2, 'description' => '负责新用户迎接与接待工作'],
            ['name' => '聊务部', 'rank' => 75, 'color' => '#196F3D', 'sort_order' => 3, 'description' => '负责聊天室日常管理与氛围维护'],
            ['name' => '宣传部', 'rank' => 70, 'color' => '#7D6608', 'sort_order' => 4, 'description' => '负责聊天室宣传推广与活动策划'],
        ];
    }

    /**
     * 职务完整数据
     *
     * @return array<int, array<string, mixed>>
     */
    private function positionsData(): array
    {
        // [部门, 职务名, icon, rank, level, max_persons, max_reward, sort_order]
        $rows = [
            // ── 办公厅 ──────────────────────────────────────────────────────
            ['办公厅', '站长',       '👑', 99, 100, 1,    null, 1],
            ['办公厅', '执行站长',   '⭐', 97, 99,  1,    null, 2],
            ['办公厅', '常务副站长', '📜', 95, 98,  1,    2000, 3],
            ['办公厅', '副站长',     '🔴', 93, 97,  1,    1500, 4],
            ['办公厅', '秘书长',     '✏️', 91, 96,  2,    1200, 5],
            ['办公厅', '三部总长',   '🪖', 89, 95,  1,    1000, 6],
            // ── 迎宾部 ──────────────────────────────────────────────────────
            ['迎宾部', '迎宾部长',       '🏆', 87, 94, 1, 800, 1],
            ['迎宾部', '迎宾政委',       '👤', 87, 94, 1, 800, 2],
            ['迎宾部', '迎宾常务副部长', '📋', 85, 93, 1, 500, 3],
            ['迎宾部', '迎宾副部长',     '🔵', 83, 92, 1, 300, 4],
            ['迎宾部', '迎宾副政委',     '🔵', 81, 91, 1, 300, 5],
            ['迎宾部', '金牌迎宾员',     '🥇', 70, 90, 2, null, 6],
            ['迎宾部', '银牌迎宾员',     '🥈', 50, 80, 3, null, 7],
            ['迎宾部', '铜牌迎宾员',     '🥉', 30, 70, 4, null, 8],
            ['迎宾部', '实习迎宾员',     '🌱', 10, 60, 4, null, 9],
            // ── 聊务部 ──────────────────────────────────────────────────────
            ['聊务部', '聊务部部长',       '🏆', 87, 94, 1, 800, 1],
            ['聊务部', '聊务部政委',       '👤', 87, 94, 1, 800, 2],
            ['聊务部', '聊务部常务副部长', '📋', 85, 93, 1, 500, 3],
            ['聊务部', '聊务部副部长',     '🔵', 83, 92, 1, 300, 4],
            ['聊务部', '聊务部副政委',     '🔵', 81, 91, 1, 300, 5],
            ['聊务部', '金牌聊务员',       '🥇', 70, 90, 2, null, 6],
            ['聊务部', '银牌聊务员',       '🥈', 50, 80, 3, null, 7],
            ['聊务部', '铜牌聊务员',       '🥉', 30, 70, 4, null, 8],
            ['聊务部', '实习聊务员',       '🌱', 10, 60, 4, null, 9],
            // ── 宣传部 ──────────────────────────────────────────────────────
            ['宣传部', '宣传部部长',       '🏆', 87, 94, 1, 800, 1],
            ['宣传部', '宣传部政委',       '👤', 87, 94, 1, 800, 2],
            ['宣传部', '宣传部常务副部长', '📋', 85, 93, 1, 500, 3],
            ['宣传部', '宣传部副部长',     '🔵', 83, 92, 1, 300, 4],
            ['宣传部', '宣传部副政委',     '🔵', 81, 91, 1, 300, 5],
            ['宣传部', '金牌宣传员',       '🥇', 70, 90, 2, null, 6],
            ['宣传部', '银牌宣传员',       '🥈', 50, 80, 3, null, 7],
            ['宣传部', '铜牌宣传员',       '🥉', 30, 70, 4, null, 8],
            ['宣传部', '实习宣传员',       '🌱', 10, 60, 4, null, 9],
        ];

        return array_map(fn ($r) => [
            'department' => $r[0],
            'name' => $r[1],
            'icon' => $r[2],
            'rank' => $r[3],
            'level' => $r[4],
            'max_persons' => $r[5],
            'max_reward' => $r[6],
            'sort_order' => $r[7],
        ], $rows);
    }

    /**
     * 默认任命权限白名单
     * key = "任命人职务对应的 positions key"
     * value = [可被任命的职务 key 列表]
     *
     * @param  array<string, Position>  $positions
     * @return array<int, array{0: string, 1: list<string>}>
     */
    private function appointLimitsData(array $positions): array
    {
        // 全三部门的所有职务 key 列表（不含办公厅）
        $allThreeDepts = array_keys(array_filter(
            $positions,
            fn ($k) => ! str_starts_with($k, '办公厅::'),
            ARRAY_FILTER_USE_KEY
        ));

        // 三部门所有部长/政委及以下（全部）
        $allThreeAll = $allThreeDepts;

        // 三部门常务副部长及以下（level <= 93）
        $allThreeBelowZhangzhang = array_keys(array_filter(
            $positions,
            fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 93,
            ARRAY_FILTER_USE_BOTH
        ));

        // 三部门副部长/副政委及以下（level <= 92）
        $allThreeBelowFubu = array_keys(array_filter(
            $positions,
            fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 92,
            ARRAY_FILTER_USE_BOTH
        ));

        // 三部门金牌及以下（level <= 90）
        $allThreeBelowGold = array_keys(array_filter(
            $positions,
            fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 90,
            ARRAY_FILTER_USE_BOTH
        ));

        // 三部门银牌及以下（level <= 80）
        $allThreeBelowSilver = array_keys(array_filter(
            $positions,
            fn ($p, $k) => ! str_starts_with($k, '办公厅::') && $p->level <= 80,
            ARRAY_FILTER_USE_BOTH
        ));

        /**
         * 便捷闭包：获取指定部门、指定最大 level 的职务 key 列表
         */
        $deptBelow = fn (string $dept, int $maxLevel) => array_keys(array_filter(
            $positions,
            fn ($p, $k) => str_starts_with($k, "{$dept}::") && $p->level <= $maxLevel,
            ARRAY_FILTER_USE_BOTH
        ));

        return [
            // 办公厅
            ['办公厅::站长',       array_merge(
                ['办公厅::执行站长', '办公厅::常务副站长', '办公厅::副站长', '办公厅::秘书长', '办公厅::三部总长'],
                $allThreeAll
            )],
            ['办公厅::执行站长',   $allThreeAll],               // 三部所有职务
            ['办公厅::常务副站长', $allThreeBelowZhangzhang],   // 三部常务副部长及以下
            ['办公厅::副站长',     $allThreeBelowFubu],         // 三部副部长级及以下
            ['办公厅::秘书长',     $allThreeBelowGold],         // 三部金牌及以下
            ['办公厅::三部总长',   $allThreeBelowSilver],       // 三部银牌及以下
            // 迎宾部
            ['迎宾部::迎宾部长',       $deptBelow('迎宾部', 90)],
            ['迎宾部::迎宾政委',       $deptBelow('迎宾部', 90)],
            ['迎宾部::迎宾常务副部长', $deptBelow('迎宾部', 80)],
            ['迎宾部::迎宾副部长',     $deptBelow('迎宾部', 70)],
            ['迎宾部::迎宾副政委',     $deptBelow('迎宾部', 70)],
            // 聊务部
            ['聊务部::聊务部部长',       $deptBelow('聊务部', 90)],
            ['聊务部::聊务部政委',       $deptBelow('聊务部', 90)],
            ['聊务部::聊务部常务副部长', $deptBelow('聊务部', 80)],
            ['聊务部::聊务部副部长',     $deptBelow('聊务部', 70)],
            ['聊务部::聊务部副政委',     $deptBelow('聊务部', 70)],
            // 宣传部
            ['宣传部::宣传部部长',       $deptBelow('宣传部', 90)],
            ['宣传部::宣传部政委',       $deptBelow('宣传部', 90)],
            ['宣传部::宣传部常务副部长', $deptBelow('宣传部', 80)],
            ['宣传部::宣传部副部长',     $deptBelow('宣传部', 70)],
            ['宣传部::宣传部副政委',     $deptBelow('宣传部', 70)],
        ];
    }
}
