<?php

namespace App\Filament\Pages;

use App\Models\SourcePaper;
use App\Models\Textbook;
use Filament\Pages\Page;
use Illuminate\Support\Arr;

class SourcePaperEnrichment extends Page
{
    protected static bool $shouldRegisterNavigation = false;
    protected static ?string $navigationLabel = '卷子信息补录';
    protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-document-text';
    protected static string|\UnitEnum|null $navigationGroup = '卷子导入流程';
    protected static ?int $navigationSort = 99;

    protected string $view = 'filament.pages.source-paper-enrichment';

    public string $search = '';
    public ?string $gradeFilter = null;
    public ?string $termFilter = null;
    public bool $dense = false;

    public ?int $selectedPaperId = null;
    public array $selectedIds = [];

    public array $form = [
        'edition' => null,
        'grade' => null,
        'term' => null,
        'chapter' => null,
        'source_type' => null,
        'source_year' => null,
        'textbook_id' => null,
        'textbook_series' => null,
        'source_name' => null,
        'source_page' => null,
        'tags' => '',
    ];

    public array $batch = [
        'edition' => null,
        'grade' => null,
        'term' => null,
        'chapter' => null,
        'source_type' => null,
        'source_year' => null,
        'textbook_id' => null,
        'textbook_series' => null,
        'source_name' => null,
        'source_page' => null,
        'tags' => '',
    ];

    public function mount(): void
    {
        $first = $this->papers()->first();
        if ($first) {
            $this->selectPaper($first->id);
        }
    }

    public function papers()
    {
        $query = SourcePaper::query()->with(['textbook']);

        if ($this->search !== '') {
            $query->where(function ($q) {
                $q->where('title', 'like', '%' . $this->search . '%')
                    ->orWhere('full_title', 'like', '%' . $this->search . '%')
                    ->orWhere('paper_code', 'like', '%' . $this->search . '%');
            });
        }

        if ($this->gradeFilter) {
            $query->where('grade', $this->gradeFilter);
        }

        if ($this->termFilter) {
            $query->where('term', $this->termFilter);
        }

        return $query->orderByDesc('id')->limit(80)->get();
    }

    public function selectedPaper(): ?SourcePaper
    {
        if (!$this->selectedPaperId) {
            return null;
        }

        return SourcePaper::query()->with('textbook')->find($this->selectedPaperId);
    }

    public function selectAllVisible(): void
    {
        $this->selectedIds = $this->papers()->pluck('id')->toArray();
    }

    public function clearSelection(): void
    {
        $this->selectedIds = [];
    }

    public function selectPaper(int $paperId): void
    {
        $paper = SourcePaper::query()->find($paperId);
        if (!$paper) {
            return;
        }

        $this->selectedPaperId = $paperId;
        $meta = $paper->meta ?? [];

        $this->form = [
            'edition' => $paper->edition,
            'grade' => $paper->grade,
            'term' => $paper->term,
            'chapter' => $paper->chapter,
            'source_type' => $paper->source_type,
            'source_year' => $paper->source_year,
            'textbook_id' => $paper->textbook_id,
            'textbook_series' => $paper->textbook_series,
            'source_name' => Arr::get($meta, 'source_name'),
            'source_page' => Arr::get($meta, 'source_page'),
            'tags' => implode(',', Arr::get($meta, 'tags', [])),
        ];
    }

    public function savePaper(): void
    {
        $paper = $this->selectedPaper();
        if (!$paper) {
            return;
        }

        $meta = $paper->meta ?? [];
        $meta['source_name'] = $this->form['source_name'] ?? null;
        $meta['source_page'] = $this->form['source_page'] ?? null;
        $meta['tags'] = $this->explodeTags($this->form['tags'] ?? '');

        $paper->update([
            'edition' => $this->form['edition'] ?? null,
            'grade' => $this->form['grade'] ?? null,
            'term' => $this->form['term'] ?? null,
            'chapter' => $this->form['chapter'] ?? null,
            'source_type' => $this->form['source_type'] ?? null,
            'source_year' => $this->form['source_year'] ?? null,
            'textbook_id' => $this->form['textbook_id'] ?? null,
            'textbook_series' => $this->form['textbook_series'] ?? null,
            'meta' => $meta,
        ]);
    }

    public function applyBatch(): void
    {
        if (empty($this->selectedIds)) {
            return;
        }

        $updates = array_filter([
            'edition' => $this->batch['edition'] ?? null,
            'grade' => $this->batch['grade'] ?? null,
            'term' => $this->batch['term'] ?? null,
            'chapter' => $this->batch['chapter'] ?? null,
            'source_type' => $this->batch['source_type'] ?? null,
            'source_year' => $this->batch['source_year'] ?? null,
            'textbook_id' => $this->batch['textbook_id'] ?? null,
            'textbook_series' => $this->batch['textbook_series'] ?? null,
        ], fn ($value) => $value !== null && $value !== '');

        foreach (SourcePaper::query()->whereIn('id', $this->selectedIds)->get() as $paper) {
            $meta = $paper->meta ?? [];
            if (!empty($this->batch['source_name'])) {
                $meta['source_name'] = $this->batch['source_name'];
            }
            if (!empty($this->batch['source_page'])) {
                $meta['source_page'] = $this->batch['source_page'];
            }
            if (!empty($this->batch['tags'])) {
                $meta['tags'] = $this->explodeTags($this->batch['tags']);
            }

            $paper->update(array_merge($updates, ['meta' => $meta]));
        }
    }

    public function autoInfer(): void
    {
        $paper = $this->selectedPaper();
        if (!$paper) {
            return;
        }

        $title = (string) ($paper->title ?? $paper->full_title ?? '');
        $raw = (string) ($paper->raw_markdown ?? '');
        $context = $title . ' ' . $raw;

        $this->form['term'] = $this->inferTerm($context) ?? $this->form['term'];
        $this->form['grade'] = $this->inferGrade($context) ?? $this->form['grade'];
        $this->form['chapter'] = $this->inferChapter($context) ?? $this->form['chapter'];
    }

    public function autoInferSelected(): void
    {
        if (empty($this->selectedIds)) {
            return;
        }

        foreach (SourcePaper::query()->whereIn('id', $this->selectedIds)->get() as $paper) {
            $context = (string) ($paper->title ?? $paper->full_title ?? '') . ' ' . (string) ($paper->raw_markdown ?? '');
            $updates = array_filter([
                'term' => $this->inferTerm($context),
                'grade' => $this->inferGrade($context),
                'chapter' => $this->inferChapter($context),
            ], fn ($value) => $value !== null && $value !== '');

            if (!empty($updates)) {
                $paper->update($updates);
            }
        }
    }

    public function textbookOptions(): array
    {
        return Textbook::query()->orderBy('id')->pluck('official_title', 'id')->toArray();
    }

    public function gradeOptions(): array
    {
        return collect(range(1, 12))->mapWithKeys(fn ($grade) => [$grade => $grade . '年级'])->toArray();
    }

    public function termOptions(): array
    {
        return [
            '上册' => '上册',
            '下册' => '下册',
            '上学期' => '上学期',
            '下学期' => '下学期',
        ];
    }

    public function sourceTypeOptions(): array
    {
        return [
            '期中' => '期中卷',
            '期末' => '期末卷',
            '单元卷' => '单元卷',
            '专项卷' => '专项卷',
            '教材' => '教材',
            '其他' => '其他',
        ];
    }

    private function inferTerm(string $context): ?string
    {
        if (str_contains($context, '上册') || str_contains($context, '上学期')) {
            return '上册';
        }
        if (str_contains($context, '下册') || str_contains($context, '下学期')) {
            return '下册';
        }
        return null;
    }

    private function inferGrade(string $context): ?string
    {
        foreach (['七年级' => '7', '八年级' => '8', '九年级' => '9', '高一' => '10', '高二' => '11', '高三' => '12'] as $label => $value) {
            if (str_contains($context, $label)) {
                return $value;
            }
        }
        return null;
    }

    private function inferChapter(string $context): ?string
    {
        if (preg_match('/第[一二三四五六七八九十]+章[^\\n]*/u', $context, $match)) {
            return $match[0];
        }
        return null;
    }

    private function explodeTags(string $tags): array
    {
        return array_values(array_filter(array_map('trim', explode(',', $tags))));
    }
}
