package database;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import obejcts.Ingredient;
import obejcts.Recepie;

public class Database {

	private static final String USERNAME = "recepieUser";
	private static final String PASSWORD = "v.FV-ssZPzVyev28";
	private static final String DATABASE = "recept";
	private static final String URL = "jdbc:mysql://nordh.xyz:3306/";
	Database instance;

	Connection conn;

	public void addIngredientToRecepie(int recepieId, Ingredient ingredient) {
		String insertIngredientSql = "INSERT INTO ingredient(name) VALUES (?)";
		String linkIngredientToRecepieSql = "INSERT INTO recepieIngredientLink(recepieId, ingredientId, amount, measurement) VALUES (?,?,?,?)";
		int ingredientId = -1;
		try (PreparedStatement ingredientStat = getConnection().prepareStatement(insertIngredientSql,
				Statement.RETURN_GENERATED_KEYS);
				PreparedStatement linkStat = getConnection().prepareStatement(linkIngredientToRecepieSql);) {
			ingredientId = getIngredient(ingredient.getName());
			if (ingredientId < 0) {
				ingredientStat.setString(1, ingredient.getName());
				ingredientStat.execute();

				ResultSet key = ingredientStat.getGeneratedKeys();

				while (key.next()) {
					ingredientId = Integer.parseInt(key.getString(1));
				}
			}

			linkStat.setInt(1, recepieId);
			linkStat.setInt(2, ingredientId);
			linkStat.setString(3, ingredient.getAmount());
			linkStat.setString(4, ingredient.getMeasurement());

			linkStat.execute();

		} catch (SQLException e) {
			System.out.println("Failing sql " + linkIngredientToRecepieSql + " " + recepieId + " "
					+ ingredientId + " " + ingredient.getAmount() + " " + ingredient.getMeasurement() + System.lineSeparator()
					+ " OR " + System.lineSeparator() + insertIngredientSql + " " + ingredient.getName());
			e.printStackTrace();
		}
	}

	public void addRecepieStep(int recepieId, int stepNumber, String stepDesc) {
		String sql = "INSERT INTO recepieSteps(recepieId, stepNumber, text) VALUES (?,?,?) ON DUPLICATE KEY UPDATE text = ?";

		try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
			stat.setInt(1, recepieId);
			stat.setInt(2, stepNumber);
			stat.setString(3, stepDesc);
			stat.setString(4, stepDesc);

			stat.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public Recepie getGetRecepieByTitle(String recepieTitle) {
		Recepie result = new Recepie();
		String sql = "SELECT * FROM recepie WHERE name = ?";

		try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
			stat.setString(1, recepieTitle);

			ResultSet rs = stat.executeQuery();

			while (rs.next()) {
				result.setId(rs.getInt("id"));
				result.setName(rs.getString("name"));
				result.setDescription(rs.getString("description"));
				result.setDifficulty(rs.getString("difficulty"));
				result.setTime(rs.getString("time"));
				result.setUrl(rs.getString("url"));
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}

		return result;
	}

	public int getIngredient(String name) {
		String sql = "SELECT id FROM ingredient WHERE name = ?";
		int result = -1;
		try (PreparedStatement stat = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
			stat.setString(1, name);
			ResultSet rs = stat.executeQuery();

			while (rs.next()) {
				result = rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return result;
	}

	public List<Recepie> getRecepiesWithoutImage(int count) {
		List<Recepie> result = new ArrayList<>();

		String sql = "SELECT * FROM recepie WHERE id NOT IN (SELECT recepieId FROM recepieImage) LIMIT ?";

		try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
			stat.setInt(1, count);
			ResultSet rs = stat.executeQuery();

			while (rs.next()) {
				result.add(new Recepie(rs.getInt("id"), rs.getString("url"), rs.getString("name"), rs.getString("time"),
						rs.getString("description"), rs.getString("difficulty")));
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}

		return result;
	}

	public int insertRecepie(Recepie newRecepie) {
		String sql = "INSERT INTO recepie(url, name, time, description, difficulty) VALUES (?,?,?,?,?)";

		int newId = -1;
		try (PreparedStatement stat = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
			stat.setString(1, newRecepie.getUrl());
			stat.setString(2, newRecepie.getName());
			stat.setString(3, newRecepie.getTime());
			stat.setString(4, newRecepie.getDescription());
			stat.setString(5, newRecepie.getDifficulty());

			stat.execute();

			ResultSet rs = stat.getGeneratedKeys();

			while (rs.next()) {
				newId = Integer.parseInt(rs.getString(1));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return newId;
	}

	public void saveRecepieImage(int recepieId, File imageFile) {
		String sql = "INSERT INTO recepieImage (recepieId, image) VALUES (?,?)";
		try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
			stat.setInt(1, recepieId);
			stat.setBlob(2, new FileInputStream(imageFile));
			stat.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private Connection getConnection() {
		if (conn == null) {
			try {
				conn = DriverManager.getConnection(URL + DATABASE, USERNAME, PASSWORD);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return conn;
	}
}
