// Cyberpunk building-facade barriers on screen edges + optional interior obstacles.
// Edge barriers blink in ~5s after zone start; explode when zone waves complete.

const EDGE_DEPTH = 3;
const INT_DEPTH  = 3;
const NEON_CYAN   = 0x00ffff;
const NEON_PINK   = 0xff00aa;
const NEON_YELLOW = 0xffee00;
const WALL_FILL   = 0x08080f;

const ACTIVATE_DELAY = 2000; // ms before edge barriers start blinking in
const BLINK_DURATION = 300;  // ms per half-blink (yoyo)
const BLINK_REPEATS  = 4;    // total blink cycles (×2 for yoyo = 2.4s of blinking)

// Edge segments — 3 per side
function buildEdgeSegments(W, H) {
  const T = 52;
  const segs = [];

  const topWidths = [Math.floor(W * 0.32), Math.floor(W * 0.36), W - Math.floor(W * 0.32) - Math.floor(W * 0.36)];
  let ox = 0;
  topWidths.forEach((w, i) => {
    segs.push({ dir: 'top',    x: ox + w / 2,    y: T / 2,      w, h: T, segIdx: i });
    ox += w;
  });
  ox = 0;
  topWidths.forEach((w, i) => {
    segs.push({ dir: 'bottom', x: ox + w / 2,    y: H - T / 2,  w, h: T, segIdx: i });
    ox += w;
  });

  const sideH = H - T * 2;
  const leftHeights = [Math.floor(sideH * 0.33), Math.floor(sideH * 0.34), sideH - Math.floor(sideH * 0.33) - Math.floor(sideH * 0.34)];
  let oy = T;
  leftHeights.forEach((h, i) => {
    segs.push({ dir: 'left',  x: T / 2,          y: oy + h / 2, w: T, h, segIdx: i });
    oy += h;
  });
  oy = T;
  leftHeights.forEach((h, i) => {
    segs.push({ dir: 'right', x: W - T / 2,       y: oy + h / 2, w: T, h, segIdx: i });
    oy += h;
  });

  return segs;
}

// Pool of interior obstacle rects (picked from by index)
function allInteriorRects(W, H) {
  const T = 52;
  const p = { x: T, y: T, w: W - T * 2, h: H - T * 2 };
  return [
    { x: p.x + p.w * 0.18, y: p.y + p.h * 0.20, w: 90,  h: 24 },
    { x: p.x + p.w * 0.72, y: p.y + p.h * 0.22, w: 100, h: 24 },
    { x: p.x + p.w * 0.50, y: p.y + p.h * 0.42, w: 24,  h: 90 },
    { x: p.x + p.w * 0.20, y: p.y + p.h * 0.68, w: 110, h: 24 },
    { x: p.x + p.w * 0.75, y: p.y + p.h * 0.70, w: 24,  h: 80 },
    { x: p.x + p.w * 0.45, y: p.y + p.h * 0.80, w: 80,  h: 24 },
  ];
}

const FLY_DIR = { top: [0, -1], bottom: [0, 1], left: [-1, 0], right: [1, 0] };

export class BarrierManager {
  /**
   * @param {Phaser.Scene} scene
   * @param {number} interiorCount - how many interior obstacles to create (0 = none)
   */
  constructor(scene, interiorCount = 0) {
    this.scene = scene;
    this._edgeSegments  = [];
    this._interiorSegs  = [];
    this._allRects      = [];   // all barrier rects for isPointBlocked
    this._edgeRects     = [];   // edge-only rects for isInsideEdgeBarrier
    this._glitchTimer   = null;
    this._glitchTargets = [];   // only contains visible/active gfx
    this._edgeActive    = false;

    this._init(interiorCount);
  }

  // ── Public API ─────────────────────────────────────────────────────────────

  /** All barrier physics (player + bullet blocking). */
  get staticGroup() { return this._staticGroup; }

  /** Interior-only physics (enemy collision — enemies spawn outside edge barriers). */
  get interiorStaticGroup() { return this._interiorStaticGroup; }

  /** True if (x,y) is inside any barrier rect. */
  isPointBlocked(x, y) {
    for (const r of this._allRects) {
      if (x >= r.x - r.w / 2 && x <= r.x + r.w / 2 &&
          y >= r.y - r.h / 2 && y <= r.y + r.h / 2) return true;
    }
    return false;
  }

  /** True if (x,y) is inside any edge barrier rect (for trap check). */
  isInsideEdgeBarrier(x, y) {
    for (const r of this._edgeRects) {
      if (x >= r.x - r.w / 2 && x <= r.x + r.w / 2 &&
          y >= r.y - r.h / 2 && y <= r.y + r.h / 2) return true;
    }
    return false;
  }

  /**
   * Destroy the interior barrier at (x,y) if one exists. Returns true if destroyed.
   * Used by BomberEnemy shards.
   */
  destroyInteriorBarrierAt(x, y) {
    for (let i = 0; i < this._interiorSegs.length; i++) {
      const seg = this._interiorSegs[i];
      const r = seg.rect;
      if (x >= r.x - r.w / 2 && x <= r.x + r.w / 2 &&
          y >= r.y - r.h / 2 && y <= r.y + r.h / 2) {

        // Visual: flash and shatter
        if (seg.gfx?.active) {
          this.scene.tweens.add({
            targets: seg.gfx,
            alpha: 0, scaleX: 1.8, scaleY: 1.8,
            duration: 250,
            onComplete: () => seg.gfx.destroy(),
          });
        }
        seg.bodyImg?.destroy();
        seg.bodyImg2?.destroy();

        this._interiorSegs.splice(i, 1);
        this._allRects = this._allRects.filter(
          rect => !(rect.x === r.x && rect.y === r.y),
        );
        this._glitchTargets = this._glitchTargets.filter(g => g !== seg.gfx);
        return true;
      }
    }
    return false;
  }

  /**
   * Animate edge barriers blinking in over ~5s, then enable their physics.
   * @param {Function} onTrapped - called if player is inside an edge barrier when it solidifies
   */
  activateEdgeBarriers(onTrapped) {
    // Edge barriers start invisible and with physics disabled
    this._edgeSegments.forEach(seg => {
      seg.gfx.setAlpha(0);
      if (seg.bodyImg?.body) seg.bodyImg.body.enable = false;
    });

    // Use a repeating time event to blink manually — more reliable on Graphics objects
    let blinksLeft = BLINK_REPEATS * 2; // each tick toggles on/off
    let visible = false;

    const blinkEvent = this.scene.time.addEvent({
      delay: BLINK_DURATION,
      startAt: ACTIVATE_DELAY,
      repeat: BLINK_REPEATS * 2 - 1,
      callback: () => {
        visible = !visible;
        const a = visible ? 1 : 0;
        this._edgeSegments.forEach(seg => { if (seg.gfx?.active) seg.gfx.setAlpha(a); });

        blinksLeft--;
        if (blinksLeft <= 0) {
          // Final state: fully solid
          this._edgeSegments.forEach(seg => {
            if (seg.gfx?.active) seg.gfx.setAlpha(1);
            if (seg.bodyImg?.body) seg.bodyImg.body.enable = true;
          });
          this._edgeActive = true;
          this._glitchTargets.push(...this._edgeSegments.map(s => s.gfx).filter(g => g?.active));
          if (onTrapped) onTrapped();
        }
      },
    });

    this._activateEvent = blinkEvent;
  }

  /**
   * Explode edge barriers with animation, then call cb when done.
   */
  explodeEdgeBarriers(cb) {
    const scene = this.scene;
    const W = scene.scale.width;
    const H = scene.scale.height;

    if (this._glitchTimer) { this._glitchTimer.remove(); this._glitchTimer = null; }

    // Disable physics immediately
    this._edgeSegments.forEach(seg => {
      if (seg.bodyImg) { seg.bodyImg.destroy(); seg.bodyImg = null; }
      seg.body = null;
    });

    // Camera shake + flash
    scene.cameras.main.shake(350, 0.014);
    const flash = scene.add.rectangle(W / 2, H / 2, W, H, 0xffffff).setDepth(80).setAlpha(0.55);
    scene.tweens.add({ targets: flash, alpha: 0, duration: 250, onComplete: () => flash.destroy() });

    let remaining = this._edgeSegments.length;
    const onSegDone = () => { if (--remaining === 0 && cb) cb(); };

    this._edgeSegments.forEach((seg, idx) => {
      if (!seg.gfx?.active) { onSegDone(); return; }
      const [dx, dy] = FLY_DIR[seg.dir];
      const flyDist  = seg.dir === 'top' || seg.dir === 'bottom' ? H * 0.7 : W * 0.7;
      const delay    = idx * 28 + Phaser.Math.Between(0, 40);

      scene.time.delayedCall(delay, () => {
        this._spawnDebris(seg);
        scene.tweens.add({
          targets: seg.gfx,
          x: seg.gfx.x + dx * flyDist,
          y: seg.gfx.y + dy * flyDist,
          alpha: 0,
          angle: Phaser.Math.Between(-25, 25),
          duration: 480,
          ease: 'Cubic.easeIn',
          onComplete: () => { seg.gfx.destroy(); onSegDone(); },
        });
      });
    });
  }

  destroy() {
    if (this._glitchTimer) this._glitchTimer.remove();
    if (this._activateEvent) this._activateEvent.remove();
    this._edgeSegments.forEach(s => s.gfx?.destroy());
    this._interiorSegs.forEach(s => s.gfx?.destroy());
    this._staticGroup?.destroy(true);
    this._interiorStaticGroup?.destroy(true);
  }

  // ── Init ───────────────────────────────────────────────────────────────────

  _init(interiorCount) {
    const scene = this.scene;
    const W = scene.scale.width;
    const H = scene.scale.height;

    if (!scene.textures.exists('_barrier_px')) {
      const pg = scene.make.graphics({ x: 0, y: 0, add: false });
      pg.fillStyle(0xffffff, 1);
      pg.fillRect(0, 0, 2, 2);
      pg.generateTexture('_barrier_px', 2, 2);
      pg.destroy();
    }

    this._staticGroup = scene.physics.add.staticGroup();
    this._interiorStaticGroup = scene.physics.add.staticGroup();

    buildEdgeSegments(W, H).forEach(def => {
      const gfx = scene.add.graphics().setDepth(EDGE_DEPTH);
      this._drawBarrier(gfx, def.w, def.h, def.dir, def.segIdx);
      gfx.x = def.x;
      gfx.y = def.y;

      const bodyImg = this._makeBody(this._staticGroup, def.x, def.y, def.w, def.h);

      this._edgeSegments.push({ gfx, bodyImg, body: bodyImg.body, dir: def.dir, rect: { x: def.x, y: def.y, w: def.w, h: def.h } });
      this._allRects.push({ x: def.x, y: def.y, w: def.w, h: def.h });
      this._edgeRects.push({ x: def.x, y: def.y, w: def.w, h: def.h });
    });

    const intPool = allInteriorRects(W, H);
    for (let i = 0; i < Math.min(interiorCount, intPool.length); i++) {
      const def = intPool[i];
      const gfx = scene.add.graphics().setDepth(INT_DEPTH);
      this._drawBarrier(gfx, def.w, def.h, null, 0);
      gfx.x = def.x;
      gfx.y = def.y;

      const bodyImg  = this._makeBody(this._staticGroup, def.x, def.y, def.w, def.h);
      const bodyImg2 = this._makeBody(this._interiorStaticGroup, def.x, def.y, def.w, def.h);

      this._interiorSegs.push({ gfx, bodyImg, bodyImg2, rect: def });
      this._allRects.push({ x: def.x, y: def.y, w: def.w, h: def.h });
      this._glitchTargets.push(gfx);
    }

    this._startGlitch();
  }

  _makeBody(group, cx, cy, w, h) {
    const img = group.create(cx, cy, '_barrier_px');
    img.setVisible(false);
    img.setDisplaySize(w, h);
    img.refreshBody();
    return img;
  }

  // ── Drawing ────────────────────────────────────────────────────────────────

  _drawBarrier(g, w, h, dir, segIdx) {
    const hw = w / 2, hh = h / 2;

    g.fillStyle(WALL_FILL, 1);
    g.fillRect(-hw, -hh, w, h);

    g.lineStyle(2, NEON_CYAN, 0.85);
    g.strokeRect(-hw, -hh, w, h);

    const INS = 5;
    g.lineStyle(1, NEON_CYAN, 0.35);
    g.strokeRect(-hw + INS, -hh + INS, w - INS * 2, h - INS * 2);

    if (dir) {
      this._drawFacade(g, w, h, dir, segIdx);
    } else {
      this._drawInteriorDetail(g, w, h);
    }
  }

  _drawFacade(g, w, h, dir, segIdx) {
    const hw = w / 2, hh = h / 2;
    const isHoriz = dir === 'top' || dir === 'bottom';

    g.fillStyle(NEON_PINK, 0.18);
    if (isHoriz) g.fillRect(-hw + 8, -3, w - 16, 6);
    else         g.fillRect(-3, -hh + 8, 6, h - 16);

    g.fillStyle(NEON_YELLOW, 0.25);
    const WIN_W = isHoriz ? 14 : 10;
    const WIN_H = isHoriz ? 10 : 14;
    const cols  = isHoriz ? 4 + segIdx : 2;
    const rows  = isHoriz ? 2          : 3 + segIdx;
    const xGap  = (w - 20) / (cols + 1);
    const yGap  = (h - 10) / (rows + 1);
    for (let r = 1; r <= rows; r++) {
      for (let c = 1; c <= cols; c++) {
        g.fillRect(-hw + 10 + xGap * c - WIN_W / 2, -hh + 5 + yGap * r - WIN_H / 2, WIN_W, WIN_H);
      }
    }

    const L = 10;
    g.lineStyle(2, NEON_PINK, 0.8);
    [[-hw, -hh], [hw, -hh], [-hw, hh], [hw, hh]].forEach(([cx, cy]) => {
      const sx = cx < 0 ? 1 : -1;
      const sy = cy < 0 ? 1 : -1;
      g.beginPath();
      g.moveTo(cx + sx * L, cy);
      g.lineTo(cx, cy);
      g.lineTo(cx, cy + sy * L);
      g.strokePath();
    });
  }

  _drawInteriorDetail(g, w, h) {
    const hw = w / 2, hh = h / 2;
    const step = Math.min(w, h) > 50 ? 16 : 12;
    g.lineStyle(1, NEON_PINK, 0.3);
    for (let i = -Math.max(w, h); i < Math.max(w, h); i += step) {
      g.beginPath();
      g.moveTo(Math.max(-hw, i - hh), Math.min(hh, i + hw));
      g.lineTo(Math.min(hw, i + hh),  Math.max(-hh, i - hw));
      g.strokePath();
    }
    g.fillStyle(NEON_CYAN, 0.6);
    g.fillRect(-3, -3, 6, 6);
  }

  // ── Glitch ─────────────────────────────────────────────────────────────────

  _startGlitch() {
    this._glitchTimer = this.scene.time.addEvent({
      delay: 800,
      loop: true,
      callback: () => {
        if (!this._glitchTargets.length || Math.random() > 0.45) return;
        const target = Phaser.Utils.Array.GetRandom(this._glitchTargets);
        if (!target?.active) return;
        this.scene.tweens.add({
          targets: target,
          alpha: { from: 1, to: 0.2 },
          duration: 60,
          yoyo: true,
          repeat: Phaser.Math.Between(1, 3),
        });
      },
    });
  }

  // ── Explosion debris ────────────────────────────────────────────────────────

  _spawnDebris({ rect, dir }) {
    const scene = this.scene;
    const colors = [NEON_CYAN, NEON_PINK, NEON_YELLOW];
    const [dx, dy] = FLY_DIR[dir];

    for (let i = 0; i < Phaser.Math.Between(6, 12); i++) {
      const piece = scene.add.rectangle(
        rect.x + Phaser.Math.Between(-rect.w / 2, rect.w / 2),
        rect.y + Phaser.Math.Between(-rect.h / 2, rect.h / 2),
        Phaser.Math.Between(4, 18),
        Phaser.Math.Between(4, 14),
        Phaser.Utils.Array.GetRandom(colors),
      ).setDepth(60).setAlpha(0.9);

      const speed = Phaser.Math.Between(80, 300);
      scene.tweens.add({
        targets: piece,
        x: piece.x + dx * speed + Phaser.Math.Between(-120, 120),
        y: piece.y + dy * speed + Phaser.Math.Between(-120, 120),
        alpha: 0, scaleX: 0.1, scaleY: 0.1,
        angle: Phaser.Math.Between(-180, 180),
        duration: Phaser.Math.Between(350, 700),
        ease: 'Cubic.easeOut',
        onComplete: () => piece.destroy(),
      });
    }
  }
}
