import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Router } from '@angular/router'; import { LucideAngularModule, Plus, Check, Drama, Clapperboard, BookText, GitBranch, Dices, ExternalLink } from 'lucide-angular'; import { CampaignService } from '../../../services/campaign.service'; import { NpcService } from '../../../services/npc.service'; import { RandomTableService } from '../../../services/random-table.service'; import { Arc, Chapter } from '../../../services/campaign.model'; import { NotebookAction } from '../../../services/notebook-action.model'; /** * Carte « Créer dans la campagne » issue d'une proposition de l'IA. Gère la cible * (chapitre pour une scène, arc pour un chapitre) et appelle les services existants. */ @Component({ selector: 'app-notebook-action-card', standalone: true, imports: [CommonModule, FormsModule, LucideAngularModule], templateUrl: './notebook-action-card.component.html', styleUrls: ['./notebook-action-card.component.scss'] }) export class NotebookActionCardComponent implements OnInit { readonly Plus = Plus; readonly Check = Check; readonly ExternalLink = ExternalLink; @Input() action!: NotebookAction; @Input() campaignId!: string; @Input() arcs: Arc[] = []; @Input() chaptersByArc: Record = {}; /** Émis après une création réussie → l'atelier rafraîchit la sidebar. */ @Output() created = new EventEmitter(); selectedArcId = ''; selectedChapterId = ''; status: 'idle' | 'creating' | 'created' | 'error' = 'idle'; errorMsg = ''; createdRoute: string[] | null = null; constructor( private campaignService: CampaignService, private npcService: NpcService, private tableService: RandomTableService, private router: Router ) {} ngOnInit(): void { if (this.arcs.length) this.selectedArcId = this.arcs[0].id!; this.syncChapter(); } get typeLabel(): string { switch (this.action.type) { case 'npc': return 'PNJ'; case 'scene': return 'Scène'; case 'chapter': return 'Chapitre'; case 'arc': return 'Arc'; case 'table': return 'Table aléatoire'; default: return this.action.type; } } get typeIcon() { switch (this.action.type) { case 'npc': return Drama; case 'scene': return Clapperboard; case 'chapter': return BookText; case 'arc': return GitBranch; case 'table': return Dices; default: return Plus; } } get needsArc(): boolean { return this.action.type === 'chapter' || this.action.type === 'scene'; } get needsChapter(): boolean { return this.action.type === 'scene'; } get targetChapters(): Chapter[] { return this.chaptersByArc[this.selectedArcId] ?? []; } syncChapter(): void { const chs = this.targetChapters; this.selectedChapterId = chs.length ? chs[0].id! : ''; } get canCreate(): boolean { if (this.status === 'creating' || this.status === 'created') return false; if (this.needsArc && !this.selectedArcId) return false; if (this.needsChapter && !this.selectedChapterId) return false; return true; } create(): void { if (!this.canCreate) return; this.status = 'creating'; this.errorMsg = ''; switch (this.action.type) { case 'npc': return this.createNpc(); case 'arc': return this.createArc(); case 'chapter': return this.createChapter(); case 'scene': return this.createScene(); case 'table': return this.createTable(); } } private createNpc(): void { this.npcService.create({ name: this.action.name, campaignId: this.campaignId, values: this.action.description ? { Description: this.action.description } : {} }).subscribe({ next: (n) => this.done(['/campaigns', this.campaignId, 'npcs', n.id!]), error: (e) => this.fail(e) }); } private createArc(): void { this.campaignService.createArc({ name: this.action.name, description: this.action.description, campaignId: this.campaignId, order: this.arcs.length, type: this.action.arcType === 'HUB' ? 'HUB' : 'LINEAR' }).subscribe({ next: (a) => this.done(['/campaigns', this.campaignId, 'arcs', a.id!]), error: (e) => this.fail(e) }); } private createChapter(): void { const order = (this.chaptersByArc[this.selectedArcId] ?? []).length; this.campaignService.createChapter({ name: this.action.name, description: this.action.description, arcId: this.selectedArcId, order }).subscribe({ next: (c) => this.done(['/campaigns', this.campaignId, 'arcs', this.selectedArcId, 'chapters', c.id!]), error: (e) => this.fail(e) }); } private createScene(): void { this.campaignService.createScene({ name: this.action.name, description: this.action.description, playerNarration: this.action.content, chapterId: this.selectedChapterId, order: 0 }).subscribe({ next: (s) => this.done( ['/campaigns', this.campaignId, 'arcs', this.selectedArcId, 'chapters', this.selectedChapterId, 'scenes', s.id!]), error: (e) => this.fail(e) }); } private createTable(): void { this.tableService.create({ name: this.action.name, diceFormula: this.action.diceFormula || '1d20', campaignId: this.campaignId, entries: (this.action.entries ?? []).map(e => ({ minRoll: e.minRoll, maxRoll: e.maxRoll, label: e.label, detail: e.detail })) }).subscribe({ next: (t) => this.done(['/campaigns', this.campaignId, 'random-tables', t.id!]), error: (e) => this.fail(e) }); } private done(route: string[]): void { this.status = 'created'; this.createdRoute = route; this.created.emit(); } private fail(err: unknown): void { this.status = 'error'; this.errorMsg = (err as { error?: { message?: string } })?.error?.message || 'Échec de la création.'; } openCreated(): void { if (this.createdRoute) this.router.navigate(this.createdRoute); } }