import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { DialogRef, DialogContentBase, DialogService } from '@progress/kendo-angular-dialog';
import { GridComponent, GridDataResult } from '@progress/kendo-angular-grid';
import { State } from '@progress/kendo-data-query';
import { first } from 'rxjs/operators';
import { MD2MobInfo, MD2MobLevelInfo, MD2MobSkill, MobSkillTarget, GameBundle } from '../../massive-darkness2.db.model';
import { MobType } from '../../massive-darkness2.model';
import { MobSkillType } from '../../massive-darkness2.model.boss';
import { MD2MobLevelInfoService, MD2MobSkillService } from '../../service/massive-darkness2.service';
import { MsgBoxService } from '../../../../services/msg-box.service';
import { MD2MobSkillEditorComponent } from '../md2-mob-skill-editor/md2-mob-skill-editor.component';

@Component({
    selector: 'ngx-md2-mob-info-detail',
    templateUrl: './md2-mob-info-detail.component.html',
    styleUrls: ['./md2-mob-info-detail.component.scss']
})
export class MD2MobInfoDetailComponent extends DialogContentBase implements OnInit {
    @Input() public mobInfo: MD2MobInfo;
    @ViewChild('levelsGrid') levelsGrid: GridComponent;
    @ViewChild('skillsGrid') skillsGrid: GridComponent;

    public mobLevelInfos: MD2MobLevelInfo[] = [];
    public levelsData: GridDataResult = { data: [], total: 0 };
    public levelsState: State = {
        skip: 0,
        take: 10,
        sort: [],
        filter: {
            logic: 'and',
            filters: []
        }
    };
    public selectedLevelInfo: MD2MobLevelInfo | null = null;
    public skillsData: GridDataResult = { data: [], total: 0 };
    public skillsState: State = {
        skip: 0,
        take: 10,
        sort: [],
        filter: {
            logic: 'and',
            filters: []
        }
    };
    public isLoading: boolean = false;

    public skillTypes: Array<{ value: MobSkillType; text: string }> = [];
    public skillTargets: Array<{ value: MobSkillTarget | null; text: string }> = [];

    constructor(
        public dialog: DialogRef,
        private dialogService: DialogService,
        private mobLevelInfoService: MD2MobLevelInfoService,
        private mobSkillService: MD2MobSkillService,
        private msgBoxService: MsgBoxService
    ) {
        super(dialog);
        this.initializeEnums();
    }

    ngOnInit(): void {
        if (this.mobInfo) {
            this.mobLevelInfos = this.mobInfo.mobLevelInfos || [];
            if (this.mobLevelInfos.length > 0) {
                this.selectLevelInfo(this.mobLevelInfos[0]);
            }
        }
    }

    private initializeEnums(): void {
        // Initialize MobSkillType options
        Object.keys(MobSkillType).filter(key => isNaN(Number(key))).forEach(key => {
            this.skillTypes.push({
                value: MobSkillType[key] as MobSkillType,
                text: key
            });
        });

        // Initialize MobSkillTarget options
        this.skillTargets.push({ value: null, text: 'None' });
        Object.keys(MobSkillTarget).filter(key => isNaN(Number(key))).forEach(key => {
            this.skillTargets.push({
                value: MobSkillTarget[key] as MobSkillTarget,
                text: key
            });
        });
    }

    public selectLevelInfo(levelInfo: MD2MobLevelInfo): void {
        if (levelInfo.defenceInfo == null) {
            levelInfo.defenceInfo = { blue: 0, green: 0, yellow: 0, orange: 0, red: 0, black: 0 };
        }
        if (levelInfo.attackInfo == null) {
            levelInfo.attackInfo = { blue: 0, green: 0, yellow: 0, orange: 0, red: 0, black: 0 };
        }
        this.selectedLevelInfo = levelInfo;
        this.loadSkills(levelInfo);
    }

    public editLevelHandler({ sender, rowIndex, dataItem }: any): void {
        // The template-driven editing directive handles edit mode automatically
        // This handler is here to ensure the grid enters edit mode
        // The grid should already be in edit mode from the directive, but we ensure it
    }

    public cancelLevelHandler({ sender, rowIndex }: any): void {
        // Cancel editing - template-driven editing handles this automatically
        sender.closeRow(rowIndex);
    }

    public addLevelHandler(): void {
        if (!this.mobInfo || !this.levelsGrid) return;

        const newLevel: MD2MobLevelInfo = {
            id: this.generateLevelId(),
            level: this.mobLevelInfos.length + 1,
            mobInfoId: this.mobInfo.id,
            rewardTokens: 0,
            fixedRareTreasure: 0,
            fixedEpicTreasure: 0,
            fixedLegendTreasure: 0,
            fixedHp: 1,
            hpPerHero: 0,
            actions: 1,
            attackInfo: { yellow: null, orange: null, red: null, blue: null, green: null, black: null },
            defenceInfo: { yellow: null, orange: null, red: null, blue: null, green: null, black: null },
            skills: []
        };

        // Use grid's addRow method to properly add a new row in edit mode
        this.levelsGrid.addRow(newLevel);
    }

    public saveLevelHandler({ dataItem, isNew }: any): void {
        if (isNew) {
            dataItem.id = this.generateLevelId();
            dataItem.mobInfoId = this.mobInfo?.id;
        }

        // Ensure required objects exist
        if (!dataItem.attackInfo) {
            dataItem.attackInfo = { yellow: null, orange: null, red: null, blue: null, green: null, black: null };
        }
        if (!dataItem.defenceInfo) {
            dataItem.defenceInfo = { yellow: null, orange: null, red: null, blue: null, green: null, black: null };
        }
        if (!dataItem.skills) {
            dataItem.skills = [];
        }

        this.isLoading = true;
        this.mobLevelInfoService.createOrUpdate(dataItem).pipe(first()).subscribe(result => {
            this.isLoading = false;
            if (isNew) {
                // For new items, add to the array

                result.attackInfo.black = 0;
                this.mobLevelInfos.push(result);
            } else {
                // For existing items, update in the array
                const index = this.mobLevelInfos.findIndex(l => l.id === result.id);
                if (index !== -1) {
                    this.mobLevelInfos[index] = result;
                    // Update selected level if it's the one being edited
                    if (this.selectedLevelInfo?.id === result.id) {
                        this.selectedLevelInfo = result;
                        this.loadSkills(result);
                    }
                }
            }
            // Close the edit row after saving
            if (this.levelsGrid) {
                const rowIndex = this.mobLevelInfos.findIndex(l => l.id === result.id);
                if (rowIndex !== -1) {
                    this.levelsGrid.closeRow(rowIndex);
                }
            }
        }, error => {
            this.isLoading = false;
            console.error('Error saving level info:', error);
        });
    }

    public removeLevelHandler({ dataItem }: { dataItem: MD2MobLevelInfo }): void {
        this.msgBoxService.showConfirmDeleteBox().pipe(first()).subscribe(answer => {
            if (answer === true) {
                this.isLoading = true;
                this.mobLevelInfoService.delete(dataItem.id).pipe(first()).subscribe(result => {
                    const index = this.mobLevelInfos.findIndex(l => l.id === dataItem.id);
                    if (index !== -1) {
                        this.mobLevelInfos.splice(index, 1);
                        // Clear selection if deleted level was selected
                        if (this.selectedLevelInfo?.id === dataItem.id) {
                            this.selectedLevelInfo = null;
                            this.skillsData = { data: [], total: 0 };
                        }
                    }
                    this.isLoading = false;
                });
            }
        });
    }

    public loadSkills(levelInfo: MD2MobLevelInfo): void {
        if (levelInfo && levelInfo.skills) {
            this.skillsData = {
                data: levelInfo.skills,
                total: levelInfo.skills.length
            };
        } else {
            this.skillsData = { data: [], total: 0 };
        }
    }

    public addSkillHandler(): void {
        if (!this.selectedLevelInfo) return;

        const newSkill: MD2MobSkill = {
            id: this.generateId(),
            mobLevelInfoId: this.selectedLevelInfo.id,
            type: MobSkillType.Combat,
            skillTarget: null,
            clawRoll: 0,
            skillRoll: 1,
            name: '',
            description: ''
        };

        this.openSkillEditor(newSkill, true);
    }

    public editSkillHandler(dataItem: MD2MobSkill): void {
        if (!this.selectedLevelInfo) return;

        // Create a copy of the skill for editing
        const skillCopy: MD2MobSkill = JSON.parse(JSON.stringify(dataItem));
        this.openSkillEditor(skillCopy, false);
    }

    private openSkillEditor(skill: MD2MobSkill, isNew: boolean): void {
        if (!this.selectedLevelInfo) return;

        const dialogRef = this.dialogService.open({
            title: isNew ? 'Add New Skill' : 'Edit Skill',
            content: MD2MobSkillEditorComponent,
            width: '80vw',
            height: 700
        });

        const editor = dialogRef.content.instance;
        editor.isAdding = isNew;
        editor.data = skill;
        editor.mobLevelInfoId = this.selectedLevelInfo.id;

        // Force model re-initialization after data is set
        setTimeout(() => {
            editor.initializeModel();
        }, 0);

        dialogRef.result.subscribe(result => {
            if (result && typeof result === 'object' && 'id' in result) {
                this.handleSkillSaved(result as MD2MobSkill, isNew);
            }
        });
    }

    private handleSkillSaved(result: MD2MobSkill, isNew: boolean): void {
        if (!this.selectedLevelInfo) return;

        if (isNew) {
            if (!this.selectedLevelInfo.skills) {
                this.selectedLevelInfo.skills = [];
            }
            this.selectedLevelInfo.skills.push(result);
        } else {
            const index = this.selectedLevelInfo.skills?.findIndex(s => s.id === result.id);
            if (index !== undefined && index !== -1 && this.selectedLevelInfo.skills) {
                this.selectedLevelInfo.skills[index] = result;
            }
        }
        this.loadSkills(this.selectedLevelInfo);
    }

    public saveSkillHandler({ dataItem, isNew }: any): void {
        // This method is no longer used but kept for backward compatibility
        // Skills are now edited via dialog
    }

    public removeSkillHandler({ dataItem }: { dataItem: MD2MobSkill }): void {
        if (!this.selectedLevelInfo) return;

        this.msgBoxService.showConfirmDeleteBox().pipe(first()).subscribe(answer => {
            if (answer === true) {
                this.isLoading = true;
                this.mobSkillService.delete(dataItem.id).pipe(first()).subscribe(result => {
                    if (this.selectedLevelInfo.skills) {
                        const index = this.selectedLevelInfo.skills.findIndex(s => s.id === dataItem.id);
                        if (index !== -1) {
                            this.selectedLevelInfo.skills.splice(index, 1);
                        }
                        this.loadSkills(this.selectedLevelInfo);
                    }
                    this.isLoading = false;
                });
            }
        });
    }


    private generateId(): string {
        return 'skill_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    }

    private generateLevelId(): string {
        return 'level_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    }

    public getSkillTypeName(type: MobSkillType): string {
        return MobSkillType[type] || '';
    }

    public getSkillTargetName(target: MobSkillTarget | null): string {
        if (target === null) return 'None';
        return MobSkillTarget[target] || '';
    }

    public getMobTypeName(type: MobType): string {
        return MobType[type] || '';
    }

    public getGameBundleName(bundle: GameBundle): string {
        return GameBundle[bundle] || '';
    }

    public close(): void {
        this.dialog.close(true);
    }
}

