<?php

if (!defined('CPR_API_KEY')) {
    die('CPR API key not configured in wp-config.php');
}

// ===========================================================================================================
// Public functions:
// ===========================================================================================================
// generatePage( animalID )  - generates a detail page for a dog, routing to CPR or SOS based on status
// getSOSDetail( animalID )  - fetches detail and parses description for SOS dogs
// getCPRDetail( animalID )  - fetches detail and parses description for CPR dogs
// getSOSList()              - get a list of SOS dogs - returns an array of dogs
// getCPRList()              - get a list of CPR dogs for adoption - returns an array
// getSize(maxSize, x, y)    - returns image size based on ratio scaling largest dim to maxSize
// filterSOSName(name)       - strips the SOS prefix from an animal name
// debugObject(variable)     - dumps the contents of a variable to the screen
// ===========================================================================================================

define('CPR_API_URL', 'https://api.rescuegroups.org/http/json');

// CPR_CACHE_TTL can be overridden in wp-config.php (set to 1 to disable caching on dev)
if (!defined('CPR_CACHE_TTL')) {
    define('CPR_CACHE_TTL', 5 * 60); // default 5 minutes
}

// Placeholder image shown when a dog has no photos
define('CPR_PLACEHOLDER_IMG', 'https://via.placeholder.com/400x400?text=No+Photo+Available');

// ===========================================================================================================
// Generates a detail page for a dog, routing to CPR or SOS description parser based on status
// ===========================================================================================================
function generatePage($animalID) {
    $result = getDetail($animalID);
    if (!$result) return false;

    $animal = $result['data'][$animalID];

    if ($animal['animalStatus'] == 'Available') {
        $result['data'][$animalID]['sections'] = getCPRDesc($animal['animalDescriptionPlain'], [
            'name'   => $animal['animalName'],
            'gender' => $animal['animalSex'],
            'breed'  => $animal['animalBreed'],
            'bdate'  => $animal['animalBirthdate'],
        ]);
    } else {
        $result['data'][$animalID]['sections'] = getSOSDesc(
            $animal['animalDescriptionPlain'],
            $animal['animalSex'],
            $animal['animalBirthdate']
        );
    }

    return $result;
}

// ===========================================================================================================
// Fetches animal detail and parses description for SOS dogs
// ===========================================================================================================
function getSOSDetail($animalID) {
    $result = getDetail($animalID);
    if (!$result) return false;

    $animal = $result['data'][$animalID];

    $result['data'][$animalID]['sections'] = getSOSDesc(
        $animal['animalDescriptionPlain'],
        $animal['animalSex'],
        $animal['animalBirthdate']
    );

    return $result;
}

// ===========================================================================================================
// Fetches animal detail and parses description for CPR dogs
// ===========================================================================================================
function getCPRDetail($animalID) {
    $result = getDetail($animalID);
    if (!$result) return false;

    $animal = $result['data'][$animalID];

    $result['data'][$animalID]['sections'] = getCPRDesc($animal['animalDescriptionPlain'], [
        'name'   => $animal['animalName'],
        'gender' => $animal['animalSex'],
        'breed'  => $animal['animalBreed'],
        'bdate'  => $animal['animalBirthdate'],
    ]);

    return $result;
}

// ===========================================================================================================
// Fetches full detail for a single animal from the RescueGroups API
// ===========================================================================================================
function getDetail($animalID) {
    $cacheKey = 'cpr_animal_' . $animalID;
    $cached   = get_transient($cacheKey);
    if ($cached !== false) return $cached;

    $fields = [
        'animalID', 'animalActivityLevel', 'animalAdoptionFee', 'animalAltered',
        'animalBirthdate', 'animalBirthdateExact', 'animalGeneralAge', 'animalBreed',
        'animalColor', 'animalDescriptionPlain', 'animalEarType', 'animalEnergyLevel',
        'animalExerciseNeeds', 'animalGeneralSizePotential', 'animalGroomingNeeds',
        'animalIndoorOutdoor', 'animalLocationDistance', 'animalLocationCitystate',
        'animalName', 'animalOKWithCats', 'animalRescueID', 'animalSex',
        'animalShedding', 'animalStatus', 'animalTailType',
        'animalPictures', 'animalVideoUrls',
    ];

    $data = [
        'apikey'       => CPR_API_KEY,
        'objectType'   => 'animals',
        'objectAction' => 'publicSearch',
        'search'       => [
            'calcFoundRows' => 'Yes',
            'resultStart'   => 0,
            'resultLimit'   => 200,
            'resultSort'    => 'animalName',
            'fields'        => $fields,
            'filters'       => [[
                'fieldName' => 'animalID',
                'operation' => 'equal',
                'criteria'  => $animalID,
            ]],
        ],
    ];

    $result = postToApi($data);

    if (!$result) {
        error_log('CPR Rescue: API failure in getDetail() for animalID ' . $animalID);
        return false;
    }

    set_transient($cacheKey, $result, CPR_CACHE_TTL);
    return $result;
}

// ===========================================================================================================
// Returns a cached list of SOS dogs (status = Sponsorship)
// ===========================================================================================================
function getSOSList() {
    $cached = get_transient('cpr_sos_list');
    if ($cached !== false) return $cached;

    $result = getList([
        'fieldName' => 'animalStatus',
        'operation' => 'equal',
        'criteria'  => 'Sponsorship',
    ]);

    if (!$result) {
        error_log('CPR Rescue: API failure in getSOSList()');
        return false;
    }

    set_transient('cpr_sos_list', $result, CPR_CACHE_TTL);
    return $result;
}

// ===========================================================================================================
// Returns a cached list of CPR dogs available for adoption (status = Available)
// ===========================================================================================================
function getCPRList() {
    $cached = get_transient('cpr_cpr_list');
    if ($cached !== false) return $cached;

    $result = getList([
        'fieldName' => 'animalStatus',
        'operation' => 'equal',
        'criteria'  => ['Available'],
    ]);

    if (!$result) {
        error_log('CPR Rescue: API failure in getCPRList()');
        return false;
    }

    set_transient('cpr_cpr_list', $result, CPR_CACHE_TTL);
    return $result;
}

// ===========================================================================================================
// Fetches a list of animals from the API based on the provided filter
// ===========================================================================================================
function getList($filter) {
    $fields = [
        'animalID', 'animalName', 'animalSpecies', 'animalStatus',
        'animalRescueID', 'animalBreed', 'animalPictures', 'animalAdoptionFee',
    ];

    $data = [
        'apikey'       => CPR_API_KEY,
        'objectType'   => 'animals',
        'objectAction' => 'publicSearch',
        'search'       => [
            'calcFoundRows' => 'Yes',
            'resultStart'   => 0,
            'resultLimit'   => 200,
            'resultSort'    => 'animalName',
            'fields'        => $fields,
            'filters'       => [$filter],
        ],
    ];

    $result = postToApi($data);

    if (!$result) return false;

    return $result;
}

// ===========================================================================================================
// Strips unprintable characters from a line of text
// ===========================================================================================================
function sanitizeLine($line) {
    return preg_replace('/[^\x09\x0A\x0D\x20-\x7E]/', '', $line);
}

// ===========================================================================================================
// Parses the description for SOS dogs into sections: about, biography, sponsorship, more
// ===========================================================================================================
function getSOSDesc($desc, $gender, $birthdate) {
    $result = [
        'sponsorship' => '',
        'about'       => '',
        'biography'   => '',
    ];

    $about_rows = [];
    $section    = 0;

    foreach (preg_split('~[\r\n]+~', $desc) as $temp_line) {
        $line = sanitizeLine($temp_line);

        if (empty($line) || ctype_space($line))           { continue; }
        if (preg_match('/^Please note/i', $line))         { continue; }

        if (preg_match('/^All about me/i', $line))        { $section = 1; continue; }
        if (preg_match('/^Foster Home/i', $line))         { $section = 2; continue; }

        if (preg_match('/^Why am I with a rescue group\?/i', $line)) {
            $section = 3;
            $line = preg_replace('/Why am I with a rescue group\? /i', '', $line);
        }

        switch ($section) {
            case 1:
                $values = preg_split('/[:?]/', $line, 2);
                $label  = trim($values[0]);
                $value  = trim($values[1] ?? '');

                if (preg_match('/^Age$/i', $label)) {
                    $label = 'Estimated Birthdate';
                    $value = $birthdate;
                }

                $about_rows[$label] = $value;

                // Inject gender right after the Name row
                if (preg_match('/^Name$/i', $label)) {
                    $about_rows['Gender'] = $gender;
                }
                break;
            case 2:
                $result['sponsorship'] .= '<p>' . $line . "</p>\n";
                break;
            case 3:
                $result['biography'] .= '<p>' . $line . "</p>\n";
                break;
        }
    }

    // Build the about table
    $result['about'] = "<table class='cpr-about-table'>\n";
    foreach ($about_rows as $label => $value) {
        $result['about'] .= "  <tr>\n";
        $result['about'] .= "    <td><strong>{$label}:</strong></td>\n";
        $result['about'] .= "    <td>{$value}</td>\n";
        $result['about'] .= "  </tr>\n";
    }
    $result['about'] .= "</table>\n";

    $result['more']  = "<p>If you would like more information on this dog or any of our SOS dogs and our farm sanctuary for senior and special needs pets, please email info@carolinapoodlerescue.org or call 864-489-3559 and leave a message. We would love to tell you more about our assisted living facility for senior and special needs pets.</p>\n";
    $result['more'] .= "<p>Please note - we do not ship dogs. If you are interested in adopting, please take a look at the distance between the foster home location and your location and make sure you are willing to make that trip.</p>\n";

    return $result;
}

// ===========================================================================================================
// Parses the description for CPR dogs into sections: about, story, application, more
// ===========================================================================================================
function getCPRDesc($desc, $info) {
    $result = [
        'story'     => '',
        'about'     => '',
        'biography' => '',
    ];

    foreach (preg_split('~[\r\n]+~', $desc) as $temp_line) {
        $line = sanitizeLine($temp_line);

        if (empty($line) || ctype_space($line))              { continue; }
        if (preg_match('/^My age/i', $line))                 { continue; }
        if (preg_match('/^Want To Know More/i', $line))      { continue; }
        if (preg_match('/s Your Quick Peek:/i', $line))      { continue; }
        if (preg_match('/^[\s&]/', $line))                   { continue; }

        if (preg_match('/to 864-441-9075/i', $line)) {
            $info['text_us'] = $line;
            continue;
        }

        // Extract structured fields into $info
        $extractors = [
            '/^Date into Rescue/i'                          => ['key' => 'date_into_rescue', 'sep' => '/:\s+/'],
            '/^Reason for being in rescue/i'                => ['key' => 'reason_in_rescue', 'sep' => '/:\s+/'],
            '/^Special needs/i'                             => ['key' => 'special_needs',    'sep' => '/\?\s+/'],
            '/^What kind of home would be best for me/i'    => ['key' => 'home',             'sep' => '/[:\?]\s+/'],
            '/^What is my personality like/i'               => ['key' => 'personality',      'sep' => '/[:\?]\s+/'],
            '/^How do I act when I first meet new people/i' => ['key' => 'new_people',       'sep' => '/[:\?]\s+/'],
            '/^Other tips and tidbits/i'                    => ['key' => 'tidbits',          'sep' => '/[:\?]\s+/'],
            '/^House trained/i'                             => ['key' => 'house_trained',    'sep' => '/[:\?]\s+/'],
            '/^Adoption Fee[:\?]/i'                         => ['key' => 'adoptFee',         'sep' => '/[:\?]\s+/'],
            '/^Fence needed[?:]/i'                          => ['key' => 'fence',            'sep' => '/[?:]\s+/'],
            '/^Foster Location:/i'                          => ['key' => 'location',         'sep' => '/:\s+/'],
        ];

        foreach ($extractors as $pattern => $extractor) {
            if (preg_match($pattern, $line)) {
                $values = preg_split($extractor['sep'], $line, 2);
                $info[$extractor['key']] = $values[1] ?? '';
                if ($pattern === '/^Other tips and tidbits/i') {
                    $line = preg_replace('/^Other tips and tidbits/i', 'Tips and Tidbits', $line);
                }
            }
        }

        // Handle Weight and Height (can appear on same line)
        if (preg_match('/Weight:/i', $line)) {
            $values = preg_split('/: +/', $line);
            if (preg_match('/Height:/i', $values[1])) {
                $values2 = preg_split('/Height:/', $values[1]);
                $info['weight'] = $values2[0];
                $info['height'] = $values2[1];
                continue;
            } else {
                $info['weight'] = $values[1];
            }
        }

        if (preg_match('/Height:/i', $line)) {
            $values = preg_split('/: +/', $line);
            $info['height'] = $values[1];
        }

        // Skip lines that were extracted into $info above
        if (preg_match('/^Foster location/i', $line)) { continue; }
        if (preg_match('/^Weight/i',          $line)) { continue; }
        if (preg_match('/^Height/i',          $line)) { continue; }
        if (preg_match('/^Spaye/i',           $line)) {
            $values = preg_split('/:\s+/', $line, 2);
            $info['spayed'] = $values[1] ?? '';
            continue;
        }
        if (preg_match('/^Adoption Fee/i',    $line)) { continue; }
        if (preg_match('/^Fence Needed/i',    $line)) { continue; }

        // Bold any label at the start of the line and add to story
        $line = preg_replace('/^(.+)[:?]/', '<strong>${1}:</strong>', $line);
        $result['story'] .= $line . "<br><br>\n";
    }

    // Build the About table
    $about_rows = [
        'Name'               => $info['name']     ?? '',
        'Want to know more?' => $info['text_us']  ?? '',
        'Sex'                => $info['gender']   ?? '',
        'Spayed/ Neutered'   => $info['spayed']   ?? '',
        'Breed'              => $info['breed']    ?? '',
        'Weight'             => $info['weight']   ?? '',
        'Height'             => $info['height']   ?? '',
        'Estimated Birthdate' => $info['bdate']   ?? '',
        'Fence Needed'       => $info['fence']    ?? '',
        'Location'           => $info['location'] ?? '',
        'Adoption Fee'       => $info['adoptFee'] ?? '',
    ];

    $result['about'] = "<table class='cpr-about-table'>\n";
    foreach ($about_rows as $label => $value) {
        $result['about'] .= "  <tr>\n";
        $result['about'] .= "    <td><strong>{$label}:</strong></td>\n";
        $result['about'] .= "    <td>{$value}</td>\n";
        $result['about'] .= "  </tr>\n";
    }
    $result['about'] .= "</table>\n";

    $result['application']  = "<p>Please note - we do not ship or transport our dogs. If you are interested in adopting a dog, take a look at the distance between the dog's location and your location and make sure you are able to make the trip.</p>\n\n";
    $result['application'] .= "<p>Thank you for your interest in a dog who needs a new home. This description contains all that we currently know about this dog. We have no perfect dogs - but many of our dogs have proven to be perfect for a certain someone. We urge all of our potential adopters not to fall in love with a picture. When screening applications, we look at the entire home and then make suggestions based on what would be a good fit for your home. You are not being screened for a specific dog although we are looking to see what type of dog interests you - poodles or non poodles, age, temperament, personality, etc. Our goal is to match you with the best possible pet for you and your home. We want to create furever families.</p>\n\n";
    $result['application'] .= "<p>If you would like to receive our monthly newsletters and learn more about how to support dogs in need, please email info@carolinapoodlerescue.org or fill out our contact form and ask to join our mailing list.</p>\n\n";
    $result['application'] .= "<p>Thank you for considering CPR!</p>\n\n";

    $result['more']  = "<p>Please note - we do not ship dogs. If you are interested in adopting, please take a look at the distance between the foster home location and your location and make sure you are willing to make that trip. Most of our dogs are at our farm in Pacolet, South Carolina.</p>\n\n";
    $result['more'] .= "<p>To apply, please visit our webpage at www.carolinapoodlerescue.org and visit the tab on the left that directs you to the online application.</p>";
    $result['more'] .= "<p>Please note that when screening applications, we look at the entire home and then make suggestions based on what would be a good fit for your home. You are not being screened for a specific dog although we are looking to see what type of dog interests you - poodles or non poodles, color, age, etc. Others here may be a better fit for you. It is very difficult to get to know a living animal from a picture and a short description. Since we are constantly getting in new dogs, this may be a dog not in our listings yet. We want you to be very happy with your new companion and will make suggestions based on what you tell us about you.</p>";
    $result['more'] .= "<p>Thank you for considering CPR.</p>";

    return $result;
}

// ===========================================================================================================
// Computes scaled image dimensions preserving aspect ratio
// ===========================================================================================================
function getSize($maxSize, $x, $y) {
    if ($x < 1) $x = $maxSize;
    if ($y < 1) $y = $maxSize;

    if ($x > $y) {
        return [
            $maxSize,
            (int) ceil($maxSize * $y / $x),
        ];
    } else {
        return [
            (int) ceil($maxSize * $x / $y),
            $maxSize,
        ];
    }
}

// ===========================================================================================================
// Strips the SOS prefix from an animal name (everything after the first hyphen)
// ===========================================================================================================
function filterSOSName($name) {
    return preg_split('/-/', $name)[0];
}

// ===========================================================================================================
// Dumps the contents of any variable to the screen - for debugging only
// ===========================================================================================================
function debugObject($variable) {
    echo '<pre>';
    print_r($variable);
    echo '</pre>';
}

// ===========================================================================================================
// RescueGroups API functions
// Reference 1: https://userguide.rescuegroups.org/display/APIDG/Full+working+PHP+example
// Reference 2: https://userguide.rescuegroups.org/display/APIDG/v2
// ===========================================================================================================
function postJson($url, $json) {
    $response = wp_remote_post($url, [
        'headers' => ['Content-Type' => 'application/json'],
        'body'    => $json,
        'timeout' => 15,
    ]);

    if (is_wp_error($response)) {
        error_log('CPR Rescue: wp_remote_post error — ' . $response->get_error_message());
        return ['status' => 'error', 'error' => $response->get_error_message(), 'result' => ''];
    }

    return ['status' => 'ok', 'error' => '', 'result' => wp_remote_retrieve_body($response)];
}

function postToApi($data) {
    $resultJson = postJson(CPR_API_URL, json_encode($data));

    if ($resultJson['status'] !== 'ok') {
        return false;
    }

    $result    = json_decode($resultJson['result'], true);
    $jsonError = getJsonError();

    if ($jsonError) {
        error_log('CPR Rescue: JSON decode error — ' . $jsonError);
        return false;
    }

    return $result;
}

function getJsonError() {
    $errors = [
        JSON_ERROR_DEPTH          => 'Maximum stack depth exceeded',
        JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
        JSON_ERROR_CTRL_CHAR      => 'Unexpected control character found',
        JSON_ERROR_SYNTAX         => 'Syntax error, malformed JSON',
        JSON_ERROR_UTF8           => 'Malformed UTF-8 characters, possibly incorrectly encoded',
    ];

    $code = json_last_error();
    if ($code === JSON_ERROR_NONE) return false;
    return $errors[$code] ?? 'Unknown JSON error';
}
