package cz.muni.fi.pa165.soccermanager;

import cz.muni.fi.pa165.soccermanager.entity.*;
import cz.muni.fi.pa165.soccermanager.enums.Nation;
import cz.muni.fi.pa165.soccermanager.enums.PlayerState;
import cz.muni.fi.pa165.soccermanager.enums.Position;
import cz.muni.fi.pa165.soccermanager.repository.*;
import java.io.InputStreamReader;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.util.*;
import org.springframework.transaction.annotation.Transactional;

@Component
@Transactional
@RequiredArgsConstructor
public class DataInitializer implements ApplicationRunner {

    private final PlayerRepository playerRepository;
    private final ChampionshipRepository championshipRepository;
    private final TeamRepository teamRepository;
    private final LeagueRepository leagueRepository;
    private final UserRepository userRepository;
    private final MatchRepository matchRepository;
    private static final SecureRandom random = new SecureRandom();
    private final PasswordEncoder encoder;


    public void run(ApplicationArguments args) {
        int situation = 1;
        if (situation == 1) {
            initPlayers();
            initUsers();
            initChampionships();
            initLeague();
            initTeams();
            initMatches();
        } else {
            initPlayers();
            initUsers();
            initChampionships();
            initLeague2();
            initTeams();
            initMatches();
            initMatches2();
        }
    }

    private void initLeague() {
        League league = new League();
        league.setName("League of Championships");
        league.setStartDate(LocalDate.of(2022,1,1));
        league.setEndDate(LocalDate.of(2022,3,31));
        leagueRepository.save(league);

        League league2 = new League();
        league2.setName("League of Championships 2");
        league2.setStartDate(LocalDate.of(2022,6,11));
        league2.setEndDate(LocalDate.of(2022,11,1));
        leagueRepository.save(league2);
    }

    private void initLeague2() {
        League league = new League();
        league.setName("League of Championships");
        league.setStartDate(LocalDate.of(2022,1,1));
        league.setEndDate(LocalDate.of(2022,3,31));
        leagueRepository.save(league);

        League league2 = new League();
        league2.setName("League of Championships 2");
        league2.setStartDate(LocalDate.of(2022,5,1));
        league2.setEndDate(LocalDate.of(2022,11,1));
        leagueRepository.save(league2);
    }

    private void initUsers() {
        User user1 = new User();
        user1.setNickName("tita");
        user1.setPassword(encoder.encode("1234"));
        userRepository.save(user1);

        User user2 = new User();
        user2.setNickName("butaji9l");
        user2.setPassword(encoder.encode("1234"));
        userRepository.save(user2);

        User user3 = new User();
        user3.setNickName("Gonduras");
        user3.setPassword(encoder.encode("1234"));
        userRepository.save(user3);

        User user4 = new User();
        user4.setNickName("TamTen");
        user4.setPassword(encoder.encode("1234"));
        userRepository.save(user4);
    }

    private void initTeams() {
        final var real = new Team("Real Madrid","El stadione");
        final var liver = new Team("Liverpool", "London FS");
        final var bayern = new Team("Bayern Munchen", "RB FootB");
        final var sparta = new Team("AC Sparta Praha", "Letna");
        final var teams = List.of(real,liver,bayern,sparta);
        final var players = playerRepository.findAll();
        /*for(int i = 0; i < players.size(); i++) {
            final var team = teams.get(i % teams.size());
            final var player = players.get(i);
            player.setTeam(team);
        }*/

        for (int j = 0; j < teams.size(); j++) {
            for (int i = j * 13 + 1; i < players.size(); i++) {
                if (i != 0 && i % 13 == 0) {
                    break;
                }
                final var team = teams.get(j);
                final var player = players.get(i);
                player.setTeam(team);
            }
        }

        real.setUser(userRepository.getById(1L));
        liver.setUser(userRepository.getById(2L));
        real.setLeague(leagueRepository.getById(2L));
        liver.setLeague(leagueRepository.getById(2L));
        bayern.setLeague(leagueRepository.getById(2L));
        sparta.setLeague(leagueRepository.getById(2L));
        teamRepository.save(real);
        teamRepository.save(liver);
        teamRepository.save(bayern);
        teamRepository.save(sparta);
        final var empty = new Team("Empty Team", "Emp");
        empty.setLeague(leagueRepository.getById(2L));
        teamRepository.save(empty);
    }

    private void initMatches() {
        Match match1 = new Match(LocalDate.now());
        match1.setDefender(teamRepository.findById(1L).get());
        match1.setChallenger(teamRepository.findById(3L).get());
        match1.setChallengerGoals(2);
        match1.setDefenderGoals(0);
        match1.setLeague(leagueRepository.getById(1L));
        matchRepository.save(match1);

        Match match2 = new Match(LocalDate.now());
        match2.setDefender(teamRepository.getById(2L));
        match2.setChallenger(teamRepository.findById(3L).get());
        match2.setChallengerGoals(1);
        match2.setDefenderGoals(1);
        match2.setLeague(leagueRepository.getById(1L));
        matchRepository.save(match2);

        Match match3 = new Match(LocalDate.of(2020,10,10));
        match3.setDefender(teamRepository.getById(1L));
        match3.setChallenger(teamRepository.getById(4L));
        match3.setChallengerGoals(2);
        match3.setDefenderGoals(4);
        match3.setLeague(leagueRepository.getById(1L));
        matchRepository.save(match3);
    }

    private void initMatches2() {
        Match match5 = new Match(LocalDate.of(2022,6,12));
        match5.setDefender(teamRepository.getById(1L));
        match5.setChallenger(teamRepository.getById(2L));
        match5.setLeague(leagueRepository.getById(2L));
        matchRepository.save(match5);

        Match match4 = new Match(LocalDate.of(2022,6,2));
        match4.setDefender(teamRepository.getById(2L));
        match4.setChallenger(teamRepository.getById(1L));
        match4.setLeague(leagueRepository.getById(2L));
        matchRepository.save(match4);

        Match match3 = new Match(LocalDate.of(2022,5,12));
        match3.setDefender(teamRepository.getById(2L));
        match3.setChallenger(teamRepository.getById(1L));
        match3.setChallengerGoals(2);
        match3.setDefenderGoals(4);
        match3.setLeague(leagueRepository.getById(2L));
        matchRepository.save(match3);

        Match match2 = new Match(LocalDate.of(2022,5,11));
        match2.setDefender(teamRepository.getById(2L));
        match2.setChallenger(teamRepository.getById(1L));
        match2.setChallengerGoals(1);
        match2.setDefenderGoals(1);
        match2.setLeague(leagueRepository.getById(2L));
        matchRepository.save(match2);

        Match match1 = new Match(LocalDate.of(2022,5,10));
        match1.setDefender(teamRepository.getById(1L));
        match1.setChallenger(teamRepository.getById(2L));
        match1.setChallengerGoals(2);
        match1.setDefenderGoals(0);
        match1.setLeague(leagueRepository.getById(2L));
        matchRepository.save(match1);
    }

    public void initChampionships() {
        Championship champ1 = new Championship(Nation.CZECH_REPUBLIC);
        Championship champ2 = new Championship(Nation.GERMANY);
        Championship champ3 = new Championship(Nation.UNITED_KINGDOM);
        Championship champ4 = new Championship(Nation.SPAIN);

        champ1.setName("FNL");
        champ2.setName("Bundesliga");
        champ3.setName("Premier League");
        champ4.setName("La Liga");

        championshipRepository.save(champ1);
        championshipRepository.save(champ2);
        championshipRepository.save(champ3);
        championshipRepository.save(champ4);
    }

    public void initPlayers(){
        List<List<String>> players = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(
            Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream("players_dataset.csv"))))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] values = line.split(",");
                players.add(Arrays.asList(values));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        for(List<String> line : players){
            PlayerState state = randomEnum(PlayerState.class);
            if (random.nextBoolean()){
                state = PlayerState.ACTIVE;
            }
            Position position = randomEnum(Position.class);
            Player player = new Player();
            player.setName(line.get(0));
            player.setBirthDate(LocalDate.parse(line.get(1)));
            player.setHeight(Double.parseDouble(line.get(2)));
            player.setWeight(Double.parseDouble(line.get(3)));
            player.setPosition(position);
            player.setState(state);
            playerRepository.save(player);
        }
    }
    private static <T extends Enum<?>> T randomEnum(Class<T> clazz){
        int x = random.nextInt(clazz.getEnumConstants().length);
        return clazz.getEnumConstants()[x];
    }
}
