package de.antco.projekt.dao;

import de.antco.projekt.Database;
import de.antco.projekt.model.ServiceItem;
import de.antco.projekt.model.WorkOrderDetails;
import de.antco.projekt.model.WorkOrderItem;

import java.math.BigDecimal;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class WorkOrderDao {
    public int createWorkOrder(int vehicleId, String note, Map<Integer, Integer> items) throws SQLException {
        if (items.isEmpty()) {
            throw new IllegalArgumentException("Keine Positionen gewählt");
        }
        try (Connection con = Database.getConnection()) {
            con.setAutoCommit(false);
            try {
                int orderId = insertOrder(con, vehicleId, note);
                insertItems(con, orderId, items);
                con.commit();
                return orderId;
            } catch (SQLException e) {
                con.rollback();
                throw e;
            } finally {
                con.setAutoCommit(true);
            }
        }
    }

    private int insertOrder(Connection con, int vehicleId, String note) throws SQLException {
        String sql = "INSERT INTO work_order(vehicle_id, note) VALUES (?, ?) RETURNING id";
        try (PreparedStatement ps = con.prepareStatement(sql)) {
            ps.setInt(1, vehicleId);
            ps.setString(2, note);
            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                return rs.getInt("id");
            }
            throw new SQLException("Vorgang konnte nicht gespeichert werden");
        }
    }

    private void insertItems(Connection con, int orderId, Map<Integer, Integer> items) throws SQLException {
        String sql = "INSERT INTO work_order_item(work_order_id, service_item_id, quantity) VALUES (?, ?, ?)";
        try (PreparedStatement ps = con.prepareStatement(sql)) {
            for (Map.Entry<Integer, Integer> entry : items.entrySet()) {
                ps.setInt(1, orderId);
                ps.setInt(2, entry.getKey());
                ps.setInt(3, entry.getValue());
                ps.addBatch();
            }
            ps.executeBatch();
        }
    }

    public List<WorkOrderDetails> fetchAllDetails() throws SQLException {
        Map<Integer, List<WorkOrderItem>> itemMap = loadItems();
        List<WorkOrderDetails> result = new ArrayList<>();
        String sql = "SELECT wo.id, wo.note, wo.created_at, p.name AS person_name, " +
                "v.brand, v.model, v.plate FROM work_order wo " +
                "JOIN vehicle v ON wo.vehicle_id = v.id " +
                "JOIN person p ON v.person_id = p.id ORDER BY wo.created_at DESC";
        try (Connection con = Database.getConnection();
             PreparedStatement ps = con.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {
            while (rs.next()) {
                int id = rs.getInt("id");
                List<WorkOrderItem> items = itemMap.getOrDefault(id, new ArrayList<>());
                BigDecimal total = items.stream()
                        .map(WorkOrderItem::getTotalPrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                result.add(new WorkOrderDetails(
                        id,
                        rs.getString("person_name"),
                        rs.getString("brand") + " " + rs.getString("model") + " (" + rs.getString("plate") + ")",
                        rs.getTimestamp("created_at").toLocalDateTime(),
                        rs.getString("note"),
                        items,
                        total
                ));
            }
        }
        return result;
    }

    private Map<Integer, List<WorkOrderItem>> loadItems() throws SQLException {
        Map<Integer, List<WorkOrderItem>> map = new HashMap<>();
        String sql = "SELECT woi.id, woi.work_order_id, woi.quantity, si.id AS service_id, si.title, si.price " +
                "FROM work_order_item woi JOIN service_item si ON woi.service_item_id = si.id";
        try (Connection con = Database.getConnection();
             PreparedStatement ps = con.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {
            while (rs.next()) {
                ServiceItem item = new ServiceItem(rs.getInt("service_id"), rs.getString("title"), rs.getBigDecimal("price"));
                WorkOrderItem orderItem = new WorkOrderItem(rs.getInt("id"), rs.getInt("work_order_id"), item, rs.getInt("quantity"));
                map.computeIfAbsent(orderItem.getWorkOrderId(), id -> new ArrayList<>()).add(orderItem);
            }
        }
        return map;
    }
}
