import datetime

# ═════════════════════════════════════════════
# Animal class
# ═════════════════════════════════════════════

class Animal:
    def __init__(self, id, name, species, size, health, age):
        self.id      = id
        self.name    = name
        self.species = species
        self.size    = size
        self.health  = health
        self.age     = age
        self.status  = "available"

    def __str__(self):
        return f"[{self.id}] {self.name} | {self.species} | {self.size} | {self.health} | age: {self.age} | {self.status}"


# ═════════════════════════════════════════════
# Shelter class
# ═════════════════════════════════════════════

class Shelter:
    def __init__(self, name):
        self.name             = name
        self.animals          = {}
        self.adopted          = {}
        self.filename         = f"{name}.txt"
        self.adopted_filename = f"{name}_adopted.txt"

    def __str__(self):
        available = sum(1 for a in self.animals.values() if a.status == "available")
        adopted   = sum(1 for a in self.animals.values() if a.status == "adopted")
        return f"{self.name} — {available} available, {adopted} adopted"

    def __len__(self):
        return len(self.animals)

    # ─────────────────────────────────────────
    # Load from files
    # ─────────────────────────────────────────

    def load(self):
        self.animals = {}
        self.adopted = {}

        try:
            with open(self.filename, "r", encoding="utf-8") as f:
                for line in f:
                    row = line.strip().split(";")
                    animal = Animal(int(row[0]), row[1], row[2], row[3], row[4], int(row[5]))
                    animal.status = row[6]
                    self.animals[animal.id] = animal
        except FileNotFoundError:
            pass

        try:
            with open(self.adopted_filename, "r", encoding="utf-8") as f:
                for line in f:
                    row = line.strip().split(";")
                    self.adopted[int(row[0])] = [row[1], row[2], row[3]]
        except FileNotFoundError:
            pass

    # ─────────────────────────────────────────
    # Get next incremental ID
    # ─────────────────────────────────────────

    def get_next_id(self):
        if not self.animals:
            return 1
        all_ids = []
        for key in self.animals:
            all_ids.append(key)
        return max(all_ids) + 1

    # ─────────────────────────────────────────
    # Add paw
    # ─────────────────────────────────────────

    def add_paw(self):
        name = ""
        while not name:
            name = input("Paw name: ")

        specie = ""
        while not specie:
            specie = input("Paw specie: ")

        size = ""
        while not size or size.lower() not in ["small", "medium", "big"]:
            size = input("Paw size (small/medium/big only): ")
        size = size.lower()

        health = ""
        while not health or health.lower() not in ["healthy", "ill"]:
            health = input("Paw health status (healthy/ill only): ")
        health = health.lower()

        while True:
            try:
                age = int(input("Paw age: "))
                if age > 0:
                    break
                print("Paw age must be greater than 0.")
            except ValueError:
                print("Invalid paw age. Enter a number.")

        id     = self.get_next_id()
        animal = Animal(id, name, specie, size, health, age)
        self.animals[id] = animal

        with open(self.filename, "a", encoding="utf-8") as f:
            f.write(f"{id};{name};{specie};{size};{health};{age};available\n")
        self.load()

    # ─────────────────────────────────────────
    # Advanced search
    # ─────────────────────────────────────────

    def adv_search(self):
        specie = input("Searched specie (0 for all): ").strip()

        size = ""
        while not size or size.lower() not in ["small", "medium", "big", "0"]:
            size = input("Searched size (small/medium/big, 0 for all): ")
        size = size.lower()

        while True:
            try:
                age = int(input("Searched max age (0 for all): "))
                if age >= 0:
                    break
                print("Age must be 0 or greater.")
            except ValueError:
                print("Invalid age. Enter a number.")

        results = {}
        for id, animal in self.animals.items():
            if animal.status == "available":
                if specie == "0" or animal.species == specie:
                    if size == "0" or animal.size == size:
                        if age == 0 or animal.age <= age:
                            results[id] = animal
        return results

    def print_adv_search(self):
        results = self.adv_search()
        for id, animal in results.items():
            print(animal)

    # ─────────────────────────────────────────
    # Edit health
    # ─────────────────────────────────────────

    def edit_health(self):
        available = {id: a for id, a in self.animals.items() if a.status == "available"}
        adopted   = {id: a for id, a in self.animals.items() if a.status == "adopted"}

        editable = False

        while True:
            try:
                id = int(input("Paw id: "))
                if id in available:
                    print(f"Paw identified: {available[id].name}")
                    editable = True
                    break
                elif id in adopted:
                    print(f"{adopted[id].name} is adopted. You can't edit an adopted paw!")
                    break
            except ValueError:
                print("Invalid ID. Enter a number.")

        if editable:
            health = ""
            while not health or health.lower() not in ["healthy", "ill"]:
                health = input("Paw health status update (healthy/ill only): ")
            self.animals[id].health = health.lower()
            print(f"{self.animals[id].name.upper()} was successfully updated. New health status is: {self.animals[id].health.upper()}.")

            with open(self.filename, "w", encoding="utf-8") as f:
                for animal in self.animals.values():
                    f.write(f"{animal.id};{animal.name};{animal.species};{animal.size};{animal.health};{animal.age};{animal.status}\n")
            self.load()

    # ─────────────────────────────────────────
    # Register adoption
    # ─────────────────────────────────────────

    def paw_adopted(self):
        available = {id: a for id, a in self.animals.items() if a.status == "available"}
        adopted   = {id: a for id, a in self.animals.items() if a.status == "adopted"}

        while True:
            try:
                id = int(input("Adopted paw id: "))
                if id in available:
                    owner_name = ""
                    while not owner_name:
                        owner_name = input("New owner name: ")

                    owner_contact = ""
                    while not owner_contact:
                        owner_contact = input("New owner contact: ")

                    adoption_date = datetime.date.today().strftime("%Y-%m-%d")

                    with open(self.adopted_filename, "a", encoding="utf-8") as f:
                        f.write(f"{id};{owner_name};{owner_contact};{adoption_date}\n")

                    self.animals[id].status = "adopted"
                    print(f"Great! {self.animals[id].name.upper()} has a new home.")

                    with open(self.filename, "w", encoding="utf-8") as f:
                        for animal in self.animals.values():
                            f.write(f"{animal.id};{animal.name};{animal.species};{animal.size};{animal.health};{animal.age};{animal.status}\n")
                    self.load()
                    break

                elif id in adopted:
                    print(f"{adopted[id].name.upper()} was already adopted.")
                    break

            except ValueError:
                print("Invalid ID. Enter a number.")

    # ─────────────────────────────────────────
    # Activity report
    # ─────────────────────────────────────────

    def activity_report(self):
        def get_date(item):
            return item[1][2]

        sorted_items   = sorted(self.adopted.items(), key=get_date)
        sorted_adopted = dict(sorted_items)

        report_date = datetime.date.today().strftime("%Y-%m-%d")
        filename    = f"{self.name}_activity_report_{report_date}.txt"

        with open(filename, "w", encoding="utf-8") as f:
            f.write("=" * 20 + "\n")
            f.write("Adopted paws\n")
            f.write("=" * 20 + "\n")
            for id, record in sorted_adopted.items():
                animal_name = self.animals[id].name
                f.write(f"{record[2]} - {animal_name}, adopted by {record[0]} ({record[1]})\n")
            f.write("=" * 20 + "\n")
            f.write("Available paws\n")
            f.write("=" * 20 + "\n")
            for id, animal in self.animals.items():
                if animal.status == "available":
                    f.write(f"{animal.name}, a {animal.age} years old, {animal.size} sized {animal.species}.\n")

        print(f"Report saved: {filename}")


# ═════════════════════════════════════════════
# Menu
# ═════════════════════════════════════════════

shelter = Shelter("safe_paws")
shelter.load()

print(shelter)

while True:
    print("\nSafe Paws Menu")
    option = input("1-Add paw\n2-Adv search\n3-Edit paw health\n4-Register adoption\n5-Activity report\nq-Quit\nChoose your option: ")
    if option == "1":
        shelter.add_paw()
        print("Paw added successfully!")
    elif option == "2":
        if len(shelter.adv_search()) > 0:
            shelter.print_adv_search()
        else:
            print("No data match your search.")
    elif option == "3":
        shelter.edit_health()
    elif option == "4":
        shelter.paw_adopted()
    elif option == "5":
        shelter.activity_report()
    elif option == "q":
        break
    else:
        print("Invalid option!")
