export type SkillType = 'active' | 'passive';

export interface SkillDef {
  id: string;
  name: string;
  type: SkillType;
  maxLevel: number;
  describe(level: number): string;
}

export interface SkillOffer {
  id: string;
  nextLevel: number;
}

export const HOTBAR_SKILLS = ['chainlightning', 'teleport', 'trap', 'gascloud'];

export const SKILLS: SkillDef[] = [
  {
    id: 'fireball',
    name: 'Feuerball',
    type: 'active',
    maxLevel: 5,
    describe: (l) => l === 1
      ? 'Schießt einen Feuerball (85 DMG, 5.5s CD)'
      : `${fireballDamage(l)} DMG · ${fireballCooldown(l)}s CD${fireballRadius(l) > 8 ? ' · größere Explosion' : ''}`,
  },
  {
    id: 'teleport',
    name: 'Teleport',
    type: 'active',
    maxLevel: 3,
    describe: (l) => `Teleport zum Zielpunkt (${teleportCooldown(l)}s CD)`,
  },
  {
    id: 'chainlightning',
    name: 'Kettenblitz',
    type: 'active',
    maxLevel: 5,
    describe: (l) => `Blitz springt auf ${lightningJumps(l)} Gegner (${lightningDamage(l)} DMG, ${lightningCooldown(l)}s CD, ${lightningJumpRange(l)} m Sprungweite)`,
  },
  {
    id: 'swordRange',
    name: 'Reichweite',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => `Schwert-Reichweite auf ${swordRange(l).toFixed(1)}`,
  },
  {
    id: 'swordDamage',
    name: 'Schärfe',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => `Schwert-Schaden ${swordDamage(l)}`,
  },
  {
    id: 'regen',
    name: 'Regeneration',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => `Heilt ${(1.5 * l).toFixed(1)} HP/s`,
  },
  {
    id: 'lifesteal',
    name: 'HP-Absorption',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => `${5 * l}% des Schadens heilt dich`,
  },
  {
    id: 'shield',
    name: 'Schild',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => `Absorbiert ${25 * l} Schaden, lädt nach 8s neu auf`,
  },
  {
    id: 'maxHp',
    name: 'Vitalität',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => `+25 max. HP (${100 + 25 * l}), heilt voll`,
  },
  {
    id: 'thorns',
    name: 'Dornen',
    type: 'passive',
    maxLevel: 3,
    describe: (l) => `Gegner erleiden ${15 * l} DPS bei Kontakt`,
  },
  {
    id: 'speed',
    name: 'Flinke Füße',
    type: 'passive',
    maxLevel: 3,
    describe: (l) => `Bewegungsgeschwindigkeit ${(7.5 + l).toFixed(1)}`,
  },
  {
    id: 'aura',
    name: 'Aura',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => l === 1
      ? 'Schädigt Gegner um dich herum und stößt sie zurück'
      : `Radius ${auraRadius(l).toFixed(1)} · ${auraDamage(l)} DMG/0,5s`,
  },
  {
    id: 'boomerang',
    name: 'Bumerang',
    type: 'passive',
    maxLevel: 5,
    describe: (l) => `${boomerangCount(l)}× kreisender Bumerang · ${boomerangDamage(l)} DMG`,
  },
  {
    id: 'trap',
    name: 'Falle',
    type: 'active',
    maxLevel: 5,
    describe: (l) => `Hält Gegner ${trapHold(l)}s fest (${trapDamage(l)} DMG, ${trapCooldown(l)}s CD)`,
  },
  {
    id: 'gascloud',
    name: 'Gaswolke',
    type: 'active',
    maxLevel: 5,
    describe: (l) => `${gasDamage(l)} DPS · Radius ${gasRadius(l)} · ${gasCooldown(l)}s CD`,
  },
];

export function getSkill(id: string): SkillDef {
  return SKILLS.find((s) => s.id === id)!;
}

export function fireballDamage(level: number): number {
  return [85, 125, 165, 205, 245][Math.min(level, 5) - 1] ?? 85;
}
export function fireballCooldown(level: number): number {
  return [5.5, 5, 4.5, 4, 3.5][Math.min(level, 5) - 1] ?? 5.5;
}
export function fireballRadius(level: number): number {
  return [7, 7, 9, 9, 11][Math.min(level, 5) - 1] ?? 7;
}
export function teleportCooldown(level: number): number {
  return [50, 35, 20][Math.min(level, 3) - 1] ?? 50;
}
export function lightningDamage(level: number): number {
  return [55, 75, 95, 115, 135][Math.min(level, 5) - 1] ?? 55;
}
export function lightningJumps(level: number): number {
  return [2, 3, 4, 5, 6][Math.min(level, 5) - 1] ?? 2;
}
export function lightningJumpRange(level: number): number {
  return [9, 10, 11, 12, 13][Math.min(level, 5) - 1] ?? 9;
}
export function lightningCooldown(level: number): number {
  return [8, 7, 6, 5, 4][Math.min(level, 5) - 1] ?? 8;
}
export function swordRange(level: number): number {
  return 2.2 + 0.6 * level;
}
export function swordDamage(level: number): number {
  return 50 + 25 * level;
}
export function auraRadius(level: number): number {
  return [3, 3.4, 3.8, 4.2, 4.6][Math.min(level, 5) - 1] ?? 3;
}
export function auraDamage(level: number): number {
  return [8, 12, 16, 20, 26][Math.min(level, 5) - 1] ?? 8;
}
export function auraPush(level: number): number {
  return [0.8, 0.9, 1.0, 1.1, 1.2][Math.min(level, 5) - 1] ?? 0.8;
}
export function boomerangDamage(level: number): number {
  return [12, 18, 24, 32, 40][Math.min(level, 5) - 1] ?? 12;
}
export function boomerangCount(level: number): number {
  return [1, 1, 2, 2, 3][Math.min(level, 5) - 1] ?? 1;
}
export function trapDamage(level: number): number {
  return [35, 45, 55, 65, 80][Math.min(level, 5) - 1] ?? 35;
}
export function trapHold(level: number): number {
  return [1.5, 1.75, 2, 2.25, 2.5][Math.min(level, 5) - 1] ?? 1.5;
}
export function trapMax(level: number): number {
  return [3, 3, 4, 4, 5][Math.min(level, 5) - 1] ?? 3;
}
export function trapCooldown(level: number): number {
  return [8, 7, 6.5, 6, 5][Math.min(level, 5) - 1] ?? 8;
}
export function gasDamage(level: number): number {
  return [12, 16, 20, 24, 30][Math.min(level, 5) - 1] ?? 12;
}
export function gasRadius(level: number): number {
  return [3.5, 4, 4.5, 5, 5.5][Math.min(level, 5) - 1] ?? 3.5;
}
export function gasDuration(level: number): number {
  return [4, 4.5, 5, 5.5, 6][Math.min(level, 5) - 1] ?? 4;
}
export function gasCooldown(level: number): number {
  return [10, 9, 8.5, 8, 7][Math.min(level, 5) - 1] ?? 10;
}

function mulberry32(seed: number): () => number {
  let a = seed >>> 0;
  return function () {
    a |= 0;
    a = (a + 0x6D2B79F5) | 0;
    let t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

export class SkillSystem {
  seed: number;
  level = 0;
  xp = 0;
  private rng: () => number;
  levels: Record<string, number> = {};

  constructor(seed: number) {
    this.seed = seed >>> 0;
    this.rng = mulberry32(this.seed);
  }

  getLevel(id: string): number {
    return this.levels[id] ?? 0;
  }

  xpNeeded(): number {
    return 30 + this.level * 15;
  }

  xpProgress(): number {
    return this.xp / this.xpNeeded();
  }

  addXp(amount: number): number {
    this.xp += amount;
    if (!this.hasAnyUpgradeLeft()) return 0;
    let leveled = 0;
    while (this.xp >= this.xpNeeded()) {
      this.xp -= this.xpNeeded();
      this.level++;
      leveled++;
    }
    return leveled;
  }

  hasPendingLevelUp(): boolean {
    return this.hasAnyUpgradeLeft() && this.xp >= this.xpNeeded();
  }

  hasAnyUpgradeLeft(): boolean {
    return SKILLS.some((s) => (this.levels[s.id] ?? 0) < s.maxLevel);
  }

  apply(skillId: string) {
    this.levels[skillId] = (this.levels[skillId] ?? 0) + 1;
  }

  rollOffers(): SkillOffer[] {
    const newPool = SKILLS.filter((s) => !this.levels[s.id]);
    const upgradePool = SKILLS.filter((s) => {
      const l = this.levels[s.id] ?? 0;
      return l > 0 && l < s.maxLevel;
    });

    const ownedCount = Object.keys(this.levels).length;
    const offers: SkillOffer[] = [];
    while (offers.length < 3 && newPool.length + upgradePool.length > 0) {
      let pool: SkillDef[];
      if (newPool.length && upgradePool.length) {
        const newBias = ownedCount < 4 ? 0.65 : 0.25;
        pool = this.rng() < newBias ? newPool : upgradePool;
      } else {
        pool = newPool.length ? newPool : upgradePool;
      }
      const idx = Math.floor(this.rng() * pool.length);
      const skill = pool[idx];
      pool.splice(idx, 1);
      offers.push({ id: skill.id, nextLevel: (this.levels[skill.id] ?? 0) + 1 });
    }
    return offers;
  }
}
