package com.yanzhu.module.ai.tool.method;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
// import com.yanzhu.module.ai.tool.pojo.Person;
import javax.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Implementation of the PersonService interface providing CRUD operations for Person entities.
 * This service uses an in-memory data store for simplicity.
 */
@Slf4j
@Service
public class PersonServiceImpl implements PersonService {

    private final Map<Integer, Person> personStore = new HashMap<>();
    private AtomicInteger idGenerator;

    /**
     * Embedded CSV data for initial population
     */
    private static final String CSV_DATA = "Id,FirstName,LastName,Email,Sex,IpAddress,JobTitle,Age\n" +
            "1,Fons,Tollfree,ftollfree0@senate.gov,Male,55.1 Tollfree Lane,Research Associate,31\n" +
            "2,Emlynne,Tabourier,etabourier1@networksolutions.com,Female,18 Tabourier Way,Associate Professor,38\n" +
            "3,Shae,Johncey,sjohncey2@yellowpages.com,Male,1 Johncey Circle,Structural Analysis Engineer,30\n" +
            "4,Sebastien,Bradly,sbradly3@mapquest.com,Male,2 Bradly Hill,Chief Executive Officer,40\n" +
            "5,Harriott,Kitteringham,hkitteringham4@typepad.com,Female,3 Kitteringham Drive,VP Sales,47\n" +
            "6,Anallise,Parradine,aparradine5@miibeian.gov.cn,Female,4 Parradine Street,Analog Circuit Design manager,44\n" +
            "7,Gorden,Kirkbright,gkirkbright6@reuters.com,Male,5 Kirkbright Plaza,Senior Editor,40\n" +
            "8,Veradis,Ledwitch,vledwitch7@google.com.au,Female,6 Ledwitch Avenue,Computer Systems Analyst IV,44\n" +
            "9,Agnesse,Penhalurick,apenhalurick8@google.it,Female,7 Penhalurick Terrace,Automation Specialist IV,41\n" +
            "10,Bibby,Hutable,bhutable9@craigslist.org,Female,8 Hutable Place,Account Representative I,43\n" +
            "11,Karoly,Lightoller,klightollera@rakuten.co.jp,Female,9 Lightoller Parkway,Senior Developer,46\n" +
            "12,Cristine,Durrad,cdurradb@aol.com,Female,10 Durrad Center,Senior Developer,48\n" +
            "13,Aggy,Napier,anapierc@hostgator.com,Female,11 Napier Court,VP Product Management,44\n" +
            "14,Prisca,Caddens,pcaddensd@vinaora.com,Female,12 Caddens Alley,Business Systems Development Analyst,41\n" +
            "15,Khalil,McKernan,kmckernane@google.fr,Male,13 McKernan Pass,Engineer IV,44\n" +
            "16,Lorry,MacTrusty,lmactrustyf@eventbrite.com,Male,14 MacTrusty Junction,Design Engineer,42\n" +
            "17,Casandra,Worsell,cworsellg@goo.gl,Female,15 Worsell Point,Systems Administrator IV,45\n" +
            "18,Janene,Pennie,jpennieh@cdbaby.com,Female,16 Pennie Circle,Accountant IV,47\n" +
            "19,Nananne,Elwell,nelwelli@cloudflare.com,Female,17 Elwell Road,Accountant III,43\n" +
            "20,Janetta,Blundell,jblundellj@amazon.co.uk,Female,18 Blundell Street,Research Associate,39";

    /**
     * Initializes the service by loading data from the embedded CSV string.
     */
    @PostConstruct
    public void init() {
        int maxId = loadDataFromCsv();
        idGenerator = new AtomicInteger(maxId);
    }

    /**
     * Loads person data from the embedded CSV string into the in-memory store.
     *
     * @return the maximum ID found in the CSV data
     */
    private int loadDataFromCsv() {
        int maxId = 0;
        try (BufferedReader reader = new BufferedReader(new StringReader(CSV_DATA))) {
            String line;
            boolean isHeader = true;
            while ((line = reader.readLine()) != null) {
                if (isHeader) {
                    isHeader = false;
                    continue;
                }
                String[] fields = line.split(",");
                if (fields.length != 8) {
                    log.warn("Skipping invalid CSV line: {}", line);
                    continue;
                }
                try {
                    Person person = new Person();
                    person.setId(Integer.parseInt(fields[0]));
                    person.setFirstName(fields[1]);
                    person.setLastName(fields[2]);
                    person.setEmail(fields[3]);
                    person.setSex(fields[4]);
                    person.setIpAddress(fields[5]);
                    person.setJobTitle(fields[6]);
                    person.setAge(Integer.parseInt(fields[7]));
                    personStore.put(person.getId(), person);
                    if (person.getId() > maxId) {
                        maxId = person.getId();
                    }
                } catch (NumberFormatException e) {
                    log.warn("Skipping CSV line with invalid number format: {}", line);
                }
            }
        } catch (IOException e) {
            log.error("Error loading data from CSV string", e);
        }
        return maxId;
    }

    /**
     * Retrieves a Person by their unique ID.
     *
     * @param id The ID of the person to retrieve.
     * @return An Optional containing the found Person, or an empty Optional if not found.
     */
    @Override
    public java.util.Optional<Person> getPersonById(int id) {
        return java.util.Optional.ofNullable(personStore.get(id));
    }

    /**
     * Retrieves all Person records currently stored.
     *
     * @return An unmodifiable List containing all Persons. Returns an empty list if none exist.
     */
    @Override
    public List<Person> getAllPersons() {
        return new ArrayList<>(personStore.values());
    }

    /**
     * Creates a new Person record.
     * Assigns a unique ID to the person and stores it.
     *
     * @param personData The data for the new person (ID field is ignored). Must not be null.
     * @return The created Person record, including the generated ID.
     */
    @Override
    public Person createPerson(Person personData) {
        Person person = new Person();
        person.setId(idGenerator.incrementAndGet());
        person.setFirstName(personData.getFirstName());
        person.setLastName(personData.getLastName());
        person.setEmail(personData.getEmail());
        person.setSex(personData.getSex());
        person.setIpAddress(personData.getIpAddress());
        person.setJobTitle(personData.getJobTitle());
        person.setAge(personData.getAge());
        personStore.put(person.getId(), person);
        return person;
    }

    /**
     * Updates an existing Person record identified by ID.
     * Replaces the existing data with the provided data, keeping the original ID.
     *
     * @param id                The ID of the person to update.
     * @param updatedPersonData The new data for the person (ID field is ignored). Must not be null.
     * @return true if the person was found and updated, false otherwise.
     */
    @Override
    public boolean updatePerson(int id, Person updatedPersonData) {
        if (personStore.containsKey(id)) {
            Person person = personStore.get(id);
            person.setFirstName(updatedPersonData.getFirstName());
            person.setLastName(updatedPersonData.getLastName());
            person.setEmail(updatedPersonData.getEmail());
            person.setSex(updatedPersonData.getSex());
            person.setIpAddress(updatedPersonData.getIpAddress());
            person.setJobTitle(updatedPersonData.getJobTitle());
            person.setAge(updatedPersonData.getAge());
            personStore.put(id, person);
            return true;
        }
        return false;
    }

    /**
     * Deletes a Person record identified by ID.
     *
     * @param id The ID of the person to delete.
     * @return true if the person was found and deleted, false otherwise.
     */
    @Override
    public boolean deletePerson(int id) {
        return personStore.remove(id) != null;
    }

    /**
     * Searches for Persons whose job title contains the given query string (case-insensitive).
     *
     * @param jobTitleQuery The string to search for within job titles. Can be null or blank.
     * @return An unmodifiable List of matching Persons. Returns an empty list if no matches or query is invalid.
     */
    @Override
    public List<Person> searchByJobTitle(String jobTitleQuery) {
        List<Person> result = new ArrayList<>();
        if (jobTitleQuery == null || jobTitleQuery.trim().isEmpty()) {
            return result;
        }
        String query = jobTitleQuery.toLowerCase();
        for (Person person : personStore.values()) {
            if (person.getJobTitle().toLowerCase().contains(query)) {
                result.add(person);
            }
        }
        return result;
    }

    /**
     * Filters Persons by their exact sex (case-insensitive).
     *
     * @param sex The sex to filter by (e.g., "Male", "Female"). Can be null or blank.
     * @return An unmodifiable List of matching Persons. Returns an empty list if no matches or filter is invalid.
     */
    @Override
    public List<Person> filterBySex(String sex) {
        List<Person> result = new ArrayList<>();
        if (sex == null || sex.trim().isEmpty()) {
            return result;
        }
        String targetSex = sex.toLowerCase();
        for (Person person : personStore.values()) {
            if (person.getSex().toLowerCase().equals(targetSex)) {
                result.add(person);
            }
        }
        return result;
    }

    /**
     * Filters Persons by their exact age.
     *
     * @param age The age to filter by.
     * @return An unmodifiable List of matching Persons. Returns an empty list if no matches.
     */
    @Override
    public List<Person> filterByAge(int age) {
        List<Person> result = new ArrayList<>();
        for (Person person : personStore.values()) {
            if (person.getAge() == age) {
                result.add(person);
            }
        }
        return result;
    }

}
