import os
from flask import Flask, render_template, request, redirect, url_for, flash, Response
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from openpyxl import Workbook
from io import BytesIO

# --- KHỞI TẠO & CẤU HÌNH ---
app = Flask(__name__)

# --- CẤU HÌNH CƠ SỞ DỮ LIỆU VÀ SECRET KEY ---
app.secret_key = os.environ.get("SECRET_KEY", "Thi1234!@#$")
mysql_user = os.environ.get("MYSQL_USER", "bhnkcaet_ql")
mysql_password = os.environ.get("MYSQL_PASSWORD", "uFM9B?5kUHqQQv3~")
mysql_host = os.environ.get("MYSQL_HOST", "localhost")
mysql_database = os.environ.get("MYSQL_DATABASE", "bhnkcaet_ql")
app.config["SQLALCHEMY_DATABASE_URI"] = f"mysql+pymysql://{mysql_user}:{mysql_password}@{mysql_host}/{mysql_database}"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# --- CẤU HÌNH FLASK-LOGIN ---
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_message = "Vui lòng đăng nhập để xem trang này."
login_manager.login_message_category = "info"


# --- MODELS ---
class DanhSachThi(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    hoc_vien_id = db.Column(db.Integer, db.ForeignKey('hoc_vien.id'))
    khoa_thi_id = db.Column(db.Integer, db.ForeignKey('khoa_thi.id'))
    ket_qua = db.Column(db.String(50), default='Chưa thi')
    ghi_chu = db.Column(db.Text)
    hoc_vien = db.relationship('HocVien', back_populates='danh_sach_thi_entries')
    khoa_thi = db.relationship('KhoaThi', back_populates='danh_sach_thi_entries')

class HocVien(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    ho_ten = db.Column(db.String(100), nullable=False)
    ngay_sinh = db.Column(db.Date, nullable=True)
    anh_the = db.Column(db.String(200))
    sdt = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(100))
    ngay_dang_ky = db.Column(db.String(100))
    goi_thi = db.Column(db.String(50))
    gplx_da_co = db.Column(db.String(10))
    sv_truong = db.Column(db.String(100))
    phi = db.Column(db.Float)
    ghi_chu = db.Column(db.Text)
    trang_thai = db.Column(db.String(50), default='chưa thi')
    danh_sach_thi_entries = db.relationship('DanhSachThi', back_populates='hoc_vien', cascade="all, delete-orphan")
    thi_lai_entries = db.relationship('ThiLai', backref='hoc_vien', lazy=True, cascade="all, delete-orphan")
    tra_bang_entry = db.relationship('TraBang', backref='hoc_vien', uselist=False, cascade="all, delete-orphan")

    def get_id(self):
        return str(self.sdt)

class KhoaThi(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    ma_khoa_thi = db.Column(db.String(50), unique=True, nullable=False)
    ngay_thi = db.Column(db.Date, nullable=False)
    san_thi = db.Column(db.String(100))
    hang_thi = db.Column(db.String(10), nullable=False)
    ngay_tap_xe = db.Column(db.Date)
    danh_sach_thi_entries = db.relationship('DanhSachThi', back_populates='khoa_thi', cascade="all, delete-orphan")

class ThiLai(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    hoc_vien_id = db.Column(db.Integer, db.ForeignKey('hoc_vien.id'), nullable=False)
    ngay_rot = db.Column(db.Date)
    san_rot = db.Column(db.String(100))
    phi_thi_lai = db.Column(db.Float)
    phi_thi_lai_da_dong = db.Column(db.Boolean, default=False)
    ngay_thi_lai = db.Column(db.Date)

class TraBang(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    hoc_vien_id = db.Column(db.Integer, db.ForeignKey('hoc_vien.id'), nullable=False, unique=True)
    trang_thai_bang = db.Column(db.String(50), default='đang đợi')
    trang_thai_nhan = db.Column(db.String(50), default='chưa trả')
    ngay_tra = db.Column(db.Date)

# --- HÀM HỖ TRỢ CHO FLASK-LOGIN ---
@login_manager.user_loader
def load_user(user_id):
    return HocVien.query.filter_by(sdt=user_id).first()


# --- ROUTES ---

@app.route('/')
def index():
    hoc_vien_list = HocVien.query.order_by(HocVien.id.desc()).limit(5).all()
    khoa_thi_list = KhoaThi.query.filter(KhoaThi.ngay_thi >= datetime.today()).order_by(KhoaThi.ngay_thi.asc()).limit(5).all()
    return render_template('index.html', hoc_vien_list=hoc_vien_list, khoa_thi_list=khoa_thi_list)

# == QUẢN LÝ HỌC VIÊN ==
@app.route('/hocvien')
def hocvien_danhsach():
    search_ho_ten = request.args.get('ho_ten', '').strip()
    search_ngay_sinh = request.args.get('ngay_sinh', '').strip()
    search_sdt = request.args.get('sdt', '').strip()
    query = HocVien.query
    if search_ho_ten:
        query = query.filter(HocVien.ho_ten.ilike(f'%{search_ho_ten}%'))
    if search_ngay_sinh:
        try:
            search_date = datetime.strptime(search_ngay_sinh, '%Y-%m-%d').date()
            query = query.filter(HocVien.ngay_sinh == search_date)
        except ValueError:
            flash('Định dạng ngày sinh không hợp lệ. Vui lòng dùng YYYY-MM-DD.', 'danger')
    if search_sdt:
        query = query.filter(HocVien.sdt.ilike(f'%{search_sdt}%'))
    hoc_vien_all = query.order_by(HocVien.id.desc()).all()
    search_terms = {'ho_ten': search_ho_ten, 'ngay_sinh': search_ngay_sinh, 'sdt': search_sdt}
    return render_template('hocvien_danhsach.html', hoc_vien_all=hoc_vien_all, search_terms=search_terms)

@app.route('/hocvien/them', methods=['GET', 'POST'])
def them_hoc_vien():
    if request.method == 'POST':
        if HocVien.query.filter_by(sdt=request.form['sdt']).first():
            flash('Số điện thoại đã tồn tại!', 'danger')
            return render_template('hocvien_form.html', action="Thêm mới", hoc_vien=request.form)
        new_hv = HocVien(
            ho_ten=request.form['ho_ten'],
            ngay_sinh=datetime.strptime(request.form['ngay_sinh'], '%Y-%m-%d').date() if request.form['ngay_sinh'] else None,
            sdt=request.form['sdt'],
            email=request.form.get('email'),
            goi_thi=request.form.get('goi_thi'),
            phi=float(request.form.get('phi', 0)) if request.form.get('phi') else None,
            ghi_chu=request.form.get('ghi_chu'),
        )
        db.session.add(new_hv)
        db.session.commit()
        flash('Thêm học viên mới thành công!', 'success')
        return redirect(url_for('hocvien_danhsach'))
    return render_template('hocvien_form.html', action="Thêm mới")

@app.route('/hocvien/<int:id>')
def hocvien_chitiet(id):
    hoc_vien = HocVien.query.get_or_404(id)
    khoa_thi_da_tham_gia_ids = [entry.khoa_thi_id for entry in hoc_vien.danh_sach_thi_entries]
    khoa_thi_chua_tham_gia = KhoaThi.query.filter(KhoaThi.id.notin_(khoa_thi_da_tham_gia_ids)).all()
    return render_template('hocvien_chitiet.html', hoc_vien=hoc_vien, khoa_thi_chua_tham_gia=khoa_thi_chua_tham_gia)

@app.route('/hocvien/<int:id>/sua', methods=['GET', 'POST'])
def sua_hoc_vien(id):
    hoc_vien = HocVien.query.get_or_404(id)
    if request.method == 'POST':
        hoc_vien.ho_ten = request.form['ho_ten']
        hoc_vien.ngay_sinh = datetime.strptime(request.form['ngay_sinh'], '%Y-%m-%d').date() if request.form['ngay_sinh'] else None
        hoc_vien.sdt = request.form['sdt']
        hoc_vien.email = request.form.get('email')
        hoc_vien.goi_thi = request.form.get('goi_thi')
        hoc_vien.phi = float(request.form.get('phi', 0)) if request.form.get('phi') else None
        hoc_vien.ghi_chu = request.form.get('ghi_chu')
        hoc_vien.trang_thai = request.form.get('trang_thai')
        db.session.commit()
        flash('Cập nhật thông tin học viên thành công!', 'info')
        return redirect(url_for('hocvien_chitiet', id=id))
    return render_template('hocvien_form.html', action="Cập nhật", hoc_vien=hoc_vien)

@app.route('/hocvien/<int:id>/xoa', methods=['POST'])
def xoa_hoc_vien(id):
    hoc_vien = HocVien.query.get_or_404(id)
    db.session.delete(hoc_vien)
    db.session.commit()
    flash(f'Đã xóa vĩnh viễn học viên {hoc_vien.ho_ten}!', 'warning')
    return redirect(url_for('hocvien_danhsach'))


# == QUẢN LÝ KHÓA THI ==
@app.route('/khoathi')
def khoathi_danhsach():
    search_hang_thi = request.args.get('hang_thi', '').strip()
    search_ma_khoa_thi = request.args.get('ma_khoa_thi', '').strip()
    search_ngay_thi = request.args.get('ngay_thi', '').strip()
    search_san_thi = request.args.get('san_thi', '').strip()
    query = KhoaThi.query
    if search_hang_thi:
        query = query.filter(KhoaThi.hang_thi.ilike(f'%{search_hang_thi}%'))
    if search_ma_khoa_thi:
        query = query.filter(KhoaThi.ma_khoa_thi.ilike(f'%{search_ma_khoa_thi}%'))
    if search_ngay_thi:
        try:
            search_date = datetime.strptime(search_ngay_thi, '%Y-%m-%d').date()
            query = query.filter(KhoaThi.ngay_thi == search_date)
        except ValueError:
            flash('Định dạng ngày thi không hợp lệ. Vui lòng dùng YYYY-MM-DD.', 'danger')
    if search_san_thi:
        query = query.filter(KhoaThi.san_thi.ilike(f'%{search_san_thi}%'))
    khoa_thi_all = query.order_by(KhoaThi.ngay_thi.desc()).all()
    search_terms = {
        'hang_thi': search_hang_thi, 'ma_khoa_thi': search_ma_khoa_thi,
        'ngay_thi': search_ngay_thi, 'san_thi': search_san_thi
    }
    return render_template('khoathi_danhsach.html', khoa_thi_all=khoa_thi_all, search_terms=search_terms)

@app.route('/khoathi/them', methods=['GET', 'POST'])
def them_khoa_thi():
    if request.method == 'POST':
        ma_khoa_thi = request.form.get('ma_khoa_thi')
        if not ma_khoa_thi:
            flash("Mã khóa thi không được để trống.", 'danger')
            return render_template('khoathi_form.html', action="Tạo mới", khoa_thi=request.form)
        if KhoaThi.query.filter_by(ma_khoa_thi=ma_khoa_thi).first():
            flash(f"Mã khóa thi '{ma_khoa_thi}' đã tồn tại. Vui lòng chọn một mã khác.", 'danger')
            return render_template('khoathi_form.html', action="Tạo mới", khoa_thi=request.form)
        ngay_thi_obj = datetime.strptime(request.form['ngay_thi'], '%Y-%m-%d').date()
        ngay_tap_xe_str = request.form.get('ngay_tap_xe')
        ngay_tap_xe_obj = None
        if ngay_tap_xe_str:
            ngay_tap_xe_obj = datetime.strptime(ngay_tap_xe_str, '%Y-%m-%d').date()
        new_kt = KhoaThi(
            ma_khoa_thi=ma_khoa_thi,
            ngay_thi=ngay_thi_obj,
            san_thi=request.form['san_thi'],
            hang_thi=request.form['hang_thi'],
            ngay_tap_xe=ngay_tap_xe_obj
        )
        db.session.add(new_kt)
        db.session.commit()
        flash('Tạo khóa thi mới thành công!', 'success')
        return redirect(url_for('khoathi_danhsach'))
    return render_template('khoathi_form.html', action="Tạo mới")

@app.route('/khoathi/<int:id>')
def khoathi_chitiet(id):
    khoa_thi = KhoaThi.query.get_or_404(id)
    hoc_vien_da_tham_gia_ids = [entry.hoc_vien_id for entry in khoa_thi.danh_sach_thi_entries]
    query_hoc_vien_co_the_them = HocVien.query
    if hoc_vien_da_tham_gia_ids:
        query_hoc_vien_co_the_them = query_hoc_vien_co_the_them.filter(HocVien.id.notin_(hoc_vien_da_tham_gia_ids))
    hoc_vien_co_the_them = query_hoc_vien_co_the_them.all()
    return render_template('khoathi_chitiet.html', khoa_thi=khoa_thi, hoc_vien_co_the_them=hoc_vien_co_the_them)

@app.route('/khoathi/<int:id>/xoa', methods=['POST'])
def xoa_khoa_thi(id):
    khoa_thi = KhoaThi.query.get_or_404(id)
    db.session.delete(khoa_thi)
    db.session.commit()
    flash(f'Đã xóa vĩnh viễn khóa thi {khoa_thi.ma_khoa_thi}!', 'warning')
    return redirect(url_for('khoathi_danhsach'))


# == LOGIC NGHIỆP VỤ PHỨC TẠP ==
@app.route('/ghidanh', methods=['POST'])
def ghi_danh_hoc_vien():
    hoc_vien_id = request.form.get('hoc_vien_id')
    khoa_thi_id = request.form.get('khoa_thi_id')
    new_entry = DanhSachThi(hoc_vien_id=hoc_vien_id, khoa_thi_id=khoa_thi_id)
    hoc_vien = HocVien.query.get(hoc_vien_id)
    hoc_vien.trang_thai = 'đang thi'
    db.session.add(new_entry)
    db.session.commit()
    flash('Ghi danh học viên vào khóa thi thành công!', 'success')
    if 'from_khoathi' in request.form:
        return redirect(url_for('khoathi_chitiet', id=khoa_thi_id))
    return redirect(url_for('hocvien_chitiet', id=hoc_vien_id))

@app.route('/khoathi/<int:id>/capnhatketqua', methods=['POST'])
def cap_nhat_ket_qua(id):
    khoa_thi = KhoaThi.query.get_or_404(id)
    for entry in khoa_thi.danh_sach_thi_entries:
        ket_qua_form = request.form.get(f'ketqua_{entry.hoc_vien_id}')
        if ket_qua_form:
            entry.ket_qua = ket_qua_form
            if ket_qua_form == 'đậu':
                entry.hoc_vien.trang_thai = 'đậu'
            elif 'rớt' in ket_qua_form:
                 entry.hoc_vien.trang_thai = 'rớt'
            else:
                 entry.hoc_vien.trang_thai = 'đã thi'
    db.session.commit()
    flash('Cập nhật kết quả thi thành công!', 'info')
    return redirect(url_for('khoathi_chitiet', id=id))

@app.route('/hocvien/<int:id>/themthilai', methods=['POST'])
def them_thi_lai(id):
    hoc_vien = HocVien.query.get_or_404(id)
    new_thilai = ThiLai(
        hoc_vien_id=id,
        ngay_rot=datetime.strptime(request.form['ngay_rot'], '%Y-%m-%d').date() if request.form.get('ngay_rot') else None,
        san_rot=request.form['san_rot'],
        phi_thi_lai=float(request.form.get('phi_thi_lai', 0)) if request.form.get('phi_thi_lai') else None,
        phi_thi_lai_da_dong='phi_thi_lai_da_dong' in request.form
    )
    hoc_vien.trang_thai = 'thi lại'
    db.session.add(new_thilai)
    db.session.commit()
    flash('Đã thêm lịch sử thi lại cho học viên!', 'success')
    return redirect(url_for('hocvien_chitiet', id=id))

@app.route('/hocvien/<int:id>/capnhatbang', methods=['POST'])
def cap_nhat_bang(id):
    hoc_vien = HocVien.query.get_or_404(id)
    if not hoc_vien.tra_bang_entry:
        new_tra_bang = TraBang(hoc_vien=hoc_vien)
        db.session.add(new_tra_bang)
        db.session.commit()
    hoc_vien.tra_bang_entry.trang_thai_bang = request.form['trang_thai_bang']
    hoc_vien.tra_bang_entry.trang_thai_nhan = request.form['trang_thai_nhan']
    if request.form.get('ngay_tra'):
        hoc_vien.tra_bang_entry.ngay_tra = datetime.strptime(request.form['ngay_tra'], '%Y-%m-%d').date()
    else:
        hoc_vien.tra_bang_entry.ngay_tra = None
    if hoc_vien.tra_bang_entry.trang_thai_nhan == 'đã trả':
        hoc_vien.trang_thai = 'đã có bằng'
    db.session.commit()
    flash('Cập nhật trạng thái bằng lái thành công!', 'info')
    return redirect(url_for('hocvien_chitiet', id=id))

@app.route('/xoa-hocvien-khoi-khoa/<int:entry_id>', methods=['POST'])
def xoa_hocvien_khoi_khoa(entry_id):
    entry = DanhSachThi.query.get_or_404(entry_id)
    khoa_thi_id = entry.khoa_thi_id
    hoc_vien_name = entry.hoc_vien.ho_ten
    if len(entry.hoc_vien.danh_sach_thi_entries) == 1:
        entry.hoc_vien.trang_thai = 'chưa thi'
    db.session.delete(entry)
    db.session.commit()
    flash(f'Đã xóa học viên {hoc_vien_name} khỏi khóa thi.', 'warning')
    return redirect(url_for('khoathi_chitiet', id=khoa_thi_id))

# == HỆ THỐNG ĐĂNG NHẬP ==
@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('portal'))
    if request.method == 'POST':
        sdt = request.form.get('sdt')
        password_str = request.form.get('password')
        hoc_vien = HocVien.query.filter_by(sdt=sdt).first()
        if hoc_vien and hoc_vien.ngay_sinh:
            expected_password = hoc_vien.ngay_sinh.strftime('%d%m%Y')
            if password_str == expected_password:
                login_user(hoc_vien)
                flash('Đăng nhập thành công!', 'success')
                return redirect(url_for('portal'))
        flash('Số điện thoại hoặc mật khẩu không chính xác.', 'danger')
    return render_template('login.html')

@app.route('/portal', methods=['GET', 'POST'])
@login_required
def portal():
    if request.method == 'POST':
        current_user.ho_ten = request.form.get('ho_ten')
        current_user.sdt = request.form.get('sdt')
        current_user.email = request.form.get('email')
        current_user.anh_the = request.form.get('anh_the')
        db.session.commit()
        flash('Cập nhật thông tin thành công!', 'success')
        return redirect(url_for('portal'))
    return render_template('portal.html')

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('Bạn đã đăng xuất.', 'info')
    return redirect(url_for('login'))

# == XUẤT FILE EXCEL ==
@app.route('/khoathi/<int:id>/export')
def export_khoathi_excel(id):
    khoa_thi = KhoaThi.query.get_or_404(id)
    workbook = Workbook()
    sheet = workbook.active
    sheet.title = khoa_thi.ma_khoa_thi
    headers = ['STT', 'Họ Tên', 'Ngày sinh', 'Ngày Thi', 'Sân Thi', 'Kết Quả', 'Ghi chú']
    sheet.append(headers)
    for index, entry in enumerate(khoa_thi.danh_sach_thi_entries):
        if entry.hoc_vien:
            stt = index + 1
            ho_ten = entry.hoc_vien.ho_ten
            ngay_sinh = entry.hoc_vien.ngay_sinh.strftime('%d-%m-%Y') if entry.hoc_vien.ngay_sinh else ''
            ngay_thi = khoa_thi.ngay_thi.strftime('%d-%m-%Y')
            san_thi = khoa_thi.san_thi
            ket_qua = entry.ket_qua
            ghi_chu = entry.ghi_chu if entry.ghi_chu else ''
            sheet.append([stt, ho_ten, ngay_sinh, ngay_thi, san_thi, ket_qua, ghi_chu])
    
    # --- SỬA LỖI fileno ---
    mem_file = BytesIO()
    workbook.save(mem_file)
    mem_file.seek(0)
    
    filename = f"danh_sach_thi_{khoa_thi.ma_khoa_thi}.xlsx"
    
    return Response(
        mem_file.read(),
        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        headers={"Content-Disposition": f"attachment;filename={filename}"}
    )

# --- CHẠY ỨNG DỤNG ---
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True, port=5001)

