import type { Race, Races } from '../types/Race';
import type { Profession, Professions } from '../types/Profession';
import type { Attribute, Attributes } from '../types/Attribute';
import type { AttributeValue } from '../types/CharacterJson';
import type { Advantage } from '../types/Advantage';
import type { AnimistForce } from '../types/AnimistForce';
import type { ArcaneBardTradition } from '../types/ArcaneBardTradition';
import type { ArcaneDancerTradition } from '../types/ArcaneDancerTradition';
import type { ArmorType } from '../types/ArmorType';
import type { Aspect } from '../types/Aspect';
import type { BlessedTradition } from '../types/BlessedTradition';
import type { Blessing } from '../types/Blessing';
import type { Book } from '../types/Book';
import type { Brew } from '../types/Brew';
import type { Cantrip } from '../types/Cantrip';
import type { CombatSpecialAbilityGroup } from '../types/CombatSpecialAbilityGroup';
import type { CombatTechniqueGroup } from '../types/CombatTechniqueGroup';
import type { CombatTechnique } from '../types/CombatTechnique';
import type { Condition } from '../types/Condition';
import type { Culture } from '../types/Culture';
import type { Curse } from '../types/Curse';
import type { DerivedCharacteristic } from '../types/DerivedCharacteristic';
import type { Disadvantage } from '../types/Disadvantage';
import type { DominationRitual } from '../types/DominationRitual';
import type { Element } from '../types/Element';
import type { ElvenMagicalSong } from '../types/ElvenMagicalSong';
import type { EquipmentGroup } from '../types/EquipmentGroup';
import type { EquipmentPackage } from '../types/EquipmentPackage';
import type { Equipment } from '../types/Equipment';
import type { ExperienceLevel } from '../types/ExperienceLevel';
import type { EyeColor } from '../types/EyeColor';
import type { FocusRule } from '../types/FocusRule';
import type { GeodeRitual } from '../types/GeodeRitual';
import type { HairColor } from '../types/HairColor';
import type { LiturgicalChantEnhancement } from '../types/LiturgicalChantEnhancement';
import type { LiturgicalChantGroup } from '../types/LiturgicalChantGroup';
import type { LiturgicalChant } from '../types/LiturgicalChant';
import type { MagicalDance } from '../types/MagicalDance';
import type { MagicalMelodie } from '../types/MagicalMelodie';
import type { MagicalTradition } from '../types/MagicalTradition';
import type { OptionalRule } from '../types/OptionalRule';
import type { Pact } from '../types/Pact';
import type { PatronCategorie } from '../types/PatronCategorie';
import type { Patron } from '../types/Patron';
import type { ProfessionVariant } from '../types/ProfessionVariant';
import type { Propertie } from '../types/Propertie';
import type { RaceVariant } from '../types/RaceVariant';
import type { Reache } from '../types/Reache';
import type { RogueSpell } from '../types/RogueSpell';
import type { SkillGroup } from '../types/SkillGroup';
import type { Skill } from '../types/Skill';
import type { SocialStatuse } from '../types/SocialStatuse';
import type { SpecialAbilitie } from '../types/SpecialAbilitie';
import type { SpecialAbilityGroup } from '../types/SpecialAbilityGroup';
import type { SpellEnhancement } from '../types/SpellEnhancement';
import type { SpellGroup } from '../types/SpellGroup';
import type { Spell } from '../types/Spell';
import type { State } from '../types/State';
import type { Subject } from '../types/Subject';
import type { Tribe } from '../types/Tribe';
import type { ZibiljaRitual } from '../types/ZibiljaRitual';

/**
 * Generic function to load data from a JSON file
 * @param fileName The name of the JSON file to load
 * @returns A promise that resolves to the loaded data
 */
async function loadData<T>(fileName: string): Promise<T[]> {
  try {
    const response = await fetch(`/data/database/${fileName}`);
    if (!response.ok) {
      throw new Error(`Failed to load ${fileName}: ${response.statusText}`);
    }
    return await response.json();
  } catch (error) {
    console.error(`Error loading ${fileName}:`, error);
    throw error;
  }
}

/**
 * Generic function to get an item by ID
 * @param fileName The name of the JSON file to load
 * @param id The ID of the item to find
 * @returns A promise that resolves to the item with the specified ID, or undefined if not found
 */
async function getItemById<T extends { id: string }>(fileName: string, id: string): Promise<T | undefined> {
  const data = await loadData<T>(fileName);
  return data.find(item => item.id === id);
}

/**
 * Function to get the name of an item by ID
 * @param fileName The name of the JSON file to load
 * @param id The ID of the item to find
 * @returns A promise that resolves to the name of the item with the specified ID, or the ID if not found
 */
export async function getItemNameById(fileName: string, id: string): Promise<string> {
  try {
    const response = await fetch(`/data/database/${fileName.replace('.yaml', '.json')}`);
    if (!response.ok) {
      throw new Error(`Failed to load ${fileName}: ${response.statusText}`);
    }
    const data = await response.json();
    const item = data.find((item: any) => item.id === id);

    if (!item) {
      return id;
    }

    // Handle different name formats
    if (typeof item.name === 'string') {
      return item.name;
    } else if (item.name && (item.name.m || item.name.f)) {
      // For gendered names, return male name by default
      return item.name.m || item.name.f;
    }

    return id;
  } catch (error) {
    console.error(`Error getting name for ${id} from ${fileName}:`, error);
    return id;
  }
}

// Race loader
export async function loadRace(id: string): Promise<Race | undefined> {
  return getItemById<Race>('Races.json', id);
}

// Profession loader
export async function loadProfession(id: string): Promise<Profession | undefined> {
  return getItemById<Profession>('Professions.json', id);
}

// Interface for attribute with value, name, and short
export interface AttributeWithValue extends Attribute {
  value: number;
}

// Attribute loader
export async function loadAttribute(id: string): Promise<Attribute | undefined> {
  return getItemById<Attribute>('Attributes.json', id);
}

// Load attribute with value, name, and short
export async function loadAttributeWithValue(attributeValue: AttributeValue): Promise<AttributeWithValue | undefined> {
  const attribute = await loadAttribute(attributeValue.id);

  if (!attribute) {
    return undefined;
  }

  return {
    ...attribute,
    value: attributeValue.value
  };
}

// Load multiple attributes with values
export async function loadAttributesWithValues(attributeValues: AttributeValue[]): Promise<AttributeWithValue[]> {
  const promises = attributeValues.map(attrValue => loadAttributeWithValue(attrValue));
  const attributes = await Promise.all(promises);

  // Filter out undefined values
  return attributes.filter((attr): attr is AttributeWithValue => attr !== undefined);
}

// Advantage loader
export async function loadAdvantage(id: string): Promise<Advantage | undefined> {
  return getItemById<Advantage>('Advantages.json', id);
}

// AnimistForce loader
export async function loadAnimistForce(id: string): Promise<AnimistForce | undefined> {
  return getItemById<AnimistForce>('AnimistForces.json', id);
}

// ArcaneBardTradition loader
export async function loadArcaneBardTradition(id: string): Promise<ArcaneBardTradition | undefined> {
  return getItemById<ArcaneBardTradition>('ArcaneBardTraditions.json', id);
}

// ArcaneDancerTradition loader
export async function loadArcaneDancerTradition(id: string): Promise<ArcaneDancerTradition | undefined> {
  return getItemById<ArcaneDancerTradition>('ArcaneDancerTraditions.json', id);
}

// ArmorType loader
export async function loadArmorType(id: string): Promise<ArmorType | undefined> {
  return getItemById<ArmorType>('ArmorTypes.json', id);
}

// Aspect loader
export async function loadAspect(id: string): Promise<Aspect | undefined> {
  return getItemById<Aspect>('Aspects.json', id);
}

// BlessedTradition loader
export async function loadBlessedTradition(id: string): Promise<BlessedTradition | undefined> {
  return getItemById<BlessedTradition>('BlessedTraditions.json', id);
}

// Blessing loader
export async function loadBlessing(id: string): Promise<Blessing | undefined> {
  return getItemById<Blessing>('Blessings.json', id);
}

// Book loader
export async function loadBook(id: string): Promise<Book | undefined> {
  return getItemById<Book>('Books.json', id);
}

// Brew loader
export async function loadBrew(id: string): Promise<Brew | undefined> {
  return getItemById<Brew>('Brews.json', id);
}

// Cantrip loader
export async function loadCantrip(id: string): Promise<Cantrip | undefined> {
  return getItemById<Cantrip>('Cantrips.json', id);
}

// CombatSpecialAbilityGroup loader
export async function loadCombatSpecialAbilityGroup(id: string): Promise<CombatSpecialAbilityGroup | undefined> {
  return getItemById<CombatSpecialAbilityGroup>('CombatSpecialAbilityGroups.json', id);
}

// CombatTechniqueGroup loader
export async function loadCombatTechniqueGroup(id: string): Promise<CombatTechniqueGroup | undefined> {
  return getItemById<CombatTechniqueGroup>('CombatTechniqueGroups.json', id);
}

// CombatTechnique loader
export async function loadCombatTechnique(id: string): Promise<CombatTechnique | undefined> {
  return getItemById<CombatTechnique>('CombatTechniques.json', id);
}

// Condition loader
export async function loadCondition(id: string): Promise<Condition | undefined> {
  return getItemById<Condition>('Conditions.json', id);
}

// Culture loader
export async function loadCulture(id: string): Promise<Culture | undefined> {
  return getItemById<Culture>('Cultures.json', id);
}

// Curse loader
export async function loadCurse(id: string): Promise<Curse | undefined> {
  return getItemById<Curse>('Curses.json', id);
}

// DerivedCharacteristic loader
export async function loadDerivedCharacteristic(id: string): Promise<DerivedCharacteristic | undefined> {
  return getItemById<DerivedCharacteristic>('DerivedCharacteristics.json', id);
}

// Disadvantage loader
export async function loadDisadvantage(id: string): Promise<Disadvantage | undefined> {
  return getItemById<Disadvantage>('Disadvantages.json', id);
}

// DominationRitual loader
export async function loadDominationRitual(id: string): Promise<DominationRitual | undefined> {
  return getItemById<DominationRitual>('DominationRituals.json', id);
}

// Element loader
export async function loadElement(id: string): Promise<Element | undefined> {
  return getItemById<Element>('Elements.json', id);
}

// ElvenMagicalSong loader
export async function loadElvenMagicalSong(id: string): Promise<ElvenMagicalSong | undefined> {
  return getItemById<ElvenMagicalSong>('ElvenMagicalSongs.json', id);
}

// EquipmentGroup loader
export async function loadEquipmentGroup(id: string): Promise<EquipmentGroup | undefined> {
  return getItemById<EquipmentGroup>('EquipmentGroups.json', id);
}

// Equipment loader
export async function loadEquipment(id: string): Promise<Equipment | undefined> {
  return getItemById<Equipment>('Equipment.json', id);
}

// EquipmentPackage loader
export async function loadEquipmentPackage(id: string): Promise<EquipmentPackage | undefined> {
  return getItemById<EquipmentPackage>('EquipmentPackages.json', id);
}

// ExperienceLevel loader
export async function loadExperienceLevel(id: string): Promise<ExperienceLevel | undefined> {
  return getItemById<ExperienceLevel>('ExperienceLevels.json', id);
}

// EyeColor loader
export async function loadEyeColor(id: string): Promise<EyeColor | undefined> {
  return getItemById<EyeColor>('EyeColors.json', id);
}

// FocusRule loader
export async function loadFocusRule(id: string): Promise<FocusRule | undefined> {
  return getItemById<FocusRule>('FocusRules.json', id);
}

// GeodeRitual loader
export async function loadGeodeRitual(id: string): Promise<GeodeRitual | undefined> {
  return getItemById<GeodeRitual>('GeodeRituals.json', id);
}

// HairColor loader
export async function loadHairColor(id: string): Promise<HairColor | undefined> {
  return getItemById<HairColor>('HairColors.json', id);
}

// LiturgicalChantEnhancement loader
export async function loadLiturgicalChantEnhancement(id: string): Promise<LiturgicalChantEnhancement | undefined> {
  return getItemById<LiturgicalChantEnhancement>('LiturgicalChantEnhancements.json', id);
}

// LiturgicalChantGroup loader
export async function loadLiturgicalChantGroup(id: string): Promise<LiturgicalChantGroup | undefined> {
  return getItemById<LiturgicalChantGroup>('LiturgicalChantGroups.json', id);
}

// LiturgicalChant loader
export async function loadLiturgicalChant(id: string): Promise<LiturgicalChant | undefined> {
  return getItemById<LiturgicalChant>('LiturgicalChants.json', id);
}

// MagicalDance loader
export async function loadMagicalDance(id: string): Promise<MagicalDance | undefined> {
  return getItemById<MagicalDance>('MagicalDances.json', id);
}

// MagicalMelodie loader
export async function loadMagicalMelodie(id: string): Promise<MagicalMelodie | undefined> {
  return getItemById<MagicalMelodie>('MagicalMelodies.json', id);
}

// MagicalTradition loader
export async function loadMagicalTradition(id: string): Promise<MagicalTradition | undefined> {
  return getItemById<MagicalTradition>('MagicalTraditions.json', id);
}

// OptionalRule loader
export async function loadOptionalRule(id: string): Promise<OptionalRule | undefined> {
  return getItemById<OptionalRule>('OptionalRules.json', id);
}

// Pact loader
export async function loadPact(id: string): Promise<Pact | undefined> {
  return getItemById<Pact>('Pacts.json', id);
}

// PatronCategorie loader
export async function loadPatronCategorie(id: string): Promise<PatronCategorie | undefined> {
  return getItemById<PatronCategorie>('PatronCategories.json', id);
}

// Patron loader
export async function loadPatron(id: string): Promise<Patron | undefined> {
  return getItemById<Patron>('Patrons.json', id);
}

// ProfessionVariant loader
export async function loadProfessionVariant(id: string): Promise<ProfessionVariant | undefined> {
  return getItemById<ProfessionVariant>('ProfessionVariants.json', id);
}

// Propertie loader
export async function loadPropertie(id: string): Promise<Propertie | undefined> {
  return getItemById<Propertie>('Properties.json', id);
}

// RaceVariant loader
export async function loadRaceVariant(id: string): Promise<RaceVariant | undefined> {
  return getItemById<RaceVariant>('RaceVariants.json', id);
}

// Reache loader
export async function loadReache(id: string): Promise<Reache | undefined> {
  return getItemById<Reache>('Reaches.json', id);
}

// RogueSpell loader
export async function loadRogueSpell(id: string): Promise<RogueSpell | undefined> {
  return getItemById<RogueSpell>('RogueSpells.json', id);
}

// SkillGroup loader
export async function loadSkillGroup(id: string): Promise<SkillGroup | undefined> {
  return getItemById<SkillGroup>('SkillGroups.json', id);
}

// Skill loader
export async function loadSkill(id: string): Promise<Skill | undefined> {
  return getItemById<Skill>('Skills.json', id);
}

// Interface for skill with value
export interface SkillWithValue extends Skill {
  value: number;
}

// Load skill with value
export async function loadSkillWithValue(id: string, value: number): Promise<SkillWithValue | undefined> {
  const skill = await loadSkill(id);

  if (!skill) {
    return undefined;
  }

  return {
    ...skill,
    value
  };
}

// Load multiple skills with values
export async function loadSkillsWithValues(talents: Skills): Promise<SkillWithValue[]> {
  const skillIds = Object.keys(talents);
  const promises = skillIds.map(id => loadSkillWithValue(id, talents[id]));
  const skills = await Promise.all(promises);

  // Filter out undefined values
  return skills.filter((skill): skill is SkillWithValue => skill !== undefined);
}

// SocialStatuse loader
export async function loadSocialStatuse(id: string): Promise<SocialStatuse | undefined> {
  return getItemById<SocialStatuse>('SocialStatuses.json', id);
}

// SpecialAbilitie loader
export async function loadSpecialAbilitie(id: string): Promise<SpecialAbilitie | undefined> {
  return getItemById<SpecialAbilitie>('SpecialAbilities.json', id);
}

// SpecialAbilityGroup loader
export async function loadSpecialAbilityGroup(id: string): Promise<SpecialAbilityGroup | undefined> {
  return getItemById<SpecialAbilityGroup>('SpecialAbilityGroups.json', id);
}

// SpellEnhancement loader
export async function loadSpellEnhancement(id: string): Promise<SpellEnhancement | undefined> {
  return getItemById<SpellEnhancement>('SpellEnhancements.json', id);
}

// SpellGroup loader
export async function loadSpellGroup(id: string): Promise<SpellGroup | undefined> {
  return getItemById<SpellGroup>('SpellGroups.json', id);
}

// Spell loader
export async function loadSpell(id: string): Promise<Spell | undefined> {
  return getItemById<Spell>('Spells.json', id);
}

// State loader
export async function loadState(id: string): Promise<State | undefined> {
  return getItemById<State>('States.json', id);
}

// Subject loader
export async function loadSubject(id: string): Promise<Subject | undefined> {
  return getItemById<Subject>('Subjects.json', id);
}

// Tribe loader
export async function loadTribe(id: string): Promise<Tribe | undefined> {
  return getItemById<Tribe>('Tribes.json', id);
}

// ZibiljaRitual loader
export async function loadZibiljaRitual(id: string): Promise<ZibiljaRitual | undefined> {
  return getItemById<ZibiljaRitual>('ZibiljaRituals.json', id);
}
