import * as THREE from 'three';

export class Police {
    constructor(game) {
        this.game = game;
        this.officers = [];
        this.warningCooldown = 0;
    }

    spawnPatrols() {
        this.officers = [];

        // Два патруля по дорогам
        const routes = [
            // Патруль 1: вдоль главной E-W дороги (тротуар z=9)
            [
                { x: -50, z: 9 },
                { x: -10, z: 9 },
                { x: 25, z: 9 },
                { x: 50, z: 9 },
                { x: 25, z: 9 },
                { x: -10, z: 9 },
            ],
            // Патруль 2: вдоль N-S (тротуар x=9) и южной
            [
                { x: 9, z: -35 },
                { x: 9, z: -5 },
                { x: 9, z: 15 },
                { x: 9, z: 40 },
                { x: 9, z: 15 },
                { x: 9, z: -5 },
            ],
        ];

        routes.forEach((waypoints, i) => {
            const officer = {
                position: new THREE.Vector3(waypoints[0].x, 0, waypoints[0].z),
                waypoints,
                currentWP: 0,
                state: 'patrol', // patrol, warning, chase, fine
                speed: 3,
                chaseSpeed: 5.5,
                detectRange: 20,
                warnTimer: 0,
                mesh: null,
                warningGiven: false,
            };

            officer.mesh = this.createOfficerMesh();
            officer.mesh.position.copy(officer.position);
            this.game.scene.add(officer.mesh);
            this.officers.push(officer);
        });
    }

    createOfficerMesh() {
        const group = new THREE.Group();

        // Тело (синяя форма)
        const bodyMat = new THREE.MeshStandardMaterial({ color: 0x1a3366 });
        const body = new THREE.Mesh(new THREE.CylinderGeometry(0.32, 0.37, 1.15, 8), bodyMat);
        body.position.y = 0.85;
        body.castShadow = true;
        group.add(body);

        // Голова
        const head = new THREE.Mesh(
            new THREE.SphereGeometry(0.23, 8, 6),
            new THREE.MeshStandardMaterial({ color: 0xc49070 })
        );
        head.position.y = 1.57;
        group.add(head);

        // Фуражка
        const capBrim = new THREE.Mesh(
            new THREE.CylinderGeometry(0.28, 0.28, 0.04, 8),
            new THREE.MeshStandardMaterial({ color: 0x1a2244 })
        );
        capBrim.position.y = 1.72;
        group.add(capBrim);

        const capTop = new THREE.Mesh(
            new THREE.CylinderGeometry(0.18, 0.22, 0.14, 8),
            new THREE.MeshStandardMaterial({ color: 0x1a2244 })
        );
        capTop.position.y = 1.80;
        group.add(capTop);

        // Ноги
        const legMat = new THREE.MeshStandardMaterial({ color: 0x1a2244 });
        [-0.12, 0.12].forEach(side => {
            const leg = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.08, 0.5, 6), legMat);
            leg.position.set(side, 0.25, 0);
            leg.castShadow = true;
            group.add(leg);
        });

        return group;
    }

    update(dt) {
        if (this.warningCooldown > 0) this.warningCooldown -= dt;

        // Ночью полиция не патрулирует
        const hour = this.game.gameTime / 60;
        const isNightTime = hour < 6 || hour > 22;

        this.officers.forEach(officer => {
            if (isNightTime) {
                // Уходят за карту ночью
                if (officer.mesh) officer.mesh.visible = false;
                officer.state = 'patrol';
                return;
            }
            if (officer.mesh) officer.mesh.visible = true;

            switch (officer.state) {
                case 'patrol':
                    this.updatePatrol(officer, dt);
                    this.checkViolation(officer);
                    break;
                case 'warning':
                    this.updateWarning(officer, dt);
                    break;
                case 'chase':
                    this.updateChase(officer, dt);
                    break;
                case 'fine':
                    // Dialog in progress, do nothing
                    break;
            }
        });
    }

    updatePatrol(officer, dt) {
        const wp = officer.waypoints[officer.currentWP];
        const target = new THREE.Vector3(wp.x, 0, wp.z);
        const dir = target.clone().sub(officer.position);
        const dist = dir.length();

        if (dist < 1) {
            officer.currentWP = (officer.currentWP + 1) % officer.waypoints.length;
        } else {
            dir.normalize();
            officer.position.add(dir.multiplyScalar(officer.speed * dt));
            officer.mesh.position.copy(officer.position);
            officer.mesh.rotation.y = Math.atan2(dir.x, dir.z);
        }
    }

    checkViolation(officer) {
        const playerPos = this.game.player.position;
        const dist = officer.position.distanceTo(playerPos);

        const detectRange = this.getDetectRange();
        if (dist > detectRange) return;

        // Попрошайничество в зоне видимости
        if (this.game.player.isBegging) {
            officer.state = 'warning';
            officer.warnTimer = 3;
            officer.warningGiven = true;
            this.game.notify('Полиция: "Прекратите попрошайничать!"', 'bad');
            return;
        }

        // Очень низкая репутация
        if (this.game.reputation.value < -30 && dist < 15) {
            officer.state = 'chase';
            this.game.notify('Полиция: "Стоять! Проверка документов!"', 'bad');
        }
    }

    updateWarning(officer, dt) {
        officer.warnTimer -= dt;

        // Смотреть на игрока
        const dir = this.game.player.position.clone().sub(officer.position);
        officer.mesh.rotation.y = Math.atan2(dir.x, dir.z);

        if (officer.warnTimer <= 0) {
            // Если всё ещё попрошайничает — переход в chase
            if (this.game.player.isBegging) {
                officer.state = 'chase';
                this.game.notify('Полиция: "Я предупреждал!"', 'bad');
            } else {
                officer.state = 'patrol';
                officer.warningGiven = false;
            }
        }
    }

    updateChase(officer, dt) {
        const playerPos = this.game.player.position;
        const dir = playerPos.clone().sub(officer.position);
        const dist = dir.length();

        if (dist < 2) {
            // Поймал
            officer.state = 'fine';
            this.showFineDialog(officer);
            return;
        }

        if (dist > 50) {
            // Потерял
            officer.state = 'patrol';
            this.game.notify('Полиция потеряла вас из виду.');
            return;
        }

        dir.normalize();
        officer.position.add(dir.multiplyScalar(officer.chaseSpeed * dt));
        officer.mesh.position.copy(officer.position);
        officer.mesh.rotation.y = Math.atan2(dir.x, dir.z);
    }

    showFineDialog(officer) {
        this.game.player.stopBegging();
        this.game.player.stopBusking();

        const fineAmount = 50 + Math.floor(Math.random() * 50);

        this.game.ui.showDialog('Полицейский', `Нарушение общественного порядка. Штраф ${fineAmount} ₽.`, [
            `Заплатить штраф (${fineAmount} ₽)`,
            'Нет денег...'
        ], (index) => {
            if (index === 0) {
                if (this.game.player.stats.money >= fineAmount) {
                    this.game.player.stats.money -= fineAmount;
                    this.game.notify(`Оплачен штраф ${fineAmount} ₽.`, 'bad');
                } else {
                    this.game.notify('Не хватает денег. Конфискация предметов.', 'bad');
                    this.confiscateItem();
                }
            } else {
                this.game.notify('Конфискация предметов.', 'bad');
                this.confiscateItem();
            }

            this.game.reputation.change(-10);
            officer.state = 'patrol';
            this.game.ui.hideDialog();
        });
    }

    confiscateItem() {
        const inv = this.game.inventory;
        const items = Object.keys(inv.items).filter(k => inv.items[k] > 0);
        if (items.length > 0) {
            const item = items[Math.floor(Math.random() * items.length)];
            const name = inv.itemData[item]?.name || item;
            inv.removeItem(item, 1);
            this.game.notify(`Конфисковано: ${name}`, 'bad');
        }
    }

    getDetectRange() {
        const rep = this.game.reputation.value;
        if (rep >= 50) return 0; // Уважаемых не трогают
        if (rep >= 20) return 10;
        if (rep <= -50) return 25;
        if (rep <= -20) return 22;
        return 20;
    }

    reset() {
        this.officers.forEach(o => {
            if (o.mesh) this.game.scene.remove(o.mesh);
        });
        this.officers = [];
        this.warningCooldown = 0;
    }
}
