<?php
require_once __DIR__ . '/common.php';

$dbconn = getDBConnection();

//no gets, current point outage info
if (empty(array_diff_key($_GET, array('service' => '')))) {
    try {
        $query = "
            SELECT json_build_object(
                'type', 'FeatureCollection',
                'features', json_agg(
                    json_build_object(
                        'type', 'Feature',
                        'geometry', ST_AsGeoJSON(realgeom)::json,
                        'properties', json_build_object(
                            'time', startguess,
                            'county', county,
                            'state', state,
                            'outage', outagen,
                            'lastchange', lastchange,
                            'cause', cause,
                            'area_geometry', ST_AsGeoJSON(COALESCE(realareageom, realgeom))::json
                        )
                    )
                    ORDER BY startguess ASC
                )
            )
            FROM power
            WHERE cwa = $1 AND active = true
        ";

        $result = pg_query_params($dbconn, $query, array('RLX'));
        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $resultArray = pg_fetch_all($result);

        // Check if we got results
        if ($resultArray && isset($resultArray[0]['json_build_object'])) {
            header('Content-Type: application/json');
            echo $resultArray[0]['json_build_object'];
        } else {
            echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
        }

        pg_free_result($result);
    } catch (Exception $e) {
        http_response_code(500);
        die('Query execution failed: ' . $e->getMessage());
    }
}

if (isset($_GET['states'])) {
    try {
        $query = "
            SELECT jsonb_build_object(
                'type', 'FeatureCollection',
                'features', jsonb_agg(features.feature)
            )
            FROM (
                SELECT jsonb_build_object(
                    'type', 'Feature',
                    'geometry', ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
                    'properties', to_jsonb(properties) - 'geom'
                ) AS feature
                FROM (
                    SELECT *
                    FROM states
                    WHERE state IN ('WV', 'VA', 'KY', 'MD', 'PA', 'OH')
                ) AS properties
            ) AS features
        ";

        $result = pg_query($dbconn, $query);
        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $resultArray = pg_fetch_all($result);

        // Set proper JSON header and handle output
        header('Content-Type: application/json');
        if ($resultArray && isset($resultArray[0]['jsonb_build_object'])) {
            echo $resultArray[0]['jsonb_build_object'];
        } else {
            echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
        }

        pg_free_result($result);
    } catch (Exception $e) {
        http_response_code(500);
        header('Content-Type: application/json');
        echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
        exit;
    }
}

if (isset($_GET['max'])) {
    if (isset($_GET['start']) && isset($_GET['end'])) {
        try {
            $starttime = getParam('start');
            $endtime = getParam('end');

            $query = "
                SELECT DISTINCT ON (county, state)
                    max(outage) as max_outage,
                    county,
                    state
                FROM (
                    SELECT DISTINCT ON (county, state, update)
                        county,
                        state,
                        SUM(outages) as outage,
                        update as time,
                        SUM(served) as served
                    FROM countyoutages
                    WHERE update > $2
                        AND update < $3
                        AND cwa = $1
                    GROUP BY county, state, update
                ) as subquery
                GROUP BY county, state
            ";

            $result = pg_query_params(
                $dbconn,
                $query,
                ['RLX', $starttime, $endtime]
            );

            if ($result === false) {
                throw new Exception('Query failed: ' . pg_last_error());
            }

            $results = [];
            while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
                $results[] = $line;
            }

            header('Content-Type: application/json');
            echo json_encode($results);

            pg_free_result($result);
        } catch (Exception $e) {
            header('Content-Type: application/json');
            http_response_code(500);
            echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
            exit;
        }
    } else {
        header('Content-Type: application/json');
        http_response_code(400);
        echo json_encode(['error' => 'Both start and end parameters are required']);
    }
}

if (isset($_GET['county'])) {
    try {
        $query = "
            WITH latest_update AS (
                SELECT MAX(update) as max_update FROM countyoutages
            )
            SELECT
                county,
                state,
                SUM(outages) as outage,
                MAX(update) as time,
                SUM(served) as served,
                ROUND(
                    CASE
                        WHEN SUM(served) > 0 THEN (SUM(outages)::FLOAT / SUM(served)) * 100
                        ELSE 0
                    END::NUMERIC, 2
                ) as perout
            FROM countyoutages
            JOIN latest_update ON countyoutages.update = latest_update.max_update
            WHERE cwa = $1
            GROUP BY county, state
            ORDER BY county, state;
        ";

        $result = pg_query_params($dbconn, $query, ['RLX']);
        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $results = [];
        while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
            $results[] = $line;
        }

        header('Content-Type: application/json');
        echo json_encode($results);

        pg_free_result($result);
    } catch (Exception $e) {
        header('Content-Type: application/json');
        http_response_code(500);
        echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
        exit;
    }
}

if (isset($_GET['countyarchive'])) {
    if (isset($_GET['start']) && isset($_GET['end'])) {
        try {
            $starttime = getParam('start');
            $endtime = getParam('end');

            $query = "
                SELECT DISTINCT ON (county, state, update)
                    county,
                    state,
                    SUM(outages) as outage,
                    update as time,
                    SUM(served) as served
                FROM countyoutages
                WHERE update > $2
                    AND update < $3
                    AND cwa = $1
                GROUP BY county, state, update
            ";

            $result = pg_query_params($dbconn, $query, ['RLX', $starttime, $endtime]);
            if ($result === false) {
                throw new Exception('Query failed: ' . pg_last_error());
            }

            $results = [];
            while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
                $results[] = $line;
            }

            header('Content-Type: application/json');
            echo json_encode($results);

            pg_free_result($result);
        } catch (Exception $e) {
            header('Content-Type: application/json');
            http_response_code(500);
            echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
            if (isset($result)) {
                pg_free_result($result);
            }
            exit;
        }
    } else {
        header('Content-Type: application/json');
        http_response_code(400);
        echo json_encode(['error' => 'Both start and end parameters are required']);
    }
}

if (isset($_GET['archivepoint'])) {
    try {
        if (!isset($_GET['start']) || !isset($_GET['end'])) {
            throw new Exception('Both start and end parameters are required');
        }

        $starttime = getParam('start');
        $endtime = getParam('end');

        $query = "
            SELECT json_build_object(
                'type', 'FeatureCollection',
                'features', json_agg(
                    json_build_object(
                        'type', 'Feature',
                        'geometry', ST_AsGeoJSON(realgeom)::json,
                        'properties', json_build_object(
                            'time', startguess,
                            'county', county,
                            'state', state,
                            'outage', outagen,
                            'lastchange', lastchange,
                            'cause', cause
                        )
                    )
                    ORDER BY startguess ASC
                )
            )
            FROM power
            WHERE cwa = $1
                AND startguess > $2
                AND lastchange < $3
        ";

        $result = pg_query_params($dbconn, $query, ['RLX', $starttime, $endtime]);
        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $resultArray = pg_fetch_all($result);

        header('Content-Type: application/json');
        if ($resultArray && isset($resultArray[0]['json_build_object'])) {
            echo $resultArray[0]['json_build_object'];
        } else {
            echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
        }

        pg_free_result($result);
    } catch (Exception $e) {
        header('Content-Type: application/json');
        $statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500;
        http_response_code($statusCode);
        echo json_encode(['error' => $e->getMessage()]);
        if (isset($result)) {
            pg_free_result($result);
        }
        exit;
    }
}

if(@$_GET['svr'] =='current') {
    $result = pg_query($dbconn,
    "SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry',  ST_AsGeoJSON(nwspoly)::json,'properties',json_build_object('issue',issue,'end',endtime,'vtec',vtec,'type',warntype)))) FROM svr where issue < now() and endtime > now()") or die('Query failed: ' . pg_last_error());
    $resultArray = pg_fetch_all($result);
    echo($resultArray[0]['json_build_object']);
    pg_free_result($result);
}

if (isset($_GET['svr']) && $_GET['svr'] === 'archive') {
    try {
        $result = null;

        if (isset($_GET['start']) && isset($_GET['end'])) {
            $starttime = getParam('start');
            $endtime = getParam('end');

            $query = "
                SELECT json_build_object(
                    'type', 'FeatureCollection',
                    'features', json_agg(
                        json_build_object(
                            'type', 'Feature',
                            'geometry', ST_AsGeoJSON(nwspoly)::json,
                            'properties', json_build_object(
                                'issue', issue,
                                'end', endtime,
                                'vtec', vtec,
                                'type', warntype
                            )
                        )
                    )
                )
            FROM svr
            WHERE issue > $1
                AND endtime < $2
            ";

            $result = pg_query_params($dbconn, $query, [$starttime, $endtime]);
        } elseif (!isset($_GET['start']) && !isset($_GET['end'])) {
            $query = "
                SELECT json_build_object(
                    'type', 'FeatureCollection',
                    'features', json_agg(
                        json_build_object(
                            'type', 'Feature',
                            'geometry', ST_AsGeoJSON(nwspoly)::json,
                            'properties', json_build_object(
                                'issue', issue,
                                'end', endtime,
                                'vtec', vtec,
                                'type', warntype
                            )
                        )
                    )
                )
            FROM svr
            WHERE issue < NOW() - INTERVAL '24 hours'
                AND endtime > NOW() - INTERVAL '24 hours'
            ";

            $result = pg_query($dbconn, $query);
        } else {
            throw new Exception('Both start and end parameters are required together');
        }

        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $resultArray = pg_fetch_all($result);

        header('Content-Type: application/json');
        if ($resultArray && isset($resultArray[0]['json_build_object'])) {
            echo $resultArray[0]['json_build_object'];
        } else {
            echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
        }

        pg_free_result($result);
    } catch (Exception $e) {
        if (isset($result)) {
            pg_free_result($result);
        }
        header('Content-Type: application/json');
        $statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500;
        http_response_code($statusCode);
        echo json_encode(['error' => $e->getMessage()]);
        exit;
    }
}

if (isset($_GET['svrpolys'])) {
    try {
        $query = "
            SELECT
                vtec,
                outagesvalid,
                polygonpop,
                outagesbuffer,
                lsrids
            FROM svr
            WHERE EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - endtime)) / 60 / 60 / 24 < 60
        ";

        $result = pg_query($dbconn, $query);
        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $results = [];
        while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
            $results[] = $line;
        }

        header('Content-Type: application/json');
        echo json_encode($results);

        pg_free_result($result);
    } catch (Exception $e) {
        if (isset($result)) {
            pg_free_result($result);
        }
        header('Content-Type: application/json');
        http_response_code(500);
        echo json_encode(['error' => $e->getMessage()]);
        exit;
    }
}

if (isset($_GET['powerids'])) {
    try {
        $powerids = $_GET['powerids'];

        // Validate input exists and isn't empty
        if (empty($powerids)) {
            throw new Exception('No power IDs provided');
        }

        // Convert comma-separated string to array and sanitize
        $poweridArray = explode(',', $powerids);
        $sanitizedIds = array_filter(array_map('intval', $poweridArray));

        if (empty($sanitizedIds)) {
            throw new Exception('Invalid power ID format');
        }

        // Prepare placeholders for the query
        $placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));

        $query = "
            SELECT
                lat,
                lon,
                lastchange,
                startguess,
                peakoutage,
                cause,
                lsrtime,
                lsrref,
                (lsrtime AT TIME ZONE 'America/New_York')::timestamp as lsrlocal
            FROM power
            WHERE id IN ($placeholders)
        ";

        $result = pg_query_params($dbconn, $query, $sanitizedIds);
        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $results = pg_fetch_all($result) ?: [];

        header('Content-Type: application/json');
        echo json_encode($results);

        pg_free_result($result);
    } catch (Exception $e) {
        if (isset($result)) {
            pg_free_result($result);
        }
        header('Content-Type: application/json');
        $statusCode = strpos($e->getMessage(), 'Invalid') !== false ? 400 : 500;
        http_response_code($statusCode);
        echo json_encode(['error' => $e->getMessage()]);
        exit;
    }
}

if (isset($_GET['poweridsgeojson'])) {
    try {
        $powerids = $_GET['poweridsgeojson'];

        if (empty($powerids)) {
            throw new Exception('No power IDs provided');
        }

        // Convert and sanitize power IDs
        $poweridArray = explode(',', $powerids);
        $sanitizedIds = array_filter(array_map('intval', $poweridArray));

        if (empty($sanitizedIds)) {
            throw new Exception('Invalid power ID format');
        }

        // Prepare placeholders
        $placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));

        $query = "
            SELECT json_build_object(
                'type', 'FeatureCollection',
                'features', json_agg(
                    json_build_object(
                        'type', 'Feature',
                        'geometry', ST_AsGeoJSON(realgeom)::json,
                        'properties', json_build_object(
                            'id', id,
                            'time', (startguess AT TIME ZONE 'UTC')::timestamp,
                            'county', county,
                            'state', state,
                            'cause', cause,
                            'outage', peakoutage,
                            'lsrtime', (lsrtime AT TIME ZONE 'UTC')::timestamp
                        )
                    ) ORDER BY startguess ASC
                )
            )
            FROM power
            WHERE id IN ($placeholders)
        ";

        $result = pg_query_params($dbconn, $query, $sanitizedIds);
        if ($result === false) {
            throw new Exception('Query failed: ' . pg_last_error());
        }

        $resultArray = pg_fetch_all($result);

        header('Content-Type: application/json');
        if ($resultArray && isset($resultArray[0]['json_build_object'])) {
            echo $resultArray[0]['json_build_object'];
        } else {
            echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
        }

        pg_free_result($result);
    } catch (Exception $e) {
        if (isset($result)) {
            pg_free_result($result);
        }
        header('Content-Type: application/json');
        $statusCode = strpos($e->getMessage(), 'Invalid') !== false ? 400 : 500;
        http_response_code($statusCode);
        echo json_encode(['error' => $e->getMessage()]);
        exit;
    }
}

if (isset($_GET['polygongeojson'])) {
    $result = null; // Initialize result to null for catch block safety
    try {
        $polygonGeoJsonString = $_GET['polygongeojson'];

        if (empty($polygonGeoJsonString)) {
            throw new Exception('No GeoJSON polygon provided', 400); // Use exception code for status
        }

        // 1. Validate if the input is valid JSON
        // We decode here primarily to check JSON validity.
        // We'll pass the *original string* to PostGIS's ST_GeomFromGeoJSON for robustness.
        $polygonGeoJson = json_decode($polygonGeoJsonString);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception('Invalid JSON format: ' . json_last_error_msg(), 400);
        }

        // 2. Optional: Basic structural validation (can rely on PostGIS for full validation)
        if (!is_object($polygonGeoJson) || !isset($polygonGeoJson->type) || !in_array($polygonGeoJson->type, ['MultiPolygon', 'Polygon'])) {
             // Allow both Polygon and MultiPolygon for flexibility? Or stick to MultiPolygon?
             // Let's allow Polygon too, as ST_Within works with both.
            // If you strictly need *only* MultiPolygon, change the check.
            throw new Exception('Input GeoJSON must be of type Polygon or MultiPolygon.', 400);
        }
        if (!isset($polygonGeoJson->coordinates) || !is_array($polygonGeoJson->coordinates)) {
            throw new Exception('Input GeoJSON must have a coordinates array.', 400);
        }

        // 3. Prepare the PostgreSQL Query using PostGIS functions
        // - ST_GeomFromGeoJSON($1): Parses the input GeoJSON string.
        // - ST_SetSRID(..., 4326): Assigns the WGS84 SRID (standard for GeoJSON). Adjust if your data uses a different SRID.
        // - ST_Within(realgeom, ...): Checks if the power outage geometry is within the provided polygon geometry.
        // - Ensure your 'realgeom' column has a spatial index for performance!
        $query = "
            SELECT json_build_object(
                'type', 'FeatureCollection',
                'features', json_agg(
                    json_build_object(
                        'type', 'Feature',
                        'geometry', ST_AsGeoJSON(realgeom)::json,
                        'properties', json_build_object(
                            'id', id,
                            'time', (startguess AT TIME ZONE 'UTC')::timestamp,
                            'county', county,
                            'state', state,
                            'cause', cause,
                            'outage', peakoutage,
                            'lsrtime', (lsrtime AT TIME ZONE 'UTC')::timestamp
                        )
                    ) ORDER BY startguess ASC -- Optional ordering
                )
            )
            FROM power
            WHERE ST_Within(realgeom, ST_SetSRID(ST_GeomFromGeoJSON($1), 4326))
        ";
        // Note: If 'realgeom' might be NULL, you might add "AND realgeom IS NOT NULL"

        // 4. Execute the query with the GeoJSON string as a parameter
        $params = [$polygonGeoJsonString];
        $result = pg_query_params($dbconn, $query, $params);

        if ($result === false) {
            // Check for specific PostGIS errors related to invalid GeoJSON input
            $pgError = pg_last_error($dbconn);
            if (strpos($pgError, 'invalid GeoJSON representation') !== false || strpos($pgError, 'ParseException') !== false || strpos($pgError, 'Invalid polygon') !== false) {
                 throw new Exception('Invalid GeoJSON geometry data provided: ' . $pgError, 400);
            } else {
                 // Throw a generic server error for other query failures
                 throw new Exception('Query failed: ' . $pgError, 500);
            }
        }

        // 5. Fetch and Output Results
        $resultArray = pg_fetch_all($result);

        header('Content-Type: application/json');
        if ($resultArray && isset($resultArray[0]['json_build_object'])) {
            // Ensure null result from json_agg (no features found) returns empty array
            $outputJson = $resultArray[0]['json_build_object'];
            $outputData = json_decode($outputJson, true);
            if (isset($outputData['features']) && $outputData['features'] === null) {
                $outputData['features'] = [];
                echo json_encode($outputData);
            } else {
                echo $outputJson; // Output the JSON directly from Postgres
            }
        } else {
            // Should ideally be handled by the check above, but as a fallback
            echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
        }

        pg_free_result($result);

    } catch (Exception $e) {
        // 6. Error Handling
        if (isset($result) && is_resource($result)) { // Check if $result is a valid resource before freeing
            pg_free_result($result);
        }
        header('Content-Type: application/json');
        // Use exception code for status if provided (>=400), default to 500
        $statusCode = ($e->getCode() >= 400 && $e->getCode() < 600) ? $e->getCode() : 500;
        http_response_code($statusCode);
        echo json_encode(['error' => $e->getMessage()]);
        exit; // Stop script execution after error
    }
}

// Close database connection when needed
if (isset($dbconn)) {
    pg_close($dbconn);
}
?>