using System.Text.Json.Serialization;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;

namespace SPTarkov.Server.Core.Models.Eft.Common.Tables;

public record BotType
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    [JsonPropertyName("appearance")]
    public Appearance BotAppearance { get; set; }

    [JsonPropertyName("chances")]
    public Chances BotChances { get; set; }

    [JsonPropertyName("difficulty")]
    public Dictionary<string, DifficultyCategories> BotDifficulty { get; set; }

    [JsonPropertyName("experience")]
    public Experience BotExperience { get; set; }

    [JsonPropertyName("firstName")]
    public List<string> FirstNames { get; set; }

    [JsonPropertyName("generation")]
    public Generation BotGeneration { get; set; }

    [JsonPropertyName("health")]
    public BotTypeHealth BotHealth { get; set; }

    [JsonPropertyName("inventory")]
    public BotTypeInventory BotInventory { get; set; }

    [JsonPropertyName("lastName")]
    public IEnumerable<string> LastNames { get; set; }

    [JsonPropertyName("skills")]
    public BotDbSkills BotSkills { get; set; }
}

public record Appearance
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    [JsonPropertyName("body")]
    public Dictionary<MongoId, double> Body { get; set; }

    [JsonPropertyName("feet")]
    public Dictionary<MongoId, double> Feet { get; set; }

    [JsonPropertyName("hands")]
    [JsonConverter(typeof(ArrayToObjectFactoryConverter))]
    public Dictionary<MongoId, double> Hands { get; set; }

    [JsonPropertyName("head")]
    [JsonConverter(typeof(ArrayToObjectFactoryConverter))]
    public Dictionary<MongoId, double> Head { get; set; }

    [JsonPropertyName("voice")]
    [JsonConverter(typeof(ArrayToObjectFactoryConverter))]
    public Dictionary<string, double> Voice { get; set; }
}

public record Chances
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    [JsonPropertyName("equipment")]
    public Dictionary<string, double> EquipmentChances { get; set; }

    [JsonPropertyName("weaponMods")]
    public Dictionary<string, double> WeaponModsChances { get; set; }

    [JsonPropertyName("equipmentMods")]
    public Dictionary<string, double> EquipmentModsChances { get; set; }
}

/* record removed in favor of Dictionary<string, double>
 used to be used in:
 Chances.WeaponModsChances
 Chances.EquipmentModsChances
 GenerateWeaponRequest.ModSpawnChances
public record ModsChances
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    [JsonPropertyName("mod_charge")]
public double? ModCharge { get; set; }

    [JsonPropertyName("mod_bipod")]
public double? ModBipod { get; set; }

    [JsonPropertyName("mod_barrel")]
public double? ModBarrel { get; set; }

    [JsonPropertyName("mod_catch")]
public double? ModCatch { get; set; }

    [JsonPropertyName("mod_gas_block")]
public double? ModGasBlock { get; set; }

    [JsonPropertyName("mod_hammer")]
public double? ModHammer { get; set; }

    [JsonPropertyName("mod_equipment")]
public double? ModEquipment { get; set; }

    [JsonPropertyName("mod_equipment_000")]
public double? ModEquipment000 { get; set; }

    [JsonPropertyName("mod_equipment_001")]
public double? ModEquipment001 { get; set; }

    [JsonPropertyName("mod_equipment_002")]
public double? ModEquipment002 { get; set; }

    [JsonPropertyName("mod_flashlight")]
public double? ModFlashlight { get; set; }

    [JsonPropertyName("mod_foregrip")]
public double? ModForegrip { get; set; }

    [JsonPropertyName("mod_launcher")]
public double? ModLauncher { get; set; }

    [JsonPropertyName("mod_magazine")]
public double? ModMagazine { get; set; }

    [JsonPropertyName("mod_mount")]
public double? ModMount { get; set; }

    [JsonPropertyName("mod_mount_000")]
public double? ModMount000 { get; set; }

    [JsonPropertyName("mod_mount_001")]
public double? ModMount001 { get; set; }

    [JsonPropertyName("mod_muzzle")]
public double? ModMuzzle { get; set; }

    [JsonPropertyName("mod_nvg")]
public double? ModNvg { get; set; }

    [JsonPropertyName("mod_pistol_grip")]
public double? ModPistolGrip { get; set; }

    [JsonPropertyName("mod_reciever")]
public double? ModReceiver { get; set; }

    [JsonPropertyName("mod_scope")]
public double? ModScope { get; set; }

    [JsonPropertyName("mod_scope_000")]
public double? ModScope000 { get; set; }

    [JsonPropertyName("mod_scope_001")]
public double? ModScope001 { get; set; }

    [JsonPropertyName("mod_scope_002")]
public double? ModScope002 { get; set; }

    [JsonPropertyName("mod_scope_003")]
public double? ModScope003 { get; set; }

    [JsonPropertyName("mod_sight_front")]
public double? ModSightFront { get; set; }

    [JsonPropertyName("mod_sight_rear")]
public double? ModSightRear { get; set; }

    [JsonPropertyName("mod_stock")]
public double? ModStock { get; set; }

    [JsonPropertyName("mod_stock_000")]
public double? ModStock000 { get; set; }

    [JsonPropertyName("mod_stock_002")]
public double? ModStock002 { get; set; }

    [JsonPropertyName("mod_stock_akms")]
public double? ModStockAkms { get; set; }

    [JsonPropertyName("mod_tactical")]
public double? ModTactical { get; set; }

    [JsonPropertyName("mod_tactical_000")]
public double? ModTactical000 { get; set; }

    [JsonPropertyName("mod_tactical_001")]
public double? ModTactical001 { get; set; }

    [JsonPropertyName("mod_tactical_002")]
public double? ModTactical002 { get; set; }

    [JsonPropertyName("mod_tactical_2")]
public double? ModTactical2 { get; set; }

    [JsonPropertyName("mod_tactical_003")]
public double? ModTactical003 { get; set; }

    [JsonPropertyName("mod_handguard")]
public double? ModHandguard { get; set; }

    [JsonPropertyName("back_plate")]
public double? BackPlate { get; set; }

    [JsonPropertyName("front_plate")]
public double? FrontPlate { get; set; }

    [JsonPropertyName("left_side_plate")]
public double? LeftSidePlate { get; set; }

    [JsonPropertyName("right_side_plate")]
public double? RightSidePlate { get; set; }

    [JsonPropertyName("mod_mount_002")]
public double? ModMount002 { get; set; }

    [JsonPropertyName("mod_mount_003")]
public double? ModMount003 { get; set; }

    [JsonPropertyName("mod_mount_004")]
public double? ModMount004 { get; set; }

    [JsonPropertyName("mod_mount_005")]
public double? ModMount005 { get; set; }

    [JsonPropertyName("mod_mount_006")]
public double? ModMount006 { get; set; }

    [JsonPropertyName("mod_muzzle_000")]
public double? ModMuzzle000 { get; set; }

    [JsonPropertyName("mod_muzzle_001")]
public double? ModMuzzle001 { get; set; }

    [JsonPropertyName("mod_pistol_grip_akms")]
public double? ModPistolGripAkms { get; set; }

    [JsonPropertyName("mod_pistolgrip")]
public double? ModPistol_Grip { get; set; }
}
*/

public record DifficultyCategories
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    public Dictionary<string, object>? Aiming { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Boss { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Change { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Core { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Cover { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Grenade { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Hearing { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Lay { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Look { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Mind { get; set; } // TODO: string | number | boolean | string[]

    public Dictionary<string, object>? Move { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Patrol { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Scattering { get; set; } // TODO: string | number | boolean

    public Dictionary<string, object>? Shoot { get; set; } // TODO: string | number | boolean
}

public record Experience
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    /// <summary>
    ///     key = bot difficulty
    /// </summary>
    [JsonPropertyName("aggressorBonus")]
    public Dictionary<string, double> AggressorBonus { get; set; }

    [JsonPropertyName("level")]
    public MinMax<int> Level { get; set; }

    /// <summary>
    ///     key = bot difficulty
    /// </summary>
    [JsonPropertyName("reward")]
    public Dictionary<string, MinMax<int>> Reward { get; set; }

    /// <summary>
    ///     key = bot difficulty
    /// </summary>
    [JsonPropertyName("standingForKill")]
    public Dictionary<string, double> StandingForKill { get; set; }

    [JsonPropertyName("useSimpleAnimator")]
    public bool UseSimpleAnimator { get; set; }
}

public record Generation
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    [JsonPropertyName("items")]
    public GenerationWeightingItems Items { get; set; }
}

public record GenerationData
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    /// <summary>
    ///     key: number of items, value: weighting
    /// </summary>
    [JsonPropertyName("weights")]
    public Dictionary<double, double> Weights { get; set; }

    /// <summary>
    ///     Array of item tpls
    /// </summary>
    [JsonPropertyName("whitelist")]
    [JsonConverter(typeof(ArrayToObjectFactoryConverter))]
    public Dictionary<MongoId, double> Whitelist { get; set; }
}

public record GenerationWeightingItems
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    [JsonPropertyName("grenades")]
    public GenerationData Grenades { get; set; }

    [JsonPropertyName("healing")]
    public GenerationData Healing { get; set; }

    [JsonPropertyName("drugs")]
    public GenerationData Drugs { get; set; }

    [JsonPropertyName("food")]
    public GenerationData Food { get; set; }

    [JsonPropertyName("drink")]
    public GenerationData Drink { get; set; }

    [JsonPropertyName("currency")]
    public GenerationData Currency { get; set; }

    [JsonPropertyName("stims")]
    public GenerationData Stims { get; set; }

    [JsonPropertyName("backpackLoot")]
    public GenerationData BackpackLoot { get; set; }

    [JsonPropertyName("pocketLoot")]
    public GenerationData PocketLoot { get; set; }

    [JsonPropertyName("vestLoot")]
    public GenerationData VestLoot { get; set; }

    [JsonPropertyName("magazines")]
    public GenerationData Magazines { get; set; }

    [JsonPropertyName("specialItems")]
    public GenerationData SpecialItems { get; set; }

    [JsonPropertyName("looseLoot")]
    public GenerationData LooseLoot { get; set; }
}

public record BotTypeHealth
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    public IEnumerable<BodyPart> BodyParts { get; set; }

    public MinMax<double> Energy { get; set; }

    public MinMax<double> Hydration { get; set; }

    public MinMax<double> Temperature { get; set; }
}

public record BodyPart
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    public MinMax<double> Chest { get; set; }

    public MinMax<double> Head { get; set; }

    public MinMax<double> LeftArm { get; set; }

    public MinMax<double> LeftLeg { get; set; }

    public MinMax<double> RightArm { get; set; }

    public MinMax<double> RightLeg { get; set; }

    public MinMax<double> Stomach { get; set; }
}

public record BotTypeInventory
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    [JsonPropertyName("equipment")]
    public Dictionary<EquipmentSlots, Dictionary<MongoId, double>> Equipment { get; set; }

    public Dictionary<string, Dictionary<MongoId, double>> Ammo { get; set; }

    [JsonPropertyName("items")]
    public ItemPools Items { get; set; }

    [JsonPropertyName("mods")]
    public GlobalMods Mods { get; set; }
}

public record ItemPools
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    public Dictionary<MongoId, double> Backpack { get; set; }

    public Dictionary<MongoId, double> Pockets { get; set; }

    public Dictionary<MongoId, double> SecuredContainer { get; set; }

    public Dictionary<MongoId, double> SpecialLoot { get; set; }

    public Dictionary<MongoId, double> TacticalVest { get; set; }
}

public record BotDbSkills
{
    [JsonExtensionData]
    public Dictionary<string, object>? ExtensionData { get; set; }

    public Dictionary<string, MinMax<double>> Common { get; set; }

    public Dictionary<string, MinMax<double>>? Mastering { get; set; }
}
