import { ENEMIES_CONFIG } from './enemiesConfig.js';
import { TOWERS_CONFIG } from './towerConfig.js';
import { TowerAnims } from './towerAnims.js';

export class TowerManager {

    constructor(scene) {
        this.scene = scene;
        this.lastFired = {}; // Track last fire time for each tower
        this.following = {};
        this.selectedTower = null;
        this.upgradeCost = null;

        this.towerAnims = new TowerAnims(scene);
    }

    createTower(type, x, y) {
        const posX = this.scene.gridToLocation(x);
        const posY = this.scene.gridToLocation(y);
        let towerBase;
        let tower;

        if (type === 'icbm') {
            towerBase = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart).setDepth(10);
            tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart+3).setDepth(11);
            tower.props = {
                'type': type,
                'level': 1
            }
        } else {
            towerBase = this.scene.add.sprite(posX, posY, 'towers', 7).setDepth(10);
            tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart).setDepth(11);
            tower.props = {
                'type': type,
                'level': 1
            }
        }

        tower.towerBase = towerBase;

        // Generate unique ID for enemy
        const uniqueId = Phaser.Math.Between(100000, 999999);
        tower.id = uniqueId;

        this.scene.towers.add(tower);
        tower.setInteractive();
        tower.on('pointerdown', () => {
            if (!this.selectedTower) {
                this.upgradeMenu(tower);  
            }  
        });

        // Draw range circle
        const config = TOWERS_CONFIG[type].level1;
        if (config) {
            const range = config.range;
            tower.showRange = this.scene.add.circle(posX, posY, range, 0x00ff00, 0);
        }
    }

    upgradeMenu(tower) {
        if (this.upgradeDetails) this.upgradeDetails.destroy();

        this.selectedTower = tower;
        const currentLevel = `level${tower.props.level}`;
        const nextLevel = currentLevel === 'level3' ? 'level3' : `level${tower.props.level + 1}`;

        this.upgradeDetails = this.scene.add.container().setDepth(18);

        const rangeCircle = this.scene.add.circle(tower.x, tower.y, TOWERS_CONFIG[tower.props.type][currentLevel].range, 0xc009900, 0.2)
            .setOrigin(0.5)
            .setDepth(5);
        this.upgradeDetails.add(rangeCircle);
        
        const centerToEdgeLine = this.scene.add.line(tower.x, tower.y, 0, 0, TOWERS_CONFIG[tower.props.type][currentLevel].range, 0, 0x00ff00)
            .setOrigin(0)
            .setDepth(6);
        this.upgradeDetails.add(centerToEdgeLine);

        this.scene.tweens.add({
            targets: centerToEdgeLine,
            angle: 360,
            duration: 8000,
            repeat: -1
        });

        const intUpgrade = this.scene.add.image(tower.x + 100, tower.y, 'intUpgrade')
            .setDepth(12)
            .setTint(0xAAAAAA)
            .setOrigin(0, 0.5);
        this.upgradeDetails.add(intUpgrade);

        this.upgradeCost = TOWERS_CONFIG[tower.props.type][nextLevel].cost;

        this.upgradeText = this.scene.add.text(tower.x + 175, tower.y - 75, `Upgrade: ${this.upgradeCost}`, {
            fontFamily: 'neuropol, arial',
            fontSize: '32px',
            fill: '#ffd900ff',
            stroke: '#c48f00ff',
            strokeThickness: 2,
            shadow: {
                offsetX: 5,
                offsetY: 5,
                color: '#000000',
                blur: 5,
                stroke: false,
                fill: true
            }
        }).setDepth(13).setInteractive();
        this.upgradeDetails.add(this.upgradeText);

        if (currentLevel !== 3) {
            const currentStats = TOWERS_CONFIG[tower.props.type][currentLevel];
            const nextStats = TOWERS_CONFIG[tower.props.type][nextLevel];
            const rangeText = `Range: +${nextStats.range - currentStats.range}\n`;
            const damageText = `Damage: +${nextStats.dmgHigh - currentStats.dmgHigh}`;
            const upgradesText = `${rangeText}${damageText}`;
            
            this.upgradeTextStats = this.scene.add.text(tower.x + 200, tower.y - 25, upgradesText, {
                fontFamily: 'neuropol, arial', fontSize: '20px', fill: '#00ff88ff', stroke: '#00c493ff', strokeThickness: 2,
                shadow: { offsetX: 2, offsetY: 2, color: '#000000', blur: 2, stroke: false, fill: true }
            }).setDepth(13).setInteractive();
            this.upgradeDetails.add(this.upgradeTextStats);
        }

        if (currentLevel === 'level3') {
            this.upgradeText.setText('Max Upgrade').disableInteractive();
        }

        this.upgradeCancelText = this.scene.add.text(tower.x + 175, tower.y + 25, `Cancel`, {
            fontFamily: 'neuropol, arial',
            fontSize: '32px',
            fill: '#ff0000ff',
            stroke: '#c40000ff',
            strokeThickness: 2,
            shadow: {
                offsetX: 5,
                offsetY: 5,
                color: '#000000',
                blur: 5,
                stroke: false,
                fill: true
            }
        }).setDepth(14).setInteractive();
        this.upgradeDetails.add(this.upgradeCancelText);

        this.upgradeCancelText.on('pointerdown', () => {
            this.closeUpgradeMenu();
        });

        this.upgradeText.on('pointerdown', () => {
            this.upgradeTower(tower);
        });

        if (this.scene.UIScene.interfaceManager.gold < TOWERS_CONFIG[tower.props.type][nextLevel].cost) {
            this.disableUpgrade(this.upgradeText);
        }
    }

    enableUpgrade(text) {
        text.setInteractive().setTint(0xFFFFFF);
    }

    disableUpgrade(text) {
        text.disableInteractive().setTint(0xAAAAAA);
    }

    isPointerOverTower(pointer) {
        let isOverTower = false;
        if (this.upgradeDetails.getBounds().contains(pointer.x, pointer.y)) {
            isOverTower = true;
        }
        return isOverTower;
    }

    closeUpgradeMenu() {
        if (this.upgradeDetails) {
            this.upgradeDetails.destroy();
            this.upgradeDetails = null;
        }        
        this.selectedTower = null;
    }

    upgradeTower(tower) {
        this.closeUpgradeMenu();
        if (tower.props.level === 3) return;
        tower.props.level++;
        const newLevel = `level${tower.props.level}`
        this.scene.sound.play('upgrade');
        if (tower.props.type === 'icbm') {
            tower.towerBase.setTexture('towers', 29+tower.props.level);
        } else {
            tower.setTexture('towers', TOWERS_CONFIG[tower.props.type][newLevel].sprite);
        }
        this.scene.UIScene.removeGold(TOWERS_CONFIG[tower.props.type][newLevel].cost);
    } 

    update(time, delta) {
        // Iterate through all towers
        this.scene.towers.children.iterate((tower) => {
            const towerX = tower.x;
            const towerY = tower.y;
            
            // Get tower config
            const type = tower.props.type;
            const level = 'level'+tower.props.level;
            const config = TOWERS_CONFIG[type][level];

            if (this.following.hasOwnProperty(tower.id)) {
                this.scene.enemies.children.iterate((enemy) => {
                    if (this.following[tower.id] === enemy.props.id
                        && type !== 'icbm') 
                        {
                            // Rotate tower to face the enemy
                            const angle = Phaser.Math.Angle.Between(towerX, towerY, enemy.x, enemy.y);
                            tower.rotation = angle;
                        }
                });
            }
            
            if (!config) return;

            const range = config.range;
            const rate = config.rate;
            
            // Check if enough time has passed since last fire
            if (this.lastFired[tower.id] === undefined || 
                time - this.lastFired[tower.id] >= rate) {
                
                // Check for enemies in range
                let enemiesInRange = [];
                this.scene.enemies.children.iterate((enemy) => {
                    const distanceTraveled = enemy.props.distanceTraveled;
                    const distance = Phaser.Math.Distance.Between(
                        towerX, towerY,
                        enemy.x, enemy.y
                    );
                    
                    if (distance <= range && enemy.props.health > 0) {
                        enemiesInRange.push(enemy);
                    }
                });
                
                // Fire if enemies are in range
                if (enemiesInRange.length > 0) {
                    
                    // Find enemy with greatest distance traveled
                    const furthestEnemy = enemiesInRange.reduce((max, current) => {
                        return current.props.distanceTraveled > max.props.distanceTraveled ? current : max;
                    });
                    
                    this.following[tower.id] = furthestEnemy.props.id;
                    const dmgType = TOWERS_CONFIG[tower.props.type].dmgType;
                    if (tower.props.type === 'icbm') {
                        this.icbmAttackTarget(tower, furthestEnemy);
                    } else {
                        if (dmgType === 'aoe') {
                            this.aoeAttackTarget(tower, furthestEnemy);
                        } else {
                            this.attackTarget(tower, furthestEnemy);
                        }
                    }
                    
                    this.lastFired[tower.id] = time;
                }
            }
        });

        if (this.upgradeDetails && this.upgradeCost <= this.scene.UIScene.interfaceManager.gold) {
            this.enableUpgrade(this.upgradeText);
        }
    }

    attackTarget(tower, enemy) {
        // Tower Properties
        const type = tower.props.type;
        const level = 'level'+tower.props.level;
        const config = TOWERS_CONFIG[type][level];
        const duration = TOWERS_CONFIG[type][level].duration;
        
        if (!config) return;

        const dmgLow = config.dmgLow;
        const dmgHigh = config.dmgHigh;

        const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y);
        tower.rotation = angle;

        if (type === 'gun') {
            const gunSound = this.scene.sound.add('gatling-gun');
            gunSound.play();
            
            const vid = tower.play(config.anim);
            this.scene.time.delayedCall(config.duration, () => {
                vid.stop();
                gunSound.stop();
            });
        }

        if (type === 'laser') {
            // Create laser beam effect
            const laserBeam = this.scene.add.graphics();
            laserBeam.lineStyle(3, 0x00ff00, 1); // 3px wide, bright green, full opacity
            
            // Draw line from tower to enemy
            const projDistance = 60;
            const projX = tower.x + Math.cos(angle) * projDistance;
            const projY = tower.y + Math.sin(angle) * projDistance;
            laserBeam.beginPath();
            laserBeam.moveTo(projX, projY);
            laserBeam.lineTo(enemy.x, enemy.y);
            laserBeam.strokePath();
            
            this.scene.sound.play('laser', { volume: .3 });
            
            // Fade out effect over duration
            this.scene.tweens.add({
                targets: laserBeam,
                alpha: 0,
                duration: config.duration,
                ease: 'Linear',
                onComplete: () => {
                    laserBeam.destroy();
                }
            });
            
            // Reset tower texture after duration
            let currentFrame = 40;
            if (tower.props.level === 2) currentFrame = 42;
            if (tower.props.level === 3) currentFrame = 44;
            tower.setTexture('towers', currentFrame+1);
            this.scene.time.delayedCall(config.duration, () => {
                tower.setTexture('towers', currentFrame);
            });
        }

        // Calculate damage (random between low and high)
        const damage = Phaser.Math.Between(dmgLow, dmgHigh);
        
        // Apply damage to enemy
        enemy.props.health -= damage;

        if (enemy.props.health > 0) {
            this.createHealthBar(enemy);
            if (type === 'gun') {
                const gunfire = this.scene.physics.add.sprite(enemy.x, enemy.y, 'ammo', 0);
                gunfire.play('gunfire');
                gunfire.setVelocity(enemy.body.velocity.x, enemy.body.velocity.y);
                this.scene.time.delayedCall(config.duration, () => {
                    gunfire.destroy();
                });
            }
        } else {
            this.destroyEnemy(enemy, tower);
        }
    }

    aoeAttackTarget(tower, enemy) {
        // Tower Properties
        const type = tower.props.type;
        const level = 'level'+tower.props.level;
        const config = TOWERS_CONFIG[type][level];
        const duration = TOWERS_CONFIG[type][level].duration;
        
        if (!config) return;

        const dmgLow = config.dmgLow;
        const dmgHigh = config.dmgHigh;

        const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y);
        tower.rotation = angle;

        if (type === 'cannon') {
            this.scene.sound.play('cannon');
            const projDistance = 50;
            const projX = tower.x + Math.cos(angle) * projDistance;
            const projY = tower.y + Math.sin(angle) * projDistance;
            const projectile = this.scene.add.sprite(projX, projY, 'ammo', 3);
            this.scene.tweens.add({
                targets: projectile,
                x: enemy.x,
                y: enemy.y,
                duration: 100,
                onComplete: () => {
                    projectile.setTexture('ammo', 4);
                    this.scene.time.delayedCall(200, () => {
                        projectile.destroy();
                    });
                }
            });
            tower.play(`${type}-${level}-fire`, { 'duration': duration });
        }

        if (type === 'flame') {
            const projDistance = 185;
            const projDistance2 = 220;
            const projX = tower.x + Math.cos(angle) * projDistance;
            const projY = tower.y + Math.sin(angle) * projDistance;
            const proj2X = tower.x + Math.cos(angle) * projDistance2;
            const proj2Y = tower.y + Math.sin(angle) * projDistance2;
            const projectile = this.scene.add.sprite(projX, projY, 'towers', 23).setScale(1.5).setAlpha(.5);
            projectile.rotation = angle;
            projectile.play(`flamethrower`);
            const flameSound = this.scene.sound.add('flamethrower');
            flameSound.play();
            this.scene.tweens.add({
                targets: projectile,
                x: proj2X,
                y: proj2Y,
                duration:1000,
                onComplete: () => {
                    projectile.destroy();
                    flameSound.stop();
                }
            });
            
        }

        // Calculate damage (random between low and high)
        const damage = Phaser.Math.Between(dmgLow, dmgHigh);

        // Get AOE distance
        const aoeDistance = config.aoe;

        // Apply damage to all enemies in range
        const enemiesInRange = this.scene.enemies.getChildren().filter(e => {
            return Phaser.Math.Distance.Between(e.x, e.y, enemy.x, enemy.y) <= aoeDistance;
        });

        enemiesInRange.forEach(targetEnemy => {
            targetEnemy.props.health -= damage;

            if (targetEnemy.props.health > 0) {
                this.createHealthBar(targetEnemy);
            } else {
                this.destroyEnemy(targetEnemy, tower);
            }
        });
    }

    icbmAttackTarget(tower, enemy) {
        // Tower Properties
        const type = tower.props.type;
        const level = 'level'+tower.props.level;
        const config = TOWERS_CONFIG[type][level];
        const duration = TOWERS_CONFIG[type][level].duration;
        
        if (!config) return;

        const dmgLow = config.dmgLow;
        const dmgHigh = config.dmgHigh;

        const fireMissle = this.scene.add.sprite(tower.x, tower.y, 'towers', 33).setDepth(12);
        tower.setVisible(false);

        this.scene.sound.play('rocket-launch');
        this.scene.tweens.add({
            targets: fireMissle,
            x: fireMissle.x,
            y: fireMissle.y - 1200,
            duration: 2000,
            ease: 'Cubic.easeIn',
            onComplete: () => {
                fireMissle.setFlipY(true);
                fireMissle.x = enemy.x;
                this.scene.tweens.add({
                    targets: fireMissle,
                    x: enemy.x,
                    y: enemy.y,
                    duration: 500,
                    ease: 'Cubic.easeIn',
                    onComplete: () => {
                        fireMissle.destroy();
                        tower.setVisible(true);
                        this.scene.sound.play('rocket-explosion', { volume: 1.5});
                        const damage = Phaser.Math.Between(dmgLow, dmgHigh);
                        const aoeDistance = config.aoe;
                        const enemiesInRange = this.scene.enemies.getChildren().filter(e => {
                            return Phaser.Math.Distance.Between(e.x, e.y, enemy.x, enemy.y) <= aoeDistance;
                        });
                        const explosion = this.scene.add.sprite(enemy.x, enemy.y, 'towers', 34).setDepth(12);
                        explosion.play('icbmExplosion', { volume: 1.5 });
                        this.scene.tweens.add({
                            targets:explosion,
                            duration: 1000,
                            scale: 3,
                            alpha: .2,
                            onComplete: () => {
                                explosion.destroy();
                            }
                        });
                        enemiesInRange.forEach(targetEnemy => {
                            targetEnemy.props.health -= damage;

                            if (targetEnemy.props.health > 0) {
                                this.createHealthBar(targetEnemy);
                            } else {
                                this.destroyEnemy(targetEnemy, tower);
                            }
                        });
                    }
                });
            }
        });
    }

    createHealthBar(enemy) {
        const barWidth = 30;
        const barHeight = 5;
        const barX = enemy.x - barWidth/2;
        const barY = enemy.y - enemy.displayHeight/2 - 10;
        const health = Math.max(enemy.props.health, 0);
        const fullHealth = ENEMIES_CONFIG[enemy.props.type].fullHealth;
        
        // Create health bar container
        const healthBar = this.scene.add.container(enemy.x, barY);
        
        // Background bar (red)
        const background = this.scene.add.rectangle(0, 0, barWidth, barHeight, 0xe83829);
        
        // Health fill (green)
        const healthFill = this.scene.add.rectangle(0, 0, barWidth, barHeight, 0x00ff00);
        
        // Position the fill relative to background
        if (health === 0) {
            healthFill.width = 0;
        } else {
            healthFill.width = (health / fullHealth) * barWidth;
        }

        healthBar.add([background, healthFill]);
        this.scene.physics.world.enable(healthBar);
        healthBar.body.setVelocity(enemy.body.velocity.x, enemy.body.velocity.y);

        this.scene.tweens.add({
            targets: healthBar,
            delay: 1000,
            alpha: 0,
            onComplete: () => {
                healthBar.destroy();
            } 
        });
    }

    destroyEnemy(enemy, tower) {
        const dieX = enemy.x;
        const dieY = enemy.y;
        const type = enemy.props.type;
        const sprite = enemy.texture.key;
        const firstFrame = enemy.texture.firstFrame;
        const velocX = enemy.body.velocity.x;
        const velocY = enemy.body.velocity.y;

        // Add some Gold
        const drop = Phaser.Math.Between(ENEMIES_CONFIG[type].dropLow, ENEMIES_CONFIG[type].dropHigh) * 5;

        // Show the Gold
        const cashDrop = this.scene.add.image(dieX, dieY, 'gold').setScale(0.5);
        const angle = Phaser.Math.Angle.Between(tower.x, tower.y, dieX, dieY);

        // Calculate end position (100px away from original position in the calculated direction)
        const endX = dieX + Math.cos(angle) * 50;
        const endY = dieY + Math.sin(angle) * 50;

        // Get coords of Gold Interface
        const cam = this.scene.cameras.main;
        
        // Animate the cash drop moving to the new position
        this.scene.sound.play('coinWoosh', { volume: 2 });
        this.scene.tweens.add({
            targets: cashDrop,
            x: endX,
            y: endY,
            duration: 500,
            ease: 'Bounce',
            onComplete: () => {
                cashDrop.postFX.addGlow();
                this.scene.tweens.add({
                    targets: cashDrop,
                    x: 1300 + cam.scrollX,
                    y: 100 + cam.scrollY,
                    alpha: 0,
                    duration: 500,
                    onComplete: () => {
                        this.scene.sound.play('coin');
                        cashDrop.destroy();
                        this.scene.UIScene.addGold(drop);
                        this.scene.UIScene.interfaceManager.updateTowerAvail();
                    }
                });
            }
        });
        
        enemy.destroy();
        
        const deadEnemy = this.scene.add.sprite(dieX, dieY, sprite, firstFrame);
        deadEnemy.play(`${type}-die`);
        
        this.scene.tweens.add({
            targets: deadEnemy,
            delay: 5000,
            duration: 2000,
            alpha: 0,
            onComplete: () => {
                deadEnemy.destroy();
            }
        });

        this.following[tower.id] = null;
    }

}