package Team5.SmartTowns;


import Team5.SmartTowns.data.*;
import Team5.SmartTowns.placeswithcoordinates.LocationsCoordinates;
import Team5.SmartTowns.placeswithcoordinates.PlacesCoordinatesRepository;
import Team5.SmartTowns.placeswithcoordinates.TownWithTrails;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;

import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.*;

import java.util.List;
//@RunWith(SpringRunner.class)
//@ContextConfiguration(classes=LocationRepository.class)
//@JdbcTest
//@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@SpringBootTest
//container?
//@Transactional
//@Import(LocationRepository.class)
public class DatabaseRepositoryTests {


    @Autowired
    private LocationRepository locationRepo;
    @Autowired
    private PlacesCoordinatesRepository placesRepo;

    @Autowired
    private TrailsRepository trailsRepo;


    @Test
    @Tag("locations")
    public void allLocationDataCanBeCalledTest(){
        List<Location> allLocations = locationRepo.getAllLocation();
        assertEquals(allLocations.get(0).getLocationName(),"MockBusiness");
    }

    @Test
    @Tag("locations")
    public void locationsCanBeAdded(){
        assertFalse(locationRepo.getAllLocation().contains("MockLocation"));
        Location location = new Location(1,"MockLocation", "Mock@Test.co.uk",
                "MockDescription","MockCaerphilly","99",false);
        locationRepo.addLocation(location);
        assertTrue(locationRepo.getAllLocation().contains("MockLocation"));
    }

    @Test
    @Tag("locations")
    public void authorisedLocationsCanBeCalled(){
        Location loc=locationRepo.getAllLocation().get(0);
        assertFalse(loc.isLocationApproved());
        assertFalse(locationRepo.getAllApprovedLocations().contains(loc));
    }

    @Test
    @Tag("locations")
    public void unauthorisedLocationsCanBeCalled(){
        Location loc=locationRepo.getAllLocation().get(0);
        assertFalse(loc.isLocationApproved());
        assertTrue(locationRepo.getAllUnapprovedLocations().contains(loc));
    }

    @Test
    @Tag("locations")
    public void nameToLocationIDTest(){
        int locID=locationRepo.nametoLocationID(locationRepo.getAllLocation().get(0).getLocationName());
        assertEquals(locID,1);
    }

    @Test
    @Tag("locations")
    public void doesLocationApprovalStatusUpdate(){
        Location loc=locationRepo.getAllLocation().get(0);
        assertFalse(loc.isLocationApproved());
        int DbID=locationRepo.nametoLocationID(loc.getLocationName());
        locationRepo.updateApprovalStatus(DbID);
        assertTrue(loc.isLocationApproved());
    }


    @Test
    public void ensureApprovedLocationsAndCoordinatesAreTheSameSize(){
        List<Location> approvedLocations = locationRepo.getAllApprovedLocations();
        List<LocationsCoordinates> coordinatesLocations = placesRepo.getAllLocationCoords();
        assertSame(approvedLocations.size(),coordinatesLocations.size() );
    }


    @Test
    @Tag("locationCoordinates")//both
    public void allLocationCoordDataCanBeCalled(){
        List<LocationsCoordinates> list = placesRepo.getAllLocationCoords();
        int locID= locationRepo.nametoLocationID("The Castle");
        assertEquals(list.get(0).getLocationID(),locID);
    }

    @Test
    @Tag("locationCoordinates")
    public void locationCoordsCanBeAdded(){//check
        LocationsCoordinates locPlc=new LocationsCoordinates(1, 51.576,-3.222);
        placesRepo.addLocationCoord(locPlc);
        System.out.println(placesRepo.getAllLocationCoords());
        assertEquals((placesRepo.getAllLocationCoords().get(placesRepo.getAllLocationCoords().size()-1).getLocationID()),(locPlc.getLocationID()));

    }

    @Test
    @Tag("locationCoordinates")
    @Tag("towns")
    public void testIfLocationCoordsWithinTownBoundary(){
        List<TownWithTrails> townsList = placesRepo.getAllTownCoords();
        assertTrue(townsList.get(0).getTownName().contains("Caerphilly"));
        LocationsCoordinates locPlc=new LocationsCoordinates(2, 99.00,-2.00);
        assertFalse(placesRepo.checkIfCoordsAreWithinTownBoundary(locPlc));
        locPlc.setLocationCoordsLat(51.576);
        locPlc.setLocationCoordsLong(-3.222);
        assertTrue(placesRepo.checkIfCoordsAreWithinTownBoundary(locPlc));
    }

    @Test
    @Tag("towns")
    public void getTownIdFromNameTest(){
        int townID = placesRepo.getTownIDFromName("Caerphilly");
        assertEquals(townID,1);
    }


    @Test
    @Tag("trails")
    public void getAllTrails(){
    List<Trail> trailList = trailsRepo.getAllTrails();
    assertEquals(trailList.get(0).getTrailName(),"Caerphilly Castle Trail");
    }
    @Test
    @Tag("trails")
    public void getTrailNameWithIdTest(){
        String trailActualName=trailsRepo.getAllTrails().get(0).getTrailName();
        String trailName = trailsRepo.getTrailNameWithID(Long.toString(trailsRepo.getAllTrails().get(0).getTrailsId()));
        assertEquals(trailName,trailActualName);
    }

    @Test
    @Tag("trails")
    public void getTrailIdWithNameTest(){
        Long trailIDActual =trailsRepo.getAllTrails().get(0).getTrailsId();
        int trailID = trailsRepo.getTrailIDFromTrailName(trailsRepo.getAllTrails().get(0).getTrailName());
        assertEquals(trailID,trailIDActual);
    }







}