import { VehicleEntity } from '../../entities/vehicle.entity';
import { ActiveJob } from '../../features/job/job.interface';

export class VehicleWrapper {
    readonly handle: number; // FiveM server entity handle

    vehicleEntity?: VehicleEntity;
    job?: ActiveJob;
    dmvTest?: any;
    extraBitmap: number = 0;
    fuelLastPosition: Vector3 = { x: 0, y: 0, z: 0 } as Vector3;
    alarmTimer?: NodeJS.Timeout;
    keyInIgnition: boolean = false;
    engine: boolean = false;        // tracked via client→server sync event
    bodyHealth: number = 1000;      // synced from client
    engineHealth: number = 1000;    // synced from client
    dimension: number = 0;          // stored server-side
    mechanicOperation?: VehicleMechanicOperation;
    attachments?: VehicleAttachment[];
    labels?: VehicleLabel[];

    constructor(handle: number) {
        this.handle = handle;
    }

    // RageMP compat: vehicle.id maps to network ID (what clients use to identify the vehicle)
    get id(): number {
        return NetworkGetNetworkIdFromEntity(this.handle);
    }

    get model(): number {
        return GetEntityModel(this.handle);
    }

    get position(): Vector3 {
        const [x, y, z] = GetEntityCoords(this.handle);
        return { x, y, z } as Vector3;
    }

    set position(v: Vector3) {
        SetEntityCoords(this.handle, v.x, v.y, v.z, false, false, false, false);
    }

    get heading(): number {
        return GetEntityHeading(this.handle);
    }

    set heading(h: number) {
        SetEntityHeading(this.handle, h);
    }

    get numberPlate(): string {
        return GetVehicleNumberPlateText(this.handle);
    }

    set numberPlate(plate: string) {
        SetVehicleNumberPlateText(this.handle, plate);
    }

    destroy(): void {
        vehicleRegistry.remove(this.handle);
        DeleteEntity(this.handle);
    }

    getVehicleOccupants(): import('../player/player-registry').PlayerWrapper[] {
        const { playerRegistry } = require('../player/player-registry');
        return playerRegistry.toArray().filter((p: any) => {
            const ped = GetPlayerPed(String(p.id));
            return GetVehiclePedIsIn(ped, false) === this.handle;
        });
    }
}

export class VehicleRegistry {
    private vehicles: Map<number, VehicleWrapper> = new Map();

    create(model: string | number, position: Vector3, options?: {
        heading?: number;
        numberPlate?: string;
        dimension?: number;
        color?: [number, number];
    }): VehicleWrapper {
        const modelHash = typeof model === 'string' ? GetHashKey(model) : model;
        const heading = options?.heading ?? 0;

        const handle = CreateVehicle(
            modelHash,
            position.x, position.y, position.z,
            heading,
            true,  // isNetwork
            false, // netMissionEntity
        );

        if (options?.numberPlate) {
            SetVehicleNumberPlateText(handle, options.numberPlate);
        }

        if (options?.color) {
            SetVehicleColours(handle, options.color[0], options.color[1]);
        }

        const wrapper = new VehicleWrapper(handle);
        this.vehicles.set(handle, wrapper);
        return wrapper;
    }

    remove(handle: number): void {
        this.vehicles.delete(handle);
    }

    get(handle: number): VehicleWrapper | undefined {
        return this.vehicles.get(handle);
    }

    getByNetId(netId: number): VehicleWrapper | undefined {
        const handle = NetworkGetEntityFromNetworkId(netId);
        return this.vehicles.get(handle);
    }

    toArray(): VehicleWrapper[] {
        return [...this.vehicles.values()];
    }

    forEach(fn: (vehicle: VehicleWrapper) => void): void {
        this.vehicles.forEach(fn);
    }
}

export const vehicleRegistry = new VehicleRegistry();
