package model;

import java.sql.*;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.LocalDateTime;
import java.util.stream.Collectors;
import javafx.application.Platform;
import javafx.scene.control.Alert;

public class DataManager {
    private static DataManager instance;
    private static final String DB_URL = "jdbc:sqlite:db/dbuml.db3";
    private static Connection connection;
    
    private Map<String, Goods> goodsMap;
    private List<String> suppliers;
    private Map<String, Integer> inventory;
    private List<OperationLog> operationLogs;

    private DataManager() {
        goodsMap = new HashMap<>();
        suppliers = new ArrayList<>();
        inventory = new HashMap<>();
        operationLogs = new ArrayList<>();
        initializeData();
    }

    public static DataManager getInstance() {
        if (instance == null) {
            instance = new DataManager();
        }
        return instance;
    }

    private void initializeData() {
        // 从数据库加载数据
        loadDataFromDatabase();
    }

    private void loadDataFromDatabase() {
        String url = "jdbc:sqlite:db/dbuml.db3";

        try (Connection conn = DriverManager.getConnection(url)) {
            // 加载商品数据
            loadGoods(conn);
            // 加载供应商数据
            loadSuppliers(conn);
            // 加载库存数据
            loadInventory(conn);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void loadGoods(Connection conn) throws SQLException {
        String sql = "SELECT * FROM inbound_records";
        try (Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                String id = rs.getString("goods_id");
                String name = rs.getString("goods_id"); // Assuming goods_id is also the name in inbound_records
                String specification = ""; // Not available in inbound_records
                String unit = ""; // Not available in inbound_records
                double price = 0; // Not available in inbound_records
                String category = ""; // Not available in inbound_records
                String remark = rs.getString("remark");

                Goods goods = new Goods(id, name, 0, remark);
                goodsMap.put(id, goods);
            }
        }
    }

    private void loadSuppliers(Connection conn) throws SQLException {
        String sql = "SELECT supplier FROM inbound_records";
        try (Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                String supplier = rs.getString("supplier");
                if (!suppliers.contains(supplier)) {
                    suppliers.add(supplier);
                }
            }
        }
    }

    private void loadInventory(Connection conn) throws SQLException {
        String sql = "SELECT goods_id, SUM(quantity) as total_quantity FROM inbound_records GROUP BY goods_id";
        try (Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                String goodsId = rs.getString("goods_id");
                int totalQuantity = rs.getInt("total_quantity");
                inventory.put(goodsId, totalQuantity);
            }
        }
    }

    public void addGoods(Goods goods) {
        goodsMap.put(goods.getId(), goods);
        if (!inventory.containsKey(goods.getId())) {
            inventory.put(goods.getId(), 0);
        }
    }

    public static List<InventoryReport> generateInventoryReport() {
        List<InventoryReport> reports = new ArrayList<>();
        String url = "jdbc:sqlite:db/dbuml.db3";

        try (Connection conn = DriverManager.getConnection(url);
             Statement stmt = conn.createStatement()) {

            String sql = "SELECT " +
                    "    w1.id, " +
                    "    w1.goods_id as goods_name, " +
                    "    w1.quantity as total_quantity, " +
                    "    w1.supplier, " +
                    "    w1.remark " +
                    "FROM warehouse w1 " +
                    "ORDER BY w1.id";  // 不再使用GROUP BY，直接显示所有记录

            ResultSet rs = stmt.executeQuery(sql);
            while (rs.next()) {
                String goodsId = rs.getString("id");
                String goodsName = rs.getString("goods_name");
                int totalQuantity = rs.getInt("total_quantity");
                String supplier = rs.getString("supplier");
                String remark = rs.getString("remark");

                reports.add(new InventoryReport(goodsId, goodsName, totalQuantity, supplier, remark));
            }

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

        return reports;
    }

    public Goods getGoods(String id) {
        return goodsMap.get(id);
    }

    public List<Goods> getAllGoods() {
        return new ArrayList<>(goodsMap.values());
    }

    public List<String> getSuppliers() {
        return new ArrayList<>(suppliers);
    }

    public int getStock(String goodsId) {
        return inventory.getOrDefault(goodsId, 0);
    }

    public void updateStock(String goodsId, int quantity) {
        inventory.put(goodsId, inventory.getOrDefault(goodsId, 0) + quantity);
    }

    public Map<String, Integer> getAllStock() {
        return new HashMap<>(inventory);
    }

    public void addOperationLog(String operationType, String operationTarget, String operator, String details) {
        System.out.println("开始添加操作日志...");
        System.out.println("类型: " + operationType);
        System.out.println("目标: " + operationTarget);
        System.out.println("详情: " + details);
        
        String id = String.format("LOG%014d", System.currentTimeMillis());
        LocalDateTime now = LocalDateTime.now();
        
        String sql = "INSERT INTO operation_logs (id, operation_type, operation_target, operator, operation_time, details) " +
                    "VALUES (?, ?, ?, ?, ?, ?)";
                    
        synchronized (DataManager.class) {
            try (PreparedStatement pstmt = getConnection().prepareStatement(sql)) {
                pstmt.setString(1, id);
                pstmt.setString(2, operationType);
                pstmt.setString(3, operationTarget);
                pstmt.setString(4, operator);
                pstmt.setString(5, now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                pstmt.setString(6, details);
                
                int result = pstmt.executeUpdate();
                if (result > 0) {
                    OperationLog log = new OperationLog(id, operationType, operationTarget, 
                                                      operator, now, details);
                    operationLogs.add(log);
                    System.out.println("操作日志已添加: " + details);
                }
                
            } catch (SQLException e) {
                System.err.println("添加操作日志失败: " + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    public List<OperationLog> getOperationLogs() {
        List<OperationLog> logs = new ArrayList<>();
        String sql = "SELECT * FROM operation_logs ORDER BY operation_time DESC";
        
        synchronized (DataManager.class) {
            try (Statement stmt = getConnection().createStatement();
                 ResultSet rs = stmt.executeQuery(sql)) {
                
                while (rs.next()) {
                    try {
                        String id = rs.getString("id");
                        String operationType = rs.getString("operation_type");
                        String operationTarget = rs.getString("operation_target");
                        String operator = rs.getString("operator");
                        String timeStr = rs.getString("operation_time");
                        String details = rs.getString("details");

                        LocalDateTime operationTime = LocalDateTime.parse(timeStr);
                        
                        OperationLog log = new OperationLog(
                            id, operationType, operationTarget,
                            operator, operationTime, details
                        );
                        logs.add(log);
                        
                        System.out.println("读取到日志: " + operationType + " - " + details);
                    } catch (Exception e) {
                        System.err.println("解析日志记录失败: " + e.getMessage());
                        e.printStackTrace();
                    }
                }
                
                System.out.println("总共读取到 " + logs.size() + " 条日志记录");
                
            } catch (SQLException e) {
                System.err.println("查询操作日志失败: " + e.getMessage());
                e.printStackTrace();
            }
        }
        
        return logs;
    }

    public List<OperationLog> getFilteredOperationLogs(LocalDateTime startDate, LocalDateTime endDate, String operationType) {
        List<OperationLog> logs = new ArrayList<>();
        String url = "jdbc:sqlite:db/dbuml.db3";
        
        StringBuilder sql = new StringBuilder("SELECT * FROM operation_logs WHERE 1=1");
        List<Object> params = new ArrayList<>();
        
        if (startDate != null && endDate != null) {
            sql.append(" AND operation_time BETWEEN ? AND ?");
            params.add(startDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            params.add(endDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }
        
        if (!"全部".equals(operationType)) {
            sql.append(" AND operation_type = ?");
            params.add(operationType);
        }
        
        sql.append(" ORDER BY operation_time DESC");
        
        try (Connection conn = DriverManager.getConnection(url);
             PreparedStatement pstmt = conn.prepareStatement(sql.toString())) {
            
            // 设置参数
            for (int i = 0; i < params.size(); i++) {
                pstmt.setObject(i + 1, params.get(i));
            }
            
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                OperationLog log = new OperationLog(
                    rs.getString("id"),
                    rs.getString("operation_type"),
                    rs.getString("operation_target"),
                    rs.getString("operator"),
                    LocalDateTime.parse(rs.getString("operation_time")),
                    rs.getString("details")
                );
                logs.add(log);
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
            showAlert("错误", "读取操作日志失败：" + e.getMessage());
        }
        
        return logs;
    }


    public void addGoodsToDatabase(Goods goods) {
        String url = "jdbc:sqlite:db/dbuml.db3";
        String sql = "INSERT INTO warehouse (id, goods_id, quantity, supplier, inbound_time, operator, remark) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?)";
        try (Connection conn = DriverManager.getConnection(url);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {

            // Generate a unique ID for each record
            String recordId = "REC" + System.currentTimeMillis();
            pstmt.setString(1, recordId);

            pstmt.setString(2, goods.getId());
            pstmt.setInt(3, goods.getQuantity());
            pstmt.setString(4, goods.getSupplier());

            // Format LocalDateTime to ISO_LOCAL_DATE_TIME format
            DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
            String inboundTimeString = goods.getInboundTime().format(formatter);
            pstmt.setString(5, inboundTimeString);

            pstmt.setString(6, goods.getOperator());
            pstmt.setString(7, goods.getRemark());

            pstmt.executeUpdate();

            // Synchronize memory data
            addGoods(goods);

            // 将操作日志类型从"新增"改为"修改"
            System.out.println("正在添加操作日志: " + "修改" + " - " + "修改货物: " + goods.getName());
            addOperationLog("修改", goods.getId(), "系统管理员", "修改货物: " + goods.getName());
        } catch (SQLException e) {
            e.printStackTrace();
            showAlert("错误", "添加货物失败：" + e.getMessage());
        }
    }


    public void updateGoodsInDatabase(Goods goods) {
        String url = "jdbc:sqlite:db/dbuml.db3";
        String sql = "UPDATE warehouse SET quantity = ?, supplier = ?, inbound_time = ?, operator = ?, remark = ? WHERE goods_id = ? ORDER BY inbound_time DESC LIMIT 1";
        try (Connection conn = DriverManager.getConnection(url);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {

            pstmt.setInt(1, goods.getQuantity());
            pstmt.setString(2, goods.getSupplier());
            pstmt.setString(3, goods.getInboundTime().toString());
            pstmt.setString(4, goods.getOperator());
            pstmt.setString(5, goods.getRemark());
            pstmt.setString(6, goods.getId());

            pstmt.executeUpdate();
            System.out.println("正在添加操作日志: " + "更新" + " - " + "更新货物: " + goods.getName());
            addOperationLog("更新", goods.getId(), "系统管理员", "更新货物: " + goods.getName());
        } catch (SQLException e) {
            e.printStackTrace();
            showAlert("错误", "更新货物失败：" + e.getMessage());
        }
    }


    protected static void showAlert(String title, String content) {
        Platform.runLater(() -> {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle(title);
            alert.setHeaderText(null);
            alert.setContentText(content);
            alert.showAndWait();
        });
    }

    public List<String> getAllCategories() {
        return goodsMap.values().stream()
                .map(Goods::getCategory)
                .distinct()
                .collect(Collectors.toList());
    }

    private static synchronized Connection getConnection() throws SQLException {
        if (connection == null || connection.isClosed()) {
            connection = DriverManager.getConnection(DB_URL);
            // 启用WAL模式，提高并发性能
            try (Statement stmt = connection.createStatement()) {
                stmt.execute("PRAGMA journal_mode=WAL");
            }
        }
        return connection;
    }

    public static void closeConnection() {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
