import * as THREE from 'three';
import { state } from '../state.js';
import { degToRad } from '../utils.js';

const FLIES_COUNT = 2;

// --- Configuration ---
const FLIGHT_HEIGHT_MIN = 0.5; // Min height for flying
const FLIGHT_HEIGHT_MAX = 2;//state.roomHeight * 0.9; // Max height for flying
const FLY_FLIGHT_SPEED_FACTOR = 0.01; // How quickly 't' increases per frame
const FLY_WAIT_BASE = 1000;
const FLY_LAND_CHANCE = 0.3;

export class FliesEffect {
    constructor(scene) {
        this.flies = [];
        this._setupFlies(scene);
    }

    _randomFlyTarget() {
        return new THREE.Vector3(
            (Math.random() - 0.5) * (state.roomSize - 1),
            FLIGHT_HEIGHT_MIN + Math.random() * (FLIGHT_HEIGHT_MAX - FLIGHT_HEIGHT_MIN),
            (Math.random() - 0.5) * (state.roomSize - 1)
        );
    }

    _createFlyMesh() {
        const flyGroup = new THREE.Group();
        const flyMaterial = new THREE.MeshPhongMaterial({ color: 0x111111, shininess: 50 });
        const bodyGeometry = new THREE.ConeGeometry(0.01, 0.02, 3);
        const body = new THREE.Mesh(bodyGeometry, flyMaterial);
        body.rotation.x = degToRad(90);
        body.castShadow = true;
        body.receiveShadow = true;
        flyGroup.add(body);

        flyGroup.userData = {
            state: 'flying',
            landTimer: 0,
            t: 0,
            speed: FLY_FLIGHT_SPEED_FACTOR + Math.random() * 0.01,
            curve: null,
            landCheckTimer: 0,
            oscillationTime: Math.random() * 100,
        };

        flyGroup.position.copy(this._randomFlyTarget());
        return flyGroup;
    }

    _createFlyCurve(fly, endPoint) {
        const startPoint = fly.position.clone();
        const midPoint = new THREE.Vector3().lerpVectors(startPoint, endPoint, 0.5);
        const offsetMagnitude = startPoint.distanceTo(endPoint) * 0.5;
        const offsetAngle = Math.random() * Math.PI * 2;

        const controlPoint = new THREE.Vector3(
            midPoint.x + Math.cos(offsetAngle) * offsetMagnitude * 0.5,
            midPoint.y + Math.random() * 0.5 + 0.5,
            midPoint.z + Math.sin(offsetAngle) * offsetMagnitude * 0.5
        );

        fly.userData.curve = new THREE.QuadraticBezierCurve3(startPoint, controlPoint, endPoint);
        fly.userData.t = 0;
        fly.userData.landCheckTimer = 50 + Math.random() * 50;
    }

    _setupFlies(scene) {
        for (let i = 0; i < FLIES_COUNT; i++) {
            const fly = this._createFlyMesh();
            scene.add(fly);
            this.flies.push(fly);
        }
    }

    update() {
        this.flies.forEach(fly => {
            const data = fly.userData;

            if (data.state === 'flying' || data.state === 'landing') {
                if (!data.curve) {
                    const newTargetPos = this._randomFlyTarget();
                    this._createFlyCurve(fly, newTargetPos);
                    data.t = 0;
                }

                data.t += data.speed;
                data.landCheckTimer--;

                if (data.t >= 1) {
                    if (data.state === 'landing') {
                        data.state = 'landed';
                        data.landTimer = FLY_WAIT_BASE + Math.random() * 1000;
                        data.t = 0;
                        return;
                    }

                    if (data.landCheckTimer <= 0 && Math.random() > FLY_LAND_CHANCE) {
                        state.raycaster.set(fly.position, new THREE.Vector3(0, -1, 0));
                        const intersects = state.raycaster.intersectObjects(state.landingSurfaces, false);

                        if (intersects.length > 0) {
                            const intersect = intersects[0];
                            data.state = 'landing';
                            let newTargetPos = new THREE.Vector3(
                                intersect.point.x,
                                intersect.point.y + 0.05,
                                intersect.point.z
                            );
                            this._createFlyCurve(fly, newTargetPos);
                            data.t = 0;
                        }
                    }

                    if (data.state !== 'landing') {
                        const newTargetPos = this._randomFlyTarget();
                        this._createFlyCurve(fly, newTargetPos);
                        data.t = 0;
                    }
                }

                fly.position.copy(data.curve.getPoint(Math.min(data.t, 1)));
                const tangent = data.curve.getTangent(Math.min(data.t, 1)).normalize();
                fly.rotation.y = Math.atan2(tangent.x, tangent.z);
                data.oscillationTime += 0.1;
                fly.position.y += Math.sin(data.oscillationTime * 4) * 0.01;

            } else if (data.state === 'landed') {
                data.landTimer--;
                if (data.landTimer <= 0) {
                    data.state = 'flying';
                    const newTargetPos = this._randomFlyTarget();
                    this._createFlyCurve(fly, newTargetPos);
                    data.t = 0;
                }
            }
        });
    }
}