/**********************************************************************
 * ANIMAL CONSTANTS
 **********************************************************************/
const ANIMAL_HUNGER_MAX = 100;
const WOLF_HUNGER_INCREMENT = 0.01;
const WOLF_DAMAGE = 10;
const WOLF_ATTACK_RANGE = 15;
const WOLF_ATTACK_COOLDOWN = 100;
const WOLF_REPRO_CHANCE = 0.00008; // Much lower than rabbits
const WOLF_REPRO_COOLDOWN = 8000; // Longer cooldown than rabbits

/**********************************************************************
 * CITIZEN AI
 **********************************************************************/
function updateCitizen(cit) {
  cit.hunger += HUNGER_INCREMENT;
  if(cit.hunger > HUNGER_MAX) cit.hunger = HUNGER_MAX;

  if(["chop", "gatherFruit", "build", "treatPatients", "teachStudents", "sellGoods", "huntWolf", "patrol"].includes(cit.task)) {
    cit.energy -= ENERGY_DECREMENT_WORK;
  } else if(cit.task === "restAtHouse") {
    cit.energy += ENERGY_INCREMENT_REST;
  } else {
    cit.energy -= 0.0005;
  }
  
  if(cit.energy < 0) cit.energy = 0;
  if(cit.energy > ENERGY_MAX) cit.energy = ENERGY_MAX;

  // Health decreases if hunger is high
  if(cit.hunger > 80) {
    cit.health -= 0.01;
    if(cit.health < 0) cit.health = 0;
  }

  if(!cit.task) assignNewTask(cit);

  switch(cit.task) {
    case 'chop': chopTask(cit); break;
    case 'deliverWood': deliverWoodTask(cit); break;
    case 'build': buildTask(cit); break;
    case 'gatherFruit': gatherFruitTask(cit); break;
    case 'deliverFruit': deliverFruitTask(cit); break;
    case 'plantFruitTree': plantFruitTreeTask(cit); break;
    case 'eatAtHouse': eatAtHouseTask(cit); break;
    case 'restAtHouse': restAtHouseTask(cit); break;
    case 'treatPatients': treatPatientsTask(cit); break;
    case 'teachStudents': teachStudentsTask(cit); break;
    case 'sellGoods': sellGoodsTask(cit); break;
    case 'visitHospital': visitHospitalTask(cit); break;
    case 'visitSchool': visitSchoolTask(cit); break;
    case 'huntWolf': huntWolfTask(cit); break;
    case 'patrol': patrolTask(cit); break;
    default: randomWander(cit); break;
  }

  cit.x += cit.vx;
  cit.y += cit.vy;
}

function updateWolf(w) {
  w.hunger += WOLF_HUNGER_INCREMENT;
  if(w.hunger >= ANIMAL_HUNGER_MAX) {
    w.dead = true;
    logAction("A wolf starved to death.");
    return;
  }
  
  // Look for prey
  if(w.hunger > 30) {
    // First try to find rabbits
    let rabbit = findNearestAnimalOfType(w, "Rabbit");
    if(rabbit && distance(w.x, w.y, rabbit.x, rabbit.y) < 200) {
      moveToward(w, rabbit.x, rabbit.y, WOLF_SPEED);
      
      // Attack if close enough and cooldown is ready
      if(distance(w.x, w.y, rabbit.x, rabbit.y) < WOLF_ATTACK_RANGE && w.attackCooldown <= 0) {
        rabbit.dead = true;
        w.hunger -= 30;
        if(w.hunger < 0) w.hunger = 0;
        w.attackCooldown = WOLF_ATTACK_COOLDOWN;
        logAction("A wolf caught and ate a rabbit!");
      }
      return;
    }
    
    // If no rabbits nearby, look for citizens (but not if soldiers are nearby)
    let nearbySoldier = citizens.find(c => 
      c.profession === "Soldier" && 
      distance(w.x, w.y, c.x, c.y) < 100
    );
    
    if(!nearbySoldier) {
      let citizen = citizens.find(c => distance(w.x, w.y, c.x, c.y) < 150);
      if(citizen) {
        moveToward(w, citizen.x, citizen.y, WOLF_SPEED);
        
        // Attack if close enough and cooldown is ready
        if(distance(w.x, w.y, citizen.x, citizen.y) < WOLF_ATTACK_RANGE && w.attackCooldown <= 0) {
          citizen.health -= WOLF_DAMAGE;
          w.attackCooldown = WOLF_ATTACK_COOLDOWN;
          
          // Knockback effect
          knockback(citizen, w.x, w.y, 20);
          
          logAction(`A wolf attacked ${citizen.name}! Health: ${Math.floor(citizen.health)}`);
          
          if(citizen.health <= 0) {
            // Remove citizen
            citizens = citizens.filter(c => c !== citizen);
            logAction(`${citizen.name} was killed by a wolf!`);
            w.hunger -= 50;
            if(w.hunger < 0) w.hunger = 0;
          }
        }
        return;
      }
    } else {
      // Run away from soldier
      moveAway(w, nearbySoldier.x, nearbySoldier.y, WOLF_SPEED);
      return;
    }
  }
  
  // Reproduce - wolves need to be well-fed and have low hunger to reproduce
  if(w.hunger < 20 && w.reproductionCooldown <= 0) {
    // Find another wolf nearby for mating
    let nearbyWolf = findNearestAnimalOfType(w, "Wolf");
    if(nearbyWolf && nearbyWolf !== w && distance(w.x, w.y, nearbyWolf.x, nearbyWolf.y) < 50) {
      if(Math.random() < WOLF_REPRO_CHANCE) {
        spawnBabyAnimal("Wolf", w.x, w.y);
        w.reproductionCooldown = WOLF_REPRO_COOLDOWN;
        logAction("A wolf pack has grown - a new wolf pup was born!");
      }
    }
  }
  
  // Random movement
  randomAnimalWander(w);
}

/**********************************************************************
 * ANIMAL AI
 **********************************************************************/
function updateAnimal(ani) {
  if(ani.type === "Rabbit") {
    updateRabbit(ani);
  } else if(ani.type === "Wolf") {
    updateWolf(ani);
  }
  
  ani.x += ani.vx;
  ani.y += ani.vy;
  if(ani.reproductionCooldown > 0) {
    ani.reproductionCooldown--;
  }
  if(ani.attackCooldown > 0) {
    ani.attackCooldown--;
  }
}

function updateRabbit(r) {
  r.hunger += RABBIT_HUNGER_INCREMENT;
  if(r.hunger >= ANIMAL_HUNGER_MAX) {
    r.dead = true;
    logAction("A rabbit starved to death.");
    return;
  }
  
  // Check for nearby wolves and run away
  let nearestWolf = findNearestAnimalOfType(r, "Wolf");
  if(nearestWolf && distance(r.x, r.y, nearestWolf.x, nearestWolf.y) < 100) {
    // Run away from wolf
    moveAway(r, nearestWolf.x, nearestWolf.y, 0.6);
    return;
  }
  // Reproduce
  if(r.hunger < 50 && r.reproductionCooldown <= 0) {
    if(Math.random() < RABBIT_REPRO_CHANCE) {
      spawnBabyAnimal("Rabbit", r.x, r.y);
      r.reproductionCooldown = RABBIT_REPRO_COOLDOWN;
    }
  }
  if(r.hunger > 50) {
    let tree = findNearestResourceOfType(r, "FruitTree");
    if(tree) {
      moveToward(r, tree.x, tree.y, 0.4);
      if(distance(r.x, r.y, tree.x, tree.y) < 10) {
        if(tree.amount > 0) {
          tree.amount--;
          r.hunger -= 2;
          if(r.hunger < 0) r.hunger = 0;
          if(Math.random() < 0.02) logAction("A rabbit is eating fruit...");
        }
      }
    } else {
      randomAnimalWander(r);
    }
  } else {
    randomAnimalWander(r);
  }
}

/**********************************************************************
 * TASKS & AI LOGIC
 **********************************************************************/
function assignNewTask(cit) {
  // Check for critical needs first
  if(cit.hunger >= HUNGER_THRESHOLD) {
    let houseWithFruit = findHouseWithFruit();
    if(houseWithFruit) {
      cit.task = "eatAtHouse";
      cit.target = houseWithFruit;
      return;
    }
  }
  
  if(cit.energy <= ENERGY_THRESHOLD) {
    let compHouse = findAnyCompletedHouse();
    if(compHouse) {
      cit.task = "restAtHouse";
      cit.target = compHouse;
      return;
    }
  }
  
  if(cit.health <= HEALTH_THRESHOLD) {
    let hospital = findCompletedHospital();
    if(hospital) {
      cit.task = "visitHospital";
      cit.target = hospital;
      return;
    }
  }
  
  // For soldiers, check for wolves to hunt
  if(cit.profession === "Soldier") {
    let nearbyWolf = findNearestAnimalOfType(cit, "Wolf");
    if(nearbyWolf && distance(cit.x, cit.y, nearbyWolf.x, nearbyWolf.y) < 300) {
      cit.task = "huntWolf";
      cit.target = nearbyWolf;
      return;
    }
  }
  
  // Profession-specific tasks
  switch(cit.profession) {
    case "Builder":
      builderTasks(cit);
      break;
    case "Farmer":
      farmerTasks(cit);
      break;
    case "Merchant":
      merchantTasks(cit);
      break;
    case "Doctor":
      doctorTasks(cit);
      break;
    case "Teacher":
      teacherTasks(cit);
      break;
    case "Soldier":
      soldierTasks(cit);
      break;
    default:
      cit.task = null;
      cit.target = null;
  }
}

function builderTasks(cit) {
  let buildingNeedingWood = buildings.find(b => !b.completed && b.deliveredWood < b.requiredWood);
  if(buildingNeedingWood) {
    if(cit.carryingWood > 0) {
      cit.task = "deliverWood";
      cit.target = buildingNeedingWood;
      return;
    }
    let tree = findNearestResourceOfType(cit, "Tree");
    if(tree) {
      cit.task = "chop";
      cit.target = tree;
      return;
    }
  }
  
  let buildingToConstruct = buildings.find(b => !b.completed && b.deliveredWood >= b.requiredWood);
  if(buildingToConstruct) {
    cit.task = "build";
    cit.target = buildingToConstruct;
    return;
  }
  
  let anyTree = findNearestResourceOfType(cit, "Tree");
  if(anyTree) {
    cit.task = "chop";
    cit.target = anyTree;
    return;
  }
  
  cit.task = null;
  cit.target = null;
}

function farmerTasks(cit) {
  if(cit.carryingFruit > 0) {
    let houseNeedFruit = findHouseNeedingFruit();
    if(houseNeedFruit) {
      cit.task = "deliverFruit";
      cit.target = houseNeedFruit;
      return;
    }
  }
  
  let fruitTree = findNearestResourceOfType(cit, "FruitTree");
  if(fruitTree && fruitTree.amount > 0) {
    cit.task = "gatherFruit";
    cit.target = fruitTree;
    return;
  }
  
  if(cit.carryingFruit >= FRUIT_PLANT_COST && Math.random() < 0.1) {
    cit.task = "plantFruitTree";
    cit.target = null;
    return;
  }
  
  cit.task = null;
  cit.target = null;
}

function merchantTasks(cit) {
  let market = findCompletedMarket();
  if(market) {
    cit.task = "sellGoods";
    cit.target = market;
    return;
  }
  
  // If no market, help with gathering resources
  if(Math.random() < 0.5) {
    farmerTasks(cit);
  } else {
    builderTasks(cit);
  }
}

function doctorTasks(cit) {
  let hospital = findCompletedHospital();
  if(hospital) {
    cit.task = "treatPatients";
    cit.target = hospital;
    return;
  }
  
  // If no hospital, help with gathering resources
  builderTasks(cit);
}

function teacherTasks(cit) {
  let school = findCompletedSchool();
  if(school) {
    cit.task = "teachStudents";
    cit.target = school;
    return;
  }
  
  // If no school, help with gathering resources
  builderTasks(cit);
}

function soldierTasks(cit) {
  // Patrol around the city center
  if(Math.random() < 0.1) {
    cit.task = "patrol";
    cit.target = {
      x: randInt(-200, 200),
      y: randInt(-200, 200)
    };
    return;
  }
  
  // Help with building when not patrolling
  builderTasks(cit);
}

/**********************************************************************
 * NEW TASK HANDLERS
 **********************************************************************/
function huntWolfTask(cit) {
  let wolf = cit.target;
  if(!wolf || wolf.dead) {
    cit.task = null;
    cit.target = null;
    return;
  }
  
  moveToward(cit, wolf.x, wolf.y, 0.5);
  
  // Attack if close enough
  if(distance(cit.x, cit.y, wolf.x, wolf.y) < 20) {
    wolf.dead = true;
    logAction(`${cit.name} [Soldier] killed a wolf!`);
    cit.task = null;
    cit.target = null;
  }
}

function patrolTask(cit) {
  let target = cit.target;
  if(!target) {
    cit.task = null;
    return;
  }
  
  moveToward(cit, target.x, target.y, 0.3);
  
  // When reached patrol point, find a new task
  if(distance(cit.x, cit.y, target.x, target.y) < 10) {
    cit.task = null;
    cit.target = null;
  }
}
function treatPatientsTask(cit) {
  let hospital = cit.target;
  if(!hospital || !hospital.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  
  moveToward(cit, hospital.x, hospital.y, 0.3);
  if(distance(cit.x, cit.y, hospital.x, hospital.y) < 20) {
    // Generate medicine
    if(frameCount % 100 === 0) {
      if(hospital.medicine < hospital.maxMedicine) {
        hospital.medicine++;
        cityStorage.medicine++;
        if(Math.random() < 0.1) {
          logAction(`${cit.name} [Doctor] created medicine at the hospital.`);
        }
      }
    }
  }
}

function teachStudentsTask(cit) {
  let school = cit.target;
  if(!school || !school.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  
  moveToward(cit, school.x, school.y, 0.3);
  if(distance(cit.x, cit.y, school.x, school.y) < 20) {
    // Generate knowledge
    if(frameCount % 100 === 0) {
      if(school.knowledge < school.maxKnowledge) {
        school.knowledge++;
        cityStorage.knowledge++;
        if(Math.random() < 0.1) {
          logAction(`${cit.name} [Teacher] is teaching at the school.`);
        }
      }
    }
  }
}

function sellGoodsTask(cit) {
  let market = cit.target;
  if(!market || !market.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  
  moveToward(cit, market.x, market.y, 0.3);
  if(distance(cit.x, cit.y, market.x, market.y) < 20) {
    // Generate income occasionally
    if(frameCount % 200 === 0 && Math.random() < 0.3) {
      let income = randInt(5, 15);
      addMoney(income, "Market sales");
      if(Math.random() < 0.1) {
        logAction(`${cit.name} [Merchant] made $${income} at the market.`);
      }
    }
  }
}

function visitHospitalTask(cit) {
  let hospital = cit.target;
  if(!hospital || !hospital.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  
  moveToward(cit, hospital.x, hospital.y, 0.4);
  if(distance(cit.x, cit.y, hospital.x, hospital.y) < 20) {
    if(hospital.medicine > 0 && cit.health < HEALTH_MAX) {
      hospital.medicine--;
      cit.health += 20;
      if(cit.health > HEALTH_MAX) cit.health = HEALTH_MAX;
      logAction(`${cit.name} received medical treatment. Health: ${Math.floor(cit.health)}`);
    }
    cit.task = null;
    cit.target = null;
  }
}

function visitSchoolTask(cit) {
  let school = cit.target;
  if(!school || !school.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  
  moveToward(cit, school.x, school.y, 0.4);
  if(distance(cit.x, cit.y, school.x, school.y) < 20) {
    if(school.knowledge > 0 && cit.education < EDUCATION_MAX) {
      school.knowledge--;
      cit.education += 10;
      if(cit.education > EDUCATION_MAX) cit.education = EDUCATION_MAX;
      logAction(`${cit.name} learned at school. Education: ${Math.floor(cit.education)}`);
    }
    cit.task = null;
    cit.target = null;
  }
}

/**********************************************************************
 * EXISTING TASK HANDLERS
 **********************************************************************/
function chopTask(cit) {
  let tree = cit.target;
  if(!tree || tree.amount <= 0) {
    cit.task = null;
    cit.target = null;
    return;
  }
  
  // Check for nearby wolves and run if not a soldier
  if(cit.profession !== "Soldier") {
    let nearbyWolf = findNearestAnimalOfType(cit, "Wolf");
    if(nearbyWolf && distance(cit.x, cit.y, nearbyWolf.x, nearbyWolf.y) < 100) {
      // Run away from wolf
      moveAway(cit, nearbyWolf.x, nearbyWolf.y, 0.6);
      if(Math.random() < 0.1) {
        logAction(`${cit.name} is running away from a wolf!`);
      }
      return;
    }
  }
  moveToward(cit, tree.x, tree.y, 0.4);
  if(distance(cit.x, cit.y, tree.x, tree.y) < 10) {
    let canGather = cit.carryingCapacity - cit.carryingWood;
    let toGather = Math.min(1, tree.amount, canGather);
    tree.amount -= toGather;
    cit.carryingWood += toGather;
    if(Math.random() < 0.01) {
      logAction(`${cit.name}[${cit.profession}] chopping wood...`);
    }
    if(cit.carryingWood >= cit.carryingCapacity || tree.amount <= 0) {
      cit.task = null;
      cit.target = null;
    }
  }
}

function deliverWoodTask(cit) {
  let b = cit.target;
  if(!b || b.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  moveToward(cit, b.x, b.y, 0.4);
  if(distance(cit.x, cit.y, b.x, b.y) < 20) {
    let needed = b.requiredWood - b.deliveredWood;
    if(needed > 0 && cit.carryingWood > 0) {
      let toDeliver = Math.min(cit.carryingWood, needed);
      b.deliveredWood += toDeliver;
      cit.carryingWood -= toDeliver;
      logAction(`${cit.name} delivered ${toDeliver} wood to ${b.buildingType}.`);
      addMoney(REWARD_DELIVER_WOOD, "deliver wood");
    }
    cit.task = null;
    cit.target = null;
  }
}

function buildTask(cit) {
  let b = cit.target;
  if(!b || b.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  moveToward(cit, b.x, b.y, 0.3);
}

function gatherFruitTask(cit) {
  let tree = cit.target;
  if(!tree || tree.amount <= 0) {
    cit.task = null;
    cit.target = null;
    return;
  }
  moveToward(cit, tree.x, tree.y, 0.4);
  if(distance(cit.x, cit.y, tree.x, tree.y) < 10) {
    let canGather = cit.carryingCapacity - cit.carryingFruit;
    let toGather = Math.min(FRUIT_GATHER_RATE, tree.amount, canGather);
    tree.amount -= toGather;
    cit.carryingFruit += toGather;
    cityStorage.food += toGather / 2; // Half goes to city storage
    if(Math.random() < 0.01) {
      logAction(`${cit.name} [${cit.profession}] is gathering fruit...`);
    }
    if(cit.carryingFruit >= cit.carryingCapacity || tree.amount <= 0) {
      cit.task = null;
      cit.target = null;
    }
  }
}

function deliverFruitTask(cit) {
  let house = cit.target;
  if(!house || !house.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  moveToward(cit, house.x, house.y, 0.4);
  if(distance(cit.x, cit.y, house.x, house.y) < 20) {
    let space = house.maxFruit - house.storedFruit;
    if(space > 0 && cit.carryingFruit > 0) {
      let toDeliver = Math.min(cit.carryingFruit, space);
      house.storedFruit += toDeliver;
      cit.carryingFruit -= toDeliver;
      logAction(`${cit.name} delivered ${toDeliver} fruit to house.`);
    }
    cit.task = null;
    cit.target = null;
  }
}

function plantFruitTreeTask(cit) {
  // Try to find a valid land position nearby
  let px, py;
  let attempts = 0;
  do {
    px = cit.x + randInt(-50, 50);
    py = cit.y + randInt(-50, 50);
    attempts++;
    // Give up after too many attempts and find a new task
    if (attempts > 20) {
      cit.task = null;
      cit.target = null;
      return;
    }
  } while (!isValidPlacement(px, py));
  
  moveToward(cit, px, py, 0.4);
  if(distance(cit.x, cit.y, px, py) < 10) {
    if(cit.carryingFruit >= FRUIT_PLANT_COST) {
      cit.carryingFruit -= FRUIT_PLANT_COST;
      resources.push(createResource("FruitTree", px, py, FRUIT_TREE_START_AMOUNT));
      logAction(`${cit.name}[${cit.profession}] planted a new fruit tree!`);
    }
    cit.task = null;
    cit.target = null;
  }
}

function eatAtHouseTask(cit) {
  let house = cit.target;
  if(!house || !house.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  moveToward(cit, house.x, house.y, 0.4);
  if(distance(cit.x, cit.y, house.x, house.y) < 20) {
    if(house.storedFruit > 0 && cit.hunger > 0) {
      let amtToEat = 10;
      let eaten = Math.min(amtToEat, house.storedFruit);
      house.storedFruit -= eaten;
      cit.hunger -= eaten;
      if(cit.hunger < 0) cit.hunger = 0;
      logAction(`${cit.name} ate ${eaten} fruit. Hunger => ${Math.floor(cit.hunger)}.`);
    }
    cit.task = null;
    cit.target = null;
  }
}

function restAtHouseTask(cit) {
  let house = cit.target;
  if(!house || !house.completed) {
    cit.task = null;
    cit.target = null;
    return;
  }
  moveToward(cit, house.x, house.y, 0.4);
  if(distance(cit.x, cit.y, house.x, house.y) < 20) {
    if(cit.energy >= ENERGY_MAX - 1) {
      cit.energy = ENERGY_MAX;
      cit.task = null;
      cit.target = null;
    }
  }
}

/**********************************************************************
 * RANDOM WANDER
 **********************************************************************/
function randomWander(cit) {
  if(Math.random() < 0.01) {
    cit.vx = (Math.random() - 0.5) * 0.3;
    cit.vy = (Math.random() - 0.5) * 0.3;
  }
}

function randomAnimalWander(a) {
  if(Math.random() < 0.01) {
    a.vx = (Math.random() - 0.5) * 0.4;
    a.vy = (Math.random() - 0.5) * 0.4;
  }
}

function moveAway(obj, tx, ty, speed=0.4) {
  let dx = obj.x - tx;
  let dy = obj.y - ty;
  let dist = Math.sqrt(dx*dx + dy*dy);
  
  // Apply water movement penalty if in water
  let actualSpeed = speed;
  if (isWater(obj.x, obj.y)) {
    actualSpeed *= WATER_MOVEMENT_PENALTY;
  }
  
  if(dist > 1) {
    obj.vx = (dx/dist) * actualSpeed;
    obj.vy = (dy/dist) * actualSpeed;
  } else {
    obj.vx = (Math.random() - 0.5) * actualSpeed;
    obj.vy = (Math.random() - 0.5) * actualSpeed;
  }
}