/**
 * Global type augmentations for the FiveM port.
 *
 * PlayerMp / VehicleMp etc. are aliased to our wrapper classes so that
 * existing feature code that references these types compiles without changes.
 */

import { PlayerWrapper } from './player/player-registry';
import { VehicleWrapper } from './vehicle/vehicle-wrapper';
import { CharacterEntity } from '../entities/character.entity';
import { AccountDto } from '../features/sw-rp-api/index';
import { SessionEntity } from '../entities/session.entity';

// Re-export wrappers under the RageMP type names so existing code just works
declare global {
    type PlayerMp = PlayerWrapper;
    type VehicleMp = VehicleWrapper;

    // Logged-in subtype (mirrors original)
    interface PlayerMpLoggedIn extends PlayerWrapper {
        character: CharacterEntity;
        account: AccountDto;
        session: SessionEntity;
    }

    // ObjectMp — FiveM server-side objects (peds, props); stub for now
    interface ObjectMp {
        id: number;
        handle: number;
        setVariable(key: string, value: any): void;
        getVariable<T = any>(key: string): T;
        furnitureOfProperty?: import('../entities/property.entity').PropertyEntity;
        inventory?: import('../entities/inventory.entity').InventoryEntity;
        itemLock: boolean;
        bluetoothConnectedTo?: PlayerWrapper;
        notifyStreaming?: boolean;
        createdBy?: string;
        createdOn?: string;
        doorLocked?: boolean;
        doorAjar?: boolean;
    }

    // Vector3 — matches RageMP's Vector3 shape
    interface Vector3 {
        x: number;
        y: number;
        z: number;
    }

    type Array4d = [number, number, number, number];

    // ColshapeMp stub
    interface ColshapeMp {
        vehicleDealership?: import('../entities/vehicle-dealership.entity').VehicleDealershipEntity;
        property?: import('../entities/property.entity').PropertyEntity;
        forProperty?: import('../entities/property.entity').PropertyEntity;
    }

    // PedMp stub
    interface PedMp {
        entity?: import('../entities/corpse.entity').CorpseEntity;
        handle: number;
    }

    interface EntityPermission {
        id: number;
        name: string;
        description: string;
        repositoryId: number;
        repositoryType: string;
    }

    // VehicleMpDatabase — vehicle with a guaranteed DB entity
    interface VehicleMpDatabase extends VehicleWrapper {
        vehicleEntity: import('../entities/vehicle.entity').VehicleEntity;
    }

    // ---- PlayerState -------------------------------------------------------
    // Copied verbatim from the original types.d.ts — nothing in here references
    // RageMP APIs directly so it's portable as-is.
    interface PlayerState {
        diedToFall?: boolean;
        reconnecting: boolean;
        lastPlayerDeath?: number;
        isOnPhone?: boolean;
        phoneAnim: {
            currentStatus: 'out' | 'call' | 'text';
            lastDict?: string;
            lastAnim?: string;
        };
        companyChat?: import('../entities/company.entity').CompanyEntity;
        interviewing?: PlayerWrapper;
        interviewedBy?: PlayerWrapper;
        shift?: { companyId: number; startTime: Date; paycheckBuffer: number; paydays: number };
        currentHairSlot: number;
        metroDuty?: string;
        sentenceId?: number | null;
        prisoned?: Date | null;
        jailed?: Date | null;
        jailedFor?: number | null;
        jailCellId?: number | null;
        paroled?: Date | null;
        segregated?: Date | null;
        segregatedFor?: number | null;
        segregatedUntil?: Date | null;
        sentencedUntil?: Date | null;
        remanded?: Date | null;
        paroleEligible?: number | null;
        noticeServed?: { release: boolean; parole: boolean };
        togLevel: boolean;
        togXChat?: boolean;
        phoneCall?: {
            id: number; number: string; party?: PlayerMpLoggedIn; objectParty?: ObjectMp;
            automatedParty?: string; outgoing: boolean; status?: string; start?: number;
            active: boolean; dialTimeout?: NodeJS.Timeout; timeoutTimeout?: NodeJS.Timeout;
            clearingTimeout?: NodeJS.Timeout; loudSpeaker?: boolean; muted?: boolean;
        };
        posResetUnlock: number;
        propertyInteractionUnlock: number;
        vehicleInteraction: boolean;
        destinationMarker?: Vector3;
        emergencyDispatch?: any;
        nonEmergencyDispatch?: any;
        menuCompany?: import('../entities/company.entity').CompanyEntity;
        phoneCaller?: PlayerMpLoggedIn;
        phoneDialTimeout?: NodeJS.Timeout;
        clothing: import('../features/clothing/index').StatefulClothingItem[];
        characterLoadedAt?: number;
        inProperty?: import('../entities/property.entity').PropertyEntity;
        inPropertyArea?: any;
        mechanicOperation?: VehicleMechanicOperation;
        atPropertyCol?: import('../entities/property.entity').PropertyEntity;
        atBackdoorCol?: import('../entities/property.entity').PropertyEntity;
        jailTimer?: NodeJS.Timeout;
        insideJail?: import('../entities/jail-cell.entity').JailCellEntity;
        jailReleaseTime?: number;
        paymentMutex: import('async-mutex').MutexInterface;
        mission?: import('../features/mission/mission.model').Mission;
        navDestCallback?: (...args: any[]) => void;
        adjustingWeapon?: number;
        objectEditor?: any;
        objectSelector?: any;
        vehicleTask?: any;
        aimControls?: any;
        furnishing?: any;
        furnitureEditor?: any;
        dmvTest?: any;
        dmvTmpKnowledge?: boolean;
        dmvTesting?: boolean;
        dmvWaivedPayments?: number;
        report: any[];
        wakeUpTimer?: NodeJS.Timeout;
        spectating?: any;
        itemOffer?: any;
        bluetoothConnectedTo?: ObjectMp;
        localStation?: any;
        localStationVolume?: number;
        killEvent?: any;
        killTime?: number;
        damageHistory: any[];
        deathState: DeathState;
        falling: boolean;
        lastMissclick?: number;
        drugVisualEffects?: any[];
        drugCameraEffect?: any;
        smoking?: any;
        drinking?: any;
        offer?: PlayerOffer;
        mdcInitialized?: boolean;
        loginTimeOut?: NodeJS.Timeout;
        loginAttempts: number;
        afkTimeout?: NodeJS.Timeout;
        trackedDutyIds: number[];
        afkStartTime?: number;
        afkDutyStartTime?: number;
        afkDutyEndTime?: number;
        tabStartTime?: number;
        tabEndTime?: number;
        adminDutyStartTime?: number;
        testerDutyStartTime?: number;
        quietModeStartTime?: number;
        pmWatchers: PlayerMpLoggedIn[];
        pmWatched: PlayerMpLoggedIn[];
        freqWatched: number[];
        factionWatched: any[];
        companyWatched: any[];
        muted?: any;
        lastKillAlert?: number;
        adminJail?: any;
        characterCreatorCharacterId?: number;
        helpmeRequest?: any;
        wikiBookmarks: any[];
        weapons?: any[];
        atm?: any;
        atmAccountUsed?: any;
        healthTracker?: NodeJS.Timer;
        actionLock: number;
        polygonEditor?: any;
        duty?: DutyState;
        serverWeapons: Record<string, number>;
        dutyTimeOverall?: number;
        specialDutyTimeOverall?: number;
        specialDuty?: number;
        lastWound?: number;
        maxHealth: number;
        regenTick?: number;
        deptFrequency?: any;
        friskRequests?: PlayerMpLoggedIn[];
        frisksApproved?: PlayerMpLoggedIn[];
        fishing?: any;
        barberShop?: any;
        adCooldown?: number;
        lastLessLethalHit?: number;
        lastPaintballHit?: number;
        lastPaintbillRuleHit?: number;
        paintballRuleHits?: number;
        attachingPlate?: any;
        removingPlate?: any;
        blockPm?: any;
        prisonCell?: any;
        propertyRadioColshapes?: any;
        vehicleLockBreakin?: VehicleWrapper;
        vehicleHotwire?: VehicleWrapper;
        bleedOut?: any;
        propertyBreakin?: number;
        dutyHandcuffs: number;
        applyingMakeup?: any;
        staticWeather?: string;
        staticTime?: number;
        pendingVehicle?: boolean;
        oocChatDisabled?: boolean;
        staffMessagesDisabled?: boolean;
        processingMissionKey?: boolean;
        showJoinMessages?: boolean;
        nametagDamageBlipTimeout?: NodeJS.Timeout;
        outfitOverrides: any[];
        lastWeaponShot?: any;
        autoLow?: any;
        vehicleModShop?: any;
        tvAccess?: number;
        lastPMSender?: PlayerMpLoggedIn;
        handlingCorpse?: boolean;
        tutorialCooldown?: number;
        mdcExtraData?: any;
        currentCallMenu?: string;
        radioFreqOrder?: any;
        lastEquippedBulletWeapon?: string;
        lastEquippedMeleeWeapon?: string;
        holdingObject?: boolean;
        tackleCooldown?: number;
        tackled?: boolean;
        changeCharacterCooldown?: number;
        corpseDigging?: boolean;
        chatHighlight?: number[];
        pushingGurney?: ObjectMp;
        onGurney?: ObjectMp;
        processingPhonePower?: boolean;
        lastTeleport?: any;
        fakeCall?: boolean;
        props: [number, number][];
    }

    // ---- Misc types from original types.d.ts -------------------------------
    type DeathState = 'ALIVE' | 'WOUNDED' | 'KNOCKED' | 'DEAD';

    interface PlayerOffer {
        target: PlayerWrapper;
        autoReject: NodeJS.Timeout;
        proximity?: number;
        resolve: (value: boolean) => void;
    }

    interface VehicleMechanicOperation {
        name: string;
        mechanic: PlayerMpLoggedIn;
        customer: PlayerMpLoggedIn;
        vehicle: VehicleWrapper;
        companyId: number;
        vehicleEntity: import('../entities/vehicle.entity').VehicleEntity;
        activity: 'paint' | 'wheels' | 'tint' | 'upgrade' | 'repair' | 'suspension' | 'engine' | 'brakes';
        data: Record<string, any>;
        timer?: NodeJS.Timeout;
        timeReady: number;
        invoiceId: number;
        mechanicReward: number;
    }

    interface VehicleAttachment {
        attachment: any;
        bone: string;
        collision: boolean;
        x: number; y: number; z: number;
        rx: number; ry: number; rz: number;
        opacity: number;
    }

    interface VehicleLabel {
        text: string; font: number; color: number; size: number;
        outline: boolean; bone: string; offset: Vector3; opacity: number; distance: number;
    }

    type CommandParamValidator =
        | 'player' | 'character' | 'account' | 'number' | 'integer'
        | 'string' | 'word' | 'vehicle' | 'property' | 'item'
        | 'company' | 'faction' | 'ped'
        | readonly any[] | any[] | RegExp;

    type CommandGuard = (player: PlayerWrapper) => true | string;

    type DutyState = { callsign: string; start: number; weapons: any[] };
    type BoundingBox = [number, number, number, number, number, number];
    type FineEntities = 'person' | 'vehicle' | 'company' | 'faction' | 'property';
    type EngineData = [string, string, number, number, number, number];
    type KeyValueCollection = Record<string, any>;
    type EventMpThis = any;
}

declare global {
    // DamageHistory / KillEntry — from features/damage/state.d.ts
    type DamageHistory = {
        id: number;
        damager: { id: number; name: string; position: Vector3; dimension: number; health: number; armor: number };
        weapon: { gameId: number; weaponName: string; ammoType: string; currentWeaponAmmo: number };
        boneIndex: number; damage: number; time: number; position: Vector3; dimension: number;
        armorHit: boolean; distance: number; health: number; armor: number;
        bleeding: number | null; postMortem?: boolean;
    };

    interface KillEntry {
        _id: string; victim_id: number; victim_name: string; victim_damages: DamageHistory[];
        killer_id: number | null; killer_name: string | null;
        kill_type: 'WOUNDED' | 'KNOCKED'; weapon: string; time: string;
        executed_time: string | null; executed_by_id: number | null;
        executed_by_name: string | null; executed_by_weapon: string | null;
        revived: string | null; respawned: string | null; accepted_death: string | null;
        rescued: string | null; rescued_by: string | null;
    }

    // mp global — set at runtime by mp-shim.ts, declared here for TypeScript
    const mp: {
        events: {
            add(event: string, handler: Function): void;
            add(events: Record<string, Function>): void;
            addProc(name: string, handler: Function): void;
            call(event: string, ...args: any[]): void;
            callRemote(event: string, ...args: any[]): void;
            delayInitialization: boolean;
        };
        players: {
            at(id: number): PlayerWrapper | undefined;
            toArray(): PlayerWrapper[];
            toArrayFast(): PlayerWrapper[];
            forEach(fn: (player: PlayerWrapper) => void): void;
            broadcast(message: string): void;
            length: number;
            exists(player: PlayerWrapper): boolean;
        };
        Vector3: new (x: number, y: number, z: number) => Vector3;
        vehicles: {
            new(model: string | number, position: Vector3, options?: any): import('./vehicle/vehicle-wrapper').VehicleWrapper;
            at(id: number): import('./vehicle/vehicle-wrapper').VehicleWrapper | undefined;
            toArray(): import('./vehicle/vehicle-wrapper').VehicleWrapper[];
            forEach(fn: (vehicle: import('./vehicle/vehicle-wrapper').VehicleWrapper) => void): void;
        };
        config: Record<string, any>;
        objects: { new(...args: any[]): any; at(id: number): any; toArray(): any[]; forEach(fn: any): void };
        peds: { new(...args: any[]): any; at(id: number): any; toArray(): any[]; forEach(fn: any): void };
        markers: { new(...args: any[]): any };
        blips: { new(...args: any[]): any };
        labels: { new(...args: any[]): any };
        colshapes: {
            newSphere(...args: any[]): any;
            newCuboid(...args: any[]): any;
            newCircle(...args: any[]): any;
            newRectangle(...args: any[]): any;
            newTube(...args: any[]): any;
            newPolygon(...args: any[]): any;
        };
    };

    type CommandParamMetaData<T> = {
        [K in keyof T]: {
            hint: string;
            validator: CommandParamValidator;
            default?: any;
            length?: number;
            overrides?: Record<string, Record<number, CommandParamMetaData<any>>>;
        };
    };

    interface VehicleLogComposition {
        id?: number;
        gameId: number;
        owner?: string;
        model: string;
        plate: string;
        occupants: string;
        bodyHealth: number;
        engineHealth: number;
        speedInMph: number;
    }

    // Client-side map object stubs (server never creates these directly in FiveM)
    interface BlipMp { destroy(): void; }
    interface MarkerMp { destroy(): void; }
    interface LabelMp { destroy(): void; }
    interface CheckpointMp { destroy(): void; }
    interface TextLabelMp { destroy(): void; text: string; }

    // PedCustomization — from original types.d.ts
    interface PedCustomization {
        headBlend: { shapes: number[]; skins: number[]; shapeMix: number; skinMix: number; thirdMix: number };
        headOverlay: { overlayId: number; data: Array4d }[];
        faceFeatures: { featureId: number; data: number }[];
        hairData: { drawable: number; color1: number; color2: number };
        outfitData: { component: number; drawable: number[] }[];
        propData: { propIndex: number; prop: [number, number] }[];
        vehicle?: { status: boolean; vehID: number; seat: number };
        weapon?: number;
    }
}

export {};
