package dao.impl;

import dao.LeaveRequestDAO;
import model.ApprovalStatus;
import model.LeaveRequest;
import model.Student;
import util.DatabaseUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class LeaveRequestDAOImpl implements LeaveRequestDAO {
    @Override
    public int insert(LeaveRequest request) {
        String sql = "INSERT INTO leave_requests (student_id, start_time, end_time, status, " +
                    "duration, location, reason_type, reason_detail, is_leaving_city, " +
                    "request_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            
            stmt.setInt(1, request.getStudent().getId());
            stmt.setTimestamp(2, new Timestamp(request.getStartTime().getTime()));
            stmt.setTimestamp(3, new Timestamp(request.getEndTime().getTime()));
            stmt.setString(4, request.getStatus().name());
            stmt.setDouble(5, request.getDuration());
            stmt.setString(6, request.getLocation());
            stmt.setString(7, request.getReasonType());
            stmt.setString(8, request.getReasonDetail());
            stmt.setBoolean(9, request.isLeavingCity());
            stmt.setTimestamp(10, new Timestamp(request.getRequestTime().getTime()));
            
            int affectedRows = stmt.executeUpdate();
            if (affectedRows == 0) {
                return 0;
            }

            try (ResultSet generatedKeys = stmt.getGeneratedKeys()) {
                if (generatedKeys.next()) {
                    request.setId(generatedKeys.getInt(1));
                }
            }
            return affectedRows;
        } catch (SQLException e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public int deleteById(int id) {
        String sql = "DELETE FROM leave_requests WHERE id = ?";
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setInt(1, id);
            return stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public int update(LeaveRequest request) {
        String sql = "UPDATE leave_requests SET student_id = ?, start_time = ?, " +
                    "end_time = ?, status = ?, duration = ?, location = ?, " +
                    "reason_type = ?, reason_detail = ?, is_leaving_city = ?, " +
                    "request_time = ? WHERE id = ?";
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setInt(1, request.getStudent().getId());
            stmt.setTimestamp(2, new Timestamp(request.getStartTime().getTime()));
            stmt.setTimestamp(3, new Timestamp(request.getEndTime().getTime()));
            stmt.setString(4, request.getStatus().name());
            stmt.setDouble(5, request.getDuration());
            stmt.setString(6, request.getLocation());
            stmt.setString(7, request.getReasonType());
            stmt.setString(8, request.getReasonDetail());
            stmt.setBoolean(9, request.isLeavingCity());
            stmt.setTimestamp(10, new Timestamp(request.getRequestTime().getTime()));
            stmt.setInt(11, request.getId());
            
            return stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public LeaveRequest findById(int id) {
        String sql = "SELECT lr.*, s.id as student_id, s.student_id as student_number, " +
                    "s.name, s.class_name, s.contact, s.college, s.major " +
                    "FROM leave_requests lr " +
                    "JOIN students s ON lr.student_id = s.id " +
                    "WHERE lr.id = ?";
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setInt(1, id);
            ResultSet rs = stmt.executeQuery();
            
            if (rs.next()) {
                return mapResultSetToLeaveRequest(rs);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<LeaveRequest> findAll() {
        List<LeaveRequest> requests = new ArrayList<>();
        String sql = "SELECT lr.*, s.id as student_id, s.student_id as student_number, " +
                    "s.name, s.class_name, s.contact, s.college, s.major " +
                    "FROM leave_requests lr " +
                    "JOIN students s ON lr.student_id = s.id";
        try (Connection conn = DatabaseUtil.getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            
            while (rs.next()) {
                requests.add(mapResultSetToLeaveRequest(rs));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return requests;
    }

    @Override
    public List<LeaveRequest> findByStudentId(int studentId) {
        List<LeaveRequest> requests = new ArrayList<>();
        String sql = "SELECT lr.*, s.id as student_id, s.student_id as student_number, " +
                    "s.name, s.class_name, s.contact, s.college, s.major " +
                    "FROM leave_requests lr " +
                    "JOIN students s ON lr.student_id = s.id " +
                    "WHERE lr.student_id = ? ORDER BY lr.request_time DESC";
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setInt(1, studentId);
            ResultSet rs = stmt.executeQuery();
            
            while (rs.next()) {
                requests.add(mapResultSetToLeaveRequest(rs));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return requests;
    }

    @Override
    public List<LeaveRequest> findByStatus(ApprovalStatus status) {
        List<LeaveRequest> requests = new ArrayList<>();
        String sql = "SELECT lr.*, s.id as student_id, s.student_id as student_number, " +
                    "s.name, s.class_name, s.contact, s.college, s.major " +
                    "FROM leave_requests lr " +
                    "JOIN students s ON lr.student_id = s.id " +
                    "WHERE lr.status = ? ORDER BY lr.request_time DESC";
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setString(1, status.name());
            ResultSet rs = stmt.executeQuery();
            
            while (rs.next()) {
                requests.add(mapResultSetToLeaveRequest(rs));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return requests;
    }

    @Override
    public int updateStatus(int requestId, ApprovalStatus status, String comment) {
        String sql = "UPDATE leave_requests SET status = ?, approval_comment = ?, approval_time = ? WHERE id = ?";
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setString(1, status.name());
            stmt.setString(2, comment);
            stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
            stmt.setInt(4, requestId);
            
            return stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            return 0;
        }
    }

    private LeaveRequest mapResultSetToLeaveRequest(ResultSet rs) throws SQLException {
        LeaveRequest request = new LeaveRequest();
        request.setId(rs.getInt("id"));
        request.setLocation(rs.getString("location"));
        request.setStartTime(rs.getTimestamp("start_time"));
        request.setEndTime(rs.getTimestamp("end_time"));
        request.setStatus(ApprovalStatus.valueOf(rs.getString("status")));
        request.setDuration(rs.getDouble("duration"));
        request.setReasonType(rs.getString("reason_type"));
        request.setReasonDetail(rs.getString("reason_detail"));
        request.setLeavingCity(rs.getBoolean("is_leaving_city"));
        request.setRequestTime(rs.getTimestamp("request_time"));
        
        // 设置学生信息
        Student student = new Student();
        student.setId(rs.getInt("student_id"));
        student.setStudentId(rs.getString("student_number"));
        student.setName(rs.getString("name"));
        student.setClassName(rs.getString("class_name"));
        student.setContact(rs.getString("contact"));
        student.setCollege(rs.getString("college"));
        student.setMajor(rs.getString("major"));
        request.setStudent(student);

        Timestamp approvalTime = rs.getTimestamp("approval_time");
        if (approvalTime != null) {
            request.setApprovalTime(approvalTime);
        }

        return request;
    }
}
