/*
 * RiskScape™ Copyright New Zealand Institute for Earth Science Limited
 * (Earth Sciences New Zealand) is distributed for research purposes only
 * under the terms of AGPLv3.
 *
 * RiskScape™ Copyright 2026 New Zealand Institute for Earth Science
 * Limited (Earth Sciences New Zealand). All rights reserved. Source code
 * available under the AGPLv3.
 * 
 * This program is free software: you can redistribute it and/or modify it under
 *  the terms of the GNU Affero General Public License as published by the Free
 *  Software Foundation, either version 3 of the License, or (at your option) any
 *  later version.
 * 
 * This program is distributed for RESEARCH PURPOSES ONLY, in the hope that it will
 * be useful for research and education initiatives.
 * 
 * If you are not a researcher, or you are a researcher who wishes to use this
 * program on terms other than AGPLv3 (including those who wish to restrict the
 * distribution of any source code created using this program), please contact:
 * https://riskscape.org.nz
 * 
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Affero General Public License for more details.  You should have received a copy
 * of the GNU Affero General Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 * 
 * By way of summary only, under the AGPLv3:
 *     • Permissions of this strongest copyleft license are conditioned
 *       on making available complete source code of licensed works and
 *       modifications, which include larger works using a licensed work,
 *       under the same license.
 *     • Copyright and license notices must be preserved.
 *     • Contributors provide an express grant of patent rights.
 *     • When a modified version is used to provide a service over a
 *       network, the complete source code of the modified version must be made
 *       available.
 */
package nz.org.riskscape.engine.cli.tests;

import static org.junit.Assert.*;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;

import org.junit.Test;

public class GL1303_IntersectionIndexCutting extends BaseModelRunCommandTest {

  String getSampleOnePipeline(String options) {
    return """
    input('sa2') ->
    group(select: {to_coverage(*, {OPTIONS}) as coverage}) ->
    join.rhs

    input('land-parcels', name: 'land_parcel') ->
    join(on: true) ->
    select({land_parcel.id, sample_one(land_parcel.geom, coverage).SA22023_V1_00 as name}) ->
    sort(by: [id, name]) as sorted
    """.replace("OPTIONS", options);
  }

  @Test
  public void canUseTheCutOptionTo_sample_one_CoveragesWithoutImpactingResults() throws Exception {
    populateProject(stdhome());

    evalCommand.pipelineFile = getSampleOnePipeline("");
    evalCommand.runnerOptions.format = "csv";
    Object problems = evalCommand.run();

    // for reasons that I can only imagine extend to hating myself, I made the eval command return errors, rather than
    // throw them, so dump this out so we can see failures in the test
    System.out.println(problems);

    assertTrue(Files.exists(getTempDirectory().resolve("sorted.csv")));

    evalCommand.pipelineFile = getSampleOnePipeline("intersection_cut: true");
    problems = evalCommand.run();

    System.out.println(problems);

    assertTrue(Files.exists(getTempDirectory().resolve("sorted-1.csv")));

    assertFilesTheSame("sorted.csv", "sorted-1.csv", 14654);
  }

  String getSampleAllPipeline(String options) {
    return """
    input('sa2') ->
    group(select: {to_coverage(*, {OPTIONS}) as coverage}) ->
    join.rhs

    input('land-parcels', name: 'land_parcel') ->
    join(on: true) ->
    # do some buffering to make sure we get a few cases where parcels are across different sas
    select({land_parcel.id, sample(buffer(land_parcel.geom, 1000), coverage) as sampled}) ->
    unnest(sampled) ->
    select({id, sampled.sampled.SA22023_V1_00 as name}) ->
    sort(by: [id, name]) as sorted
    """.replace("OPTIONS", options);
  }

  @Test
  public void canUseTheCutOptionTo_sample_CoveragesWithoutImpactingResults() throws Exception {
    populateProject(stdhome());

    evalCommand.pipelineFile = getSampleAllPipeline("");
    evalCommand.runnerOptions.format = "csv";
    Object problems = evalCommand.run();

    System.out.println(problems);

    evalCommand.pipelineFile = getSampleAllPipeline("intersection_cut: true");
    problems = evalCommand.run();

    System.out.println(problems);

    assertFilesTheSame("sorted.csv", "sorted-1.csv", 97765);
  }


  private void assertFilesTheSame(String lhs, String rhs, long expectedLines) throws IOException {
    Path lhsPath = getTempDirectory().resolve(lhs);
    Path rhsPath = getTempDirectory().resolve(rhs);


    Iterator<String> lhsIterator = Files.newBufferedReader(lhsPath).lines().iterator();
    Iterator<String> rhsIterator = Files.newBufferedReader(rhsPath).lines().iterator();

    long lineCounter = 0;
    while (lhsIterator.hasNext() || rhsIterator.hasNext()) {
      String lhsLine = lhsIterator.hasNext() ? lhsIterator.next() : null;
      String rhsLine = rhsIterator.hasNext() ? rhsIterator.next() : null;

      assertEquals(lhsLine, rhsLine);
      lineCounter++;
    }

    assertEquals(expectedLines, lineCounter);

  }


}
