<?php

namespace App\Filament\Resources;

use App\Filament\Resources\MarkdownImportResource\Pages;
use App\Models\MarkdownImport;
use BackedEnum;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Notifications\Notification;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Schemas\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Collection;
use UnitEnum;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use App\Support\TextEncoding;
use App\Rules\MarkdownFileExtension;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Enums\FiltersLayout;

class MarkdownImportResource extends Resource
{
    protected static ?string $model = MarkdownImport::class;

    protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-arrow-up-tray';

    protected static ?string $navigationLabel = 'Markdown 导入';

    protected static ?string $modelLabel = 'Markdown 导入';

    protected static ?string $pluralModelLabel = 'Markdown 导入';

    protected static UnitEnum|string|null $navigationGroup = '卷子导入流程';

    protected static ?int $navigationSort = 1;

    protected static ?string $title = 'Markdown 试卷导入管理';

    protected static ?string $description = '导入 Markdown 格式的数学试卷，AI 智能识别题目，人工校对后入库';

    public static function mutateFormDataBeforeCreate(array $data): array
    {
        // 支持上传 markdown 文件：读取内容写入 original_markdown
        if (!empty($data['markdown_file']) && empty($data['original_markdown'])) {
            $path = $data['markdown_file'];
            if (is_string($path) && Storage::disk('local')->exists($path)) {
                $data['original_markdown'] = TextEncoding::toUtf8(Storage::disk('local')->get($path));
            }
        }

        // 文件名默认取上传文件名（优先原始文件名，其次取存储路径 basename）
        if (empty($data['file_name']) && !empty($data['markdown_file'])) {
            $storedNames = $data['uploaded_file_names'] ?? null;
            if (is_array($storedNames) && !empty($storedNames)) {
                $data['file_name'] = (string) array_values($storedNames)[0];
            } else {
                $path = is_array($data['markdown_file']) ? ($data['markdown_file'][0] ?? '') : (string) $data['markdown_file'];
                $data['file_name'] = $path !== '' ? basename($path) : null;
            }
        }

        // 文件名作为来源名称
        if (!empty($data['file_name'])) {
            $data['source_name'] = $data['file_name'];
            $data['source_type'] = 'other';
        }

        unset($data['markdown_file']);
        unset($data['uploaded_file_names']);

        return $data;
    }

    /**
     * 允许创建新的 Markdown 导入记录
     */
    public static function canCreate(): bool
    {
        return true;
    }

    public static function form(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Section::make('上传与来源信息')
                    ->schema([
                        \Filament\Forms\Components\TextInput::make('file_name')
                            ->label('文件名（来源名称）')
                            ->required(fn (Get $get): bool => empty($get('markdown_file')))
                            ->maxLength(255),

                        FileUpload::make('markdown_file')
                            ->label('Markdown 文件（可选）')
                            ->disk('local')
                            ->directory('imports/markdown')
                            ->helperText('仅支持 .md / .markdown / .txt；上传后会自动读取内容并填充编辑器')
                            ->maxSize(10 * 1024)
                            ->storeFileNamesIn('uploaded_file_names')
                            ->dehydrated(true)
                            ->preserveFilenames()
                            ->rules([new MarkdownFileExtension()])
                            ->afterStateUpdated(function ($state, Set $set, Get $get): void {
                                // 在提交表单前，FileUpload 的 state 可能还是 TemporaryUploadedFile（尚未保存到 disk）
                                $first = is_array($state) ? ($state[0] ?? null) : $state;

                                if ($first instanceof TemporaryUploadedFile) {
                                    $set('original_markdown', TextEncoding::toUtf8((string) @file_get_contents($first->getRealPath())));

                                    if (empty($get('file_name'))) {
                                        $set('file_name', $first->getClientOriginalName());
                                    }

                                    return;
                                }

                                $paths = is_array($state) ? $state : (empty($state) ? [] : [$state]);
                                $path = (string) ($paths[0] ?? '');
                                if ($path === '') {
                                    return;
                                }

                                // 已保存到 disk 后：读取文件内容填充编辑器
                                if (Storage::disk('local')->exists($path)) {
                                    $set('original_markdown', TextEncoding::toUtf8(Storage::disk('local')->get($path)));
                                }

                                // 上传后的真实文件名：BaseFileUpload 会在保存时 storeFileName($storedFile, originalName)
                                $storedNames = $get('uploaded_file_names');
                                if (is_string($storedNames) && $storedNames !== '') {
                                    $set('file_name', $storedNames);
                                } elseif (empty($get('file_name'))) {
                                    $set('file_name', basename($path));
                                }
                            }),

                        Hidden::make('uploaded_file_names')
                            ->dehydrated(true),
                    ])
                    ->columns(2),

                Section::make('解析规则（可选）')
                    ->schema([
                        Select::make('parse_mode')
                            ->label('解析模式')
                            ->options([
                                'strict' => '严格模式',
                                'relaxed' => '宽松模式',
                            ])
                            ->default('strict')
                            ->dehydrated(false),
                        TextInput::make('split_marker')
                            ->label('分题符号')
                            ->placeholder('如：---')
                            ->dehydrated(false),
                        TextInput::make('type_marker')
                            ->label('题型标记')
                            ->placeholder('如：#选择题')
                            ->dehydrated(false),
                        Toggle::make('auto_detect_images')
                            ->label('自动识别图片')
                            ->default(true)
                            ->dehydrated(false),
                    ])
                    ->columns(2)
                    ->collapsed(),

                Section::make('Markdown 内容')
                    ->schema([
                        MarkdownEditor::make('original_markdown')
                            ->label('Markdown 内容（编辑器）')
                            ->required(fn (Get $get): bool => empty($get('markdown_file')))
                            ->columnSpanFull()
                            // 固定编辑器高度，避免内容过长把页面撑开
                            ->minHeight('45vh')
                            ->maxHeight('45vh')
                            ->toolbarButtons([
                                'bold',
                                'italic',
                                'strike',
                                'blockquote',
                                'bulletList',
                                'orderedList',
                                'link',
                                'codeBlock',
                                'table',
                                'undo',
                                'redo',
                            ]),
                    ]),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                // 文件名列 - 固定宽度，可折行显示
                TextColumn::make('file_name')
                    ->label('文件')
                    ->searchable()
                    ->sortable()
                    ->weight('bold')
                    ->color('gray-900')
                    ->wrap()
                    ->width('200px'),

                // 状态列 - 固定宽度，只显示基本状态
                TextColumn::make('current_status')
                    ->label('状态')
                    ->getStateUsing(function (?Model $record): string {
                        if (!$record) return '—';

                        return match ($record->status) {
                            'pending' => '⏳ 待处理',
                            'processing' => '🟡 处理中',
                            'parsed' => '✅ 已解析',
                            'reviewed' => '📝 已校对',
                            'completed' => '🎉 已完成',
                            'failed' => '❌ 处理失败',
                            default => '—',
                        };
                    })
                    ->badge()
                    ->color(fn (?Model $record): string => match ($record?->status ?? '') {
                        'pending' => 'gray',
                        'processing' => 'warning',
                        'parsed' => 'success',
                        'reviewed' => 'primary',
                        'completed' => 'success',
                        'failed' => 'danger',
                        default => 'gray',
                    })
                    ->width('120px'),

                // 详细信息列 - 显示完整进度信息，包括总数
                TextColumn::make('detailed_progress')
                    ->label('详情')
                    ->getStateUsing(function (?Model $record): string {
                        if (!$record) return '—';

                        return match ($record->status) {
                            'processing' => $record->progress_message ?: sprintf(
                                'AI 解析中：%d/%d 题',
                                $record->progress_current ?? 0,
                                $record->progress_total ?? 0
                            ),
                            'parsed' => sprintf(
                                '已解析 %d/%d 题，等待校对',
                                $record->parsed_count ?? 0,
                                $record->progress_total ?? 0
                            ),
                            'reviewed' => sprintf(
                                '已校对 %d/%d 题，待入库',
                                $record->accepted_count ?? 0,
                                $record->progress_total ?? 0
                            ),
                            'completed' => sprintf(
                                '成功入库 %d/%d 题',
                                $record->accepted_count ?? 0,
                                $record->progress_total ?? 0
                            ),
                            'failed' => '处理失败：' . ($record->error_message ?: '未知错误'),
                            'pending' => '准备就绪，总计 ' . ($record->progress_total ?? 0) . ' 题',
                            default => '—',
                        };
                    })
                    ->wrap()
                    ->color('gray-600')
                    ->width('1fr'), // 占据剩余所有空间

                // 快速操作列 - 固定宽度
                TextColumn::make('quick_actions')
                    ->label('操作')
                    ->getStateUsing(function (?Model $record): string {
                        if (!$record) return '—';

                        return match ($record->status) {
                            'processing' => '🔄 处理中',
                            'parsed', 'reviewed' => '👁️ 查看校对',
                            'completed' => '📊 查看结果',
                            'failed' => '🔁 重试',
                            'pending' => '▶️ 开始',
                            default => '—',
                        };
                    })
                    ->url(function (?Model $record): ?string {
                        if (!$record) return null;

                        return match ($record->status) {
                            'parsed', 'reviewed' => route('filament.admin.resources.pre-question-candidates.index', [
                                'import_id' => $record->id,
                                'tab' => $record->status === 'reviewed' ? 'reviewed' : null
                            ]),
                            'completed' => route('filament.admin.pages.markdown-import-workbench', [
                                'import_id' => $record->id,
                            ]),
                            default => null,
                        };
                    })
                    ->color('primary')
                    ->weight('medium')
                    ->wrap()
                    ->width('100px'),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('status')
                    ->label('状态')
                    ->options([
                        'pending' => '待处理',
                        'processing' => '处理中',
                        'parsed' => '已解析',
                        'reviewed' => '已校对',
                        'completed' => '已完成',
                        'failed' => '处理失败',
                    ]),

                Tables\Filters\SelectFilter::make('source_type')
                    ->label('来源类型')
                    ->options([
                        'textbook' => '教材',
                        'exam' => '考试',
                        'other' => '其他',
                    ]),
                Tables\Filters\SelectFilter::make('filename_parse')
                    ->label('命名规范')
                    ->options([
                        'valid' => '正常',
                        'invalid' => '不规范',
                    ])
                    ->query(function (Builder $query, array $data) {
                        $value = $data['value'] ?? null;
                        $driver = DB::getDriverName();
                        $regex = '^.+_[0-9]+_[0-2]_.+_.+$';

                        if ($value === 'valid') {
                            if ($driver === 'mysql') {
                                $query->whereRaw('file_name REGEXP ?', [$regex]);
                            } else {
                                $query->where('file_name', 'like', '%_%_%_%_%');
                            }
                        }
                        if ($value === 'invalid') {
                            if ($driver === 'mysql') {
                                $query->where(function ($q) use ($regex) {
                                    $q->whereNull('file_name')->orWhereRaw('file_name NOT REGEXP ?', [$regex]);
                                });
                            } else {
                                $query->where(function ($q) {
                                    $q->whereNull('file_name')->orWhere('file_name', 'not like', '%_%_%_%_%');
                                });
                            }
                        }
                    }),
            ], layout: FiltersLayout::AboveContentCollapsible)
            ->actions([
                // 第一行按钮 - 主要操作
                EditAction::make()
                    ->label('编辑')
                    ->size('sm'),

                Action::make('workbench')
                    ->label('工作台')
                    ->icon('heroicon-o-rectangle-stack')
                    ->color('primary')
                    ->size('sm')
                    ->visible(fn (?Model $record): bool => !empty($record?->parseFilename()))
                    ->url(fn (?Model $record): string => route('filament.admin.pages.markdown-import-workbench', [
                        'import_id' => $record?->id,
                    ])),

                Action::make('review')
                    ->label('校对')
                    ->icon('heroicon-o-clipboard-document-list')
                    ->color('success')
                    ->size('sm')
                    ->visible(fn (?Model $record): bool => in_array($record?->status, ['parsed', 'reviewed', 'completed']) && !empty($record?->parseFilename()))
                    ->url(function (?Model $record): string {
                        $importId = $record?->id;
                        $status = $record?->status;

                        if ($status === 'parsed') {
                            return route('filament.admin.resources.pre-question-candidates.index', [
                                'import_id' => $importId
                            ]);
                        } elseif (in_array($status, ['reviewed', 'completed'])) {
                            return route('filament.admin.resources.pre-question-candidates.index', [
                                'import_id' => $importId,
                                'tab' => 'reviewed'
                            ]);
                        }

                        return route('filament.admin.resources.pre-question-candidates.index', [
                            'import_id' => $importId
                        ]);
                    }),

                Action::make('delete')
                    ->label('删除')
                    ->icon('heroicon-o-trash')
                    ->color('danger')
                    ->size('sm')
                    ->requiresConfirmation()
                    ->modalHeading('删除导入记录')
                    ->modalDescription('确定要删除这条导入记录吗？此操作不可撤销。')
                    ->action(function (?Model $record) {
                        if ($record) {
                            $record->delete();
                            Notification::make()
                                ->title('删除成功')
                                ->success()
                                ->send();
                        }
                    }),

                // 第二行按钮 - 处理操作
                Action::make('run_pipeline')
                    ->label('全流程')
                    ->icon('heroicon-o-play-circle')
                    ->color('success')
                    ->size('sm')
                    ->requiresConfirmation()
                    ->modalHeading('触发 Markdown 拆分 + AI 结构化')
                    ->modalDescription('立即提交队列，按 source_file → source_paper → paper_part → candidate → AI 结构化 执行。')
                    ->action(function (?Model $record) {
                        if (!$record) {
                            return;
                        }
                        dispatch(new \App\Jobs\ProcessMarkdownSplit($record->id));
                        $record->update([
                            'status' => MarkdownImport::STATUS_PROCESSING,
                            'progress_stage' => MarkdownImport::STAGE_QUEUED,
                            'progress_message' => '已进入队列…',
                            'processing_started_at' => now(),
                            'processing_finished_at' => null,
                            'error_message' => null,
                        ]);

                        Notification::make()
                            ->title('已提交解析队列')
                            ->success()
                            ->send();
                    }),

                Action::make('parse')
                    ->label('解析')
                    ->icon('heroicon-o-cog-6-tooth')
                    ->color('info')
                    ->size('sm')
                    ->visible(fn (?Model $record): bool => in_array($record?->status, ['pending', 'failed']))
                    ->requiresConfirmation()
                    ->modalHeading('解析 Markdown')
                    ->modalDescription('将解析 Markdown 中的题目候选，并使用 AI 进行初步筛选。')
                    ->action(function (?Model $record) {
                        if ($record) {
                            static::parseMarkdown($record);
                        }
                    }),

                Action::make('ai_parse')
                    ->label('AI解析')
                    ->icon('heroicon-o-sparkles')
                    ->color('warning')
                    ->size('sm')
                    ->visible(fn (?Model $record): bool => in_array($record?->status, ['pending', 'processing', 'parsed', 'failed']))
                    ->requiresConfirmation()
                    ->modalHeading('重新执行 AI 解析')
                    ->modalDescription('将对所有候选题重新进行 AI 结构化解析，清除之前的解析标记。此操作不会重新拆分题目。')
                    ->action(function (?Model $record) {
                        if (!$record) {
                            return;
                        }

                        static::triggerAiParsing($record);
                    }),
            ])
            ->bulkActions([
                BulkActionGroup::make([
                    DeleteBulkAction::make(),

                    BulkAction::make('bulk_ai_parse')
                        ->label('批量 AI 解析')
                        ->icon('heroicon-o-sparkles')
                        ->color('warning')
                        ->requiresConfirmation()
                        ->modalHeading('批量执行 AI 解析')
                        ->modalDescription('将对选中的所有记录重新执行 AI 结构化解析，清除之前的解析标记。')
                        ->action(function (Collection $records) {
                            foreach ($records as $record) {
                                static::triggerAiParsing($record);
                            }
                        }),
                ]),
            ])
            ->recordClasses(fn (Model $record) => $record->status === 'failed' ? 'bg-rose-50/60' : null)
            ->defaultSort('created_at', 'desc')
            ->paginated([10, 25, 50, 100]);
    }

    public static function getEloquentQuery(): Builder
    {
        // 让 parsed_count / accepted_count 成为可排序的 SQL 字段（避免 order by accessor 报错）
        return parent::getEloquentQuery()
            ->withCount([
                'candidates as parsed_count' => fn (Builder $query) => $query->where('status', '!=', 'superseded'),
                'candidates as accepted_count' => fn (Builder $query) => $query
                    ->where('status', '!=', 'superseded')
                    ->where('is_question_candidate', true),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListMarkdownImports::route('/'),
            'create' => Pages\CreateMarkdownImport::route('/create'),
            'edit' => Pages\EditMarkdownImport::route('/{record}/edit'),
        ];
    }


    /**
     * 解析 Markdown
     */
    public static function parseMarkdown(Model $record): void
    {
        try {
            // 验证状态
            if (!in_array($record->status, ['pending', 'failed'], true)) {
                Notification::make()
                    ->title('只能解析待处理或失败状态的记录')
                    ->warning()
                    ->send();
                return;
            }

            // 验证 markdown 内容
            if (empty($record->original_markdown)) {
                Notification::make()
                    ->title('Markdown 内容不能为空')
                    ->warning()
                    ->send();
                return;
            }

            // 失败状态重试：清空错误信息并重新进入待处理
            if ($record->status === 'failed') {
                $record->update([
                    'status' => 'pending',
                    'error_message' => null,
                ]);
            }

            // 先更新状态，确保列表页可见变化（避免“点了没反应”的体验）
            $record->update([
                'status' => 'processing',
                'progress_stage' => \App\Models\MarkdownImport::STAGE_QUEUED,
                'progress_message' => '已提交解析任务，等待处理…',
                'progress_current' => 0,
                'progress_total' => 0,
                'progress_updated_at' => now(),
                'processing_started_at' => now(),
                'processing_finished_at' => null,
                'error_message' => null,
            ]);

            \Log::info('Markdown import parse queued', [
                'import_id' => $record->id,
                'status' => $record->status,
                'stage' => $record->progress_stage,
            ]);

            // 派发异步任务
            \App\Jobs\ProcessMarkdownSplit::dispatch($record->id);

            Notification::make()
                ->title('已提交解析任务，正在后台处理...')
                ->body('列表页将自动刷新显示进度；若长期无进度，请确认 queue worker 正在运行。')
                ->success()
                ->send();

        } catch (\Exception $e) {
            Notification::make()
                ->title('解析失败：' . $e->getMessage())
                ->danger()
                ->send();
        }
    }

    /**
     * 重新执行 AI 解析
     */
    public static function triggerAiParsing(Model $record): void
    {
        try {
            // 检查是否有候选题
            $candidateCount = \App\Models\PreQuestionCandidate::where('import_id', $record->id)
                ->where('status', '!=', 'superseded')
                ->count();

            if ($candidateCount === 0) {
                Notification::make()
                    ->title('没有找到候选题，无法执行 AI 解析')
                    ->warning()
                    ->send();
                return;
            }

            // 清理旧的队列任务
            \Illuminate\Support\Facades\DB::table('jobs')
                ->where('payload', 'like', '%"markdownImportId":' . $record->id . '%')
                ->orWhere('payload', 'like', '%"markdownImportId";i:' . $record->id . ';%')
                ->delete();

            // 清除所有候选题的 AI 解析标记
            $candidates = \App\Models\PreQuestionCandidate::where('import_id', $record->id)
                ->where('status', '!=', 'superseded')
                ->get();

            foreach ($candidates as $candidate) {
                $meta = $candidate->meta ?? [];
                unset($meta['ai_parsed'], $meta['ai_parsed_at']);
                $candidate->update([
                    'stem' => null,
                    'options' => null,
                    'images' => null,
                    'tables' => null,
                    'ai_confidence' => null,
                    'confidence' => null,
                    'status' => 'pending',
                    'meta' => $meta,
                ]);
            }

            // 更新导入记录状态
            $record->update([
                'status' => 'processing',
                'progress_stage' => \App\Models\MarkdownImport::STAGE_AI_PARSING,
                'progress_message' => 'AI 解析中…',
                'progress_current' => 0,
                'progress_total' => $candidateCount,
                'progress_updated_at' => now(),
                'processing_started_at' => now(),
                'processing_finished_at' => null,
                'error_message' => null,
            ]);

            // 创建批次并派发 jobs
            $batchSize = 10;
            $batches = (int) ceil($candidateCount / $batchSize);

            for ($b = 0; $b < $batches; $b++) {
                $startSeq = ($b * $batchSize) + 1;
                $endSeq = min(($b + 1) * $batchSize, $candidateCount);

                \App\Jobs\ProcessMarkdownCandidateBatch::dispatch($record->id, $startSeq, $endSeq);
            }

            \Illuminate\Support\Facades\Log::info('AI parsing batches dispatched', [
                'import_id' => $record->id,
                'total_candidates' => $candidateCount,
                'batch_size' => $batchSize,
                'batches' => $batches,
            ]);

            Notification::make()
                ->title('已提交 AI 解析任务')
                ->body("共 {$candidateCount} 个候选题，已分为 {$batches} 个批次并发处理")
                ->success()
                ->send();

        } catch (\Exception $e) {
            Notification::make()
                ->title('AI 解析失败：' . $e->getMessage())
                ->danger()
                ->send();
        }
    }
}
